Afgedankte code

EN NL TR

Het vorige fragment

De fragmentenindex

Het volgende fragment

Over RIP-relatieve adressering

Iets dat iedereen interesseert is de nieuwe RIP-relatieve adresseringsmodus van de x64-systemen.  Het is de default-adresseringsmode van 64-bit programma's.

RIP-relatieve adresering houdt in dat je geheugen aanspreekt relatief ten opzichte van het RIP-register (of relatief van EIP indien de 32-adresseringsoperand gebruikt werd).

Alle bugs die gaan over ml64.exe zijn voor versie 8.00.2207, Ik heb geen weet van andere versies.  De laatste versie die ik geprobeerd heb is versie 8.00.50215.44 en die heeft de beschreven foutjes niet.

Ik ga er vanuit dat je kennis hebt van assemblerprogrammatie, dit artikel is niet echt voor beginnelingen.

NOTA: de auteur van diStorm64 heeft me op een (nogal zware) fout gewezen in dit artikel, ik wil hem langs deze weg nogmaals bedanken :)



Hoe RIP/EIP relatieve adressering werkt in 32-bit-mode

In 32-bit-programma's kan je dit niet doen :

Je zal iets zoals dit moeten doen :


How RIP/EIP relative addressing works in 64-bit mode

In 64-bit-programma's kan je dit wel schrijven :

NOTA: ML64 is dom en laat ons niet toe het bovenstaande te schrijven!

Het is ook leuk om te weten dat RIP in feite naar het einde van de huidige instructie wijst, dus RIP zal altijd naar de volgende offset wijzen ongeacht het aantal (nuteloze) operands je aan de opcode hebt toegevoegd.


In verband met nuteloze operands in 64-bit-mode

I hope you know what operands, opcodes etc. are :).

In 64-bit mode the segment operands are ignored and if you encode multiple REX bytes (see the AMD64/EM64T manuals) only the last REX byte is taken into account, so if you write a disassembler or if you are writing a program to emulate/protect/encrypt 64-bit executables, you need to take this behaviour into account.  The maximum size of an instruction taking all operand etc into account is 15 bytes (atleast that's what I read in the AMD64 programmer's manual).


Absolute adressering in 64-bit-mode

Absolute adressering was niet geïmplementeerd in de oudere versies van ml64.  De laatste versie (8.00.50215.44) die ik geprobeerd heb, deed het wel! :

Je moest dit schrijven om het zelfde resultaat te bekomen :

Door een bug assembleerden oudere versies van ML64 dit niet correct :


RIP/EIP-relatieve adressering in ML64

Ik heb slecht nieuws, ML64, Microsoft's Macro Assembler voor x64-systemen, geeft ons geen volledige controle over RIP-relatieve adressering.  We kunnen noch RIP, noch EIP gebruik als een parameter in een adressering.

Maar, als we een variable gebruiken dan zal de linker dit automatisch naar een RIP-relatieve adressering omzetten.  Dit houdt in dat als je tweemaal dezelfde instructie schrijft, deze binair niet hetzelfde zal zijn :

NOTA: de actuele binaire uitvoer hangt af van de locatie van de code en van de locatie van de variable "test" tijdens het linken.


RIP/EIP-relatieve adressering in FASM

Good nieuws!  RIP-relatieve adressering werkt met flat assembler.


RIP/EIP-relative addressing in YASM

Good nieuws!  RIP-relatieve adressering werkt met YASM.


Een testprogramma dat de oude en nieuwe techniek van het bekomen van RIP (EIP) demonstreert

Ik heb volgende testprogramma geschreven dat zal nakijken of de volgende instructie een "nop" is, als RIP correct bekomen werd dan zal het verwijzen naar deze "nop"-instructie.  Ik heb sommige instructies moeten hardcoden omdat ML64 het manueel gebruik van RIP niet ondersteund (!) (Gezipte broncode en executable) :

Om deze source code in iets uitvoerbaar te toveren doe je :

ml64 XXX.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main

(er vanuit gaande dat kernel32.lib en user32.lib in dezelfde directory staan als ml64.exe)

en

(waar XXX de naam is van het assemblerbestand)
 


Een testprogramma dat de volgende instructie wijzigt via RIP-relatieve adressering

Ik heb onderstaande testprogramma  geschreven om het aanpassen van de volgende instructie via RIP te demonstreren (Gezipte broncode en executable), dit programma vereist ML64 :

Om dit programma te compileren en te linken start je ml64 als volgt :

ml64 XXX.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main

(er vanuit gaande dat kernel32.lib en user32.lib in dezelfde directory staan als ml64.exe)

en

(waar XXX de naam is van het assemblerbestand)
 


Extra: Een andere bug in ML64

NOTA: deze bug komt niet langer voor in de nieuwere ML64-versies!

Tijdens het testen van ML64 had ik nog een bug gevonden : : ML64 liet ons toe 16-bit adressering-instructies in te voeren maar ze werden wel uitgevoerd door hun binaire overeenkomende 32-bit instructies, bijvoorbeeld :

is binair hetzelfde als :

 

Het vorige fragment

De fragmentenindex

Het volgende fragment