Sec24 – Introduktion till Intel X86 – Instruktioner

Av: Oscar Andersson, Sec24,
Rev 1.0 2013-07-16

OBS:  Följande guide är för utbildningssyfte enbart och får absolut inte användas för olagliga ändamål.

Innan du påbörjar denna guide är det rekommenderat att du läser igenom och förstår “Introduktion till Intel X86“.

1. NOP

Den första instruktionen är NOP som står för No Operation. Det är ett kommando som i princip inte gör någonting utan kan enbart användas för att justera bytes eller sätta en fördröjningstid. Illasinnade hackare kan använda NOP-instruktionen för att göra sin exploits mer tillförlitliga. Kuriosa: “The one-byte NOP instruction is an alias mnemonic for the XCHG (E)AX, (E)AX instruction.”.

2. PUSH

PUSH lägger till ett Word, Doubleword eller Quardword på stacken. I exemplen nedan använder vi enbart DWORD (4 byte). Kan antingen vara ett immediate value eller ett värde i ett register. Push-instuktionen minskar automatiskt stackpekaren,esp, med 4. Grafisk representation nedan:

Sec24-sec-24-hur-hackar-man-introduktion Intel X86 C programmering assembler reverse engineering 10

 3. POP

POP tar bort ett värde från stacken. Tar ett DWORD från stacken, stoppar det i ett register och ökar ESP med 4.

Sec24-sec-24-hur-hackar-man-introduktion Intel X86 C programmering assembler reverse engineering 11

4. CALL

CALLs uppgift är att överlåta kontrollen till en annan funktion på ett sätt att kontrollen senare kan återupptas där den slutade. Detta görs genom att adressen för nästa instruktion pushas på stacken, används av RET när proceduren genomförts, och byter sedan ut EIP, instruktionspekaren, till adressen som tilldelats instruktionen. Destinationsadressen kan sedan vara specificerad antingen genom en Absolut address, exempelvis 0x0012FF8C, eller Relative Address där nästa instruktion ska sluta på 0x50 exempelvis.

5. RET

RET menas med Return from Procedure, “Tillbaka från funktionen”. Finns i två olika former:

– POPa toppen av stacken till EIP (glöm inte att POP ökar ESP, Stackpekaren). Instruktionen skrivs normalt ut som “ret” och används normalt av cdecl-funktioner. Kallas även för en plain return.

– POPa toppen av stacken till EIP och addera ett fast antal bytes till ESP. Skrivs ut som “ret 0x8” eller “ret 0x20” exempelvis och används ofta av stdcall-funktioner.

6. MOV

Står för MOVE, flytta, och kan göra följande förflyttningar:
– Register till register
– minne till register, register till minne
– direkt till register, direkt till minne
ALDRIG minne till minne. Minnesadresser ges ut i r/m32-form.

7. LEA

LEA är en akronym för Load Effective Address (Ladda Effektiv Adress). Används ofta för pekararitmetik (pointer arithmetic) och ibland för vanlig aritmetik (Till exempel hämta adressen för en viss array plats 4 utan att gå in i minnet). Använder r/m32 formen men är undantaget från regeln att hakparenteser [] innebär att värdet ska behandlas som en minnesadress, för att sedan hämta det faktiska värdet på den hämtade adressen.

Exempel: ebx = 0x2, edx = 0x1000

lea eax, [edx+ebx*2]

eax = 0x1004, inte värdet från minnesadressen 0x1004.

8. ADD och SUB

Adderar och subtraherar precis som det låter. Destinationsoperanden (Destination operand)  kan vara r/m32 eller register. Källoperanden (Source operand) kan vara r/m32, register eller en immediate. Källa och destination får inte vara rm/32 därför att det skulle kunna tillåta minne till minne transferering, vilket inte är tillåtet i X86. Utvärderar operationen som om det vore signerad och osignerad data och sätter lämpliga flaggor. Instruktionen modifierar flaggorna: OF, SF, ZF, AF, PF, och CF.

Exempel:

add esp, 8 (Adderar esp med 8)

sub eax, [ebx*2] ([] innebär att vi går in i minnet (Undantag LEA). Tar först minnesadressen och multiplicerar denna med två. Hämtar sedan värdet på minnesadressen och subtraherer eax med detta värde.)