2016-08-08 72 views
3

Ich bin ein sehr gelegentlicher Benutzer der Montage. Also brauche ich Hilfe von einem Experten, um ein kleines Stück Code zu entschlüsseln, mit dem ich umgehen muss.Versammlung decode für x64 JMP Anweisung

0000: 48 ff 25 61 57 07 00 rex.W jmp QWORD PTR [rip+0x75761]  # 0x75768 
0007: cc      int3 

Dies ist ein Memory-indirekte Sprung zu einer 8-Byte/64-Bit-Adresse an rip+0x75761 gehalten, so dass die absoluten Adresse wird das Sprungziel geladen von 0007 + 0x75761 = 0x75768 ist, nicht wahr?

+2

Ja, übrigens ist der REX.W redundant. – harold

+0

Danke! Leider ist der Code auf einer x64 Windows 10-Installation eines Kunden für eine der user32.dll-Funktionen. Keine Ahnung, wie dieser Code dort angekommen ist, weil es kein Standard-MS-Code ist. Also muss ich dafür sorgen. – user118708

+0

Sind Sie sicher, dass dies 64-Bit-Maschinencode ist? Wenn es als 32-Bit-Code demontiert wurde, wäre das Byte "0x48" ein "dec" oder "inc". ('dec eax' denke ich). –

Antwort

2

Dies ist eine Standard-Tail-Call-Sequenz auf x86-64, wie sie durch den Microsoft-Compiler erzeugt werden würde.

Ja, wie Sie gesagt haben, es ist ein indirekter Sprung zu einer 64-Bit-Speicheradresse, 0x75768. An dem Punkt, an dem dieser Code ausgeführt wird, ist gleich 7, also rip + 0x75761 == == 0x75768. Der Code überträgt die Kontrolle bedingungslos an die Anweisungen unter der Adresse 0x75768.

Die nachfolgende ist nur Polsterung, dient aber auch als Ziegelmauer. Die Ausführung sollte wegen des unbedingten Zweigs in der vorherigen Anweisung niemals diesen Punkt erreichen. Wenn dies der Fall wäre, würde die CPU einfangen, da dies der "Unterbrechungs" -Interrupt ist.

Wie für die REX.W-Präfix, Harold ist technisch korrekt, dass es unnötig ist, aber nicht aus dem Grund, die Sie vielleicht denken. Etwas überraschend, wenn ein indirekter Sprung durch ein Register auf x86-64 verwendet wird, benötigt Windows das Präfix REX.W, um sicherzustellen, dass der Stack-Abbau erfolgreich ist. Der Stapelabwicklungscode verwendet dies intern als Signal. Ross Ridge hat an excellent answer über den Zweck von REX-Präfix-JMP-Anweisungen in Windows x64 geschrieben.

Dies ist in diesem Fall nicht unbedingt notwendig, da es sich um einen indirekten Sprung mit einem IP-relativen Operanden handelt, aber der Compiler gibt es anscheinend trotzdem ab. Seine Logik für die Handhabung ist wahrscheinlich nicht so komplex, und vielleicht erzeugt es diesen Code immer aus Konsistenzgründen. Oder vielleicht ist die offizielle Dokumentation nicht umfassend, wie genau der Stapelabwicklungscode implementiert wird. Lieber sicher als Nachsicht, da es in einem zusätzlichen REX.W-Präfix keinen wirklichen Nachteil gibt.

+0

REX.W wurde von Microsoft in ihrem Windows 10-Jubiläumsupdate zur WIn32-API hinzugefügt. Auch wenn es optional ist, wird es Teil des Betriebssystems. – user118708

+0

Ich glaube nicht, dass ich verstehe, was Sie sagen, @user. Wie fügen Sie der API einen Assembly-Opcode hinzu? Wenn Sie sagen, dass der Code, der mit Windows 10 ausgeliefert wird, diese Kodierung verwendet, dann ja, sicherlich. Alle Versionen von 64-Bit-Windows haben und haben immer. Keine 32-Bit-Versionen von Windows, einschließlich der 32-Bit-Version von Windows 10 Anniversary Edition. Und der Grund, warum es hier "optional" ist, ist, dass es für IP-relative Kodierungen eigentlich nicht notwendig ist. Sie benötigen es nur für indirekte Kodierungen. Das hat sich in Windows 10 nicht geändert. Das Abwickeln des Stapels funktioniert immer noch auf die gleiche Weise. –

+0

Moment mal, es ist kein relativer Sprung. Es wird ein RIP-relativer Adressierungsmodus verwendet, um einen absoluten 64-Bit-Zeiger zu laden. Das ist viel anders als 'REX.W = 1 jmp rel32' als Rückruf ohne Indirection. –