From aldeid
Jump to navigation Jump to search
You are here
x86 Assembly


Compiler, linker, loader

This section/article is being written and is therefore not complete.
Thank you for your comprehension.

Flow of execution

The execution flow or control flow corresponds to the logic of a program.

The following code is an extract of a malware named kinject.exe:

// Inject a process that's already running
if(strcmp(argv[3], "--runtime")==0 || strcmp(argv[3], "-r")==0)
    //Get Process Id from exe name
    if(argc>3 && strcmp(argv[4],"--resolve") == 0)
        ProcPid = GetPidByName(argv[1]);
        if(ProcPid==0) DispError("GetPidByName failed.", DIE);
        printf("Process %s has PID: %d\n", argv[1], ProcPid);
        ProcPid = atol(argv[1]);
    HANDLE hProc;
    hProc = OpenProcess(PROCESS_ALL_ACCESS, true,ProcPid);
        printf("OpenProcess failed, triggering DebugPrivilege...");
        if(LoadPrivilege()!=1) DispError("DebugPrivilege : load FAILED", DIE);
        printf(" OK");

    hProc = OpenProcess(PROCESS_ALL_ACCESS, true,ProcPid);
    if(hProc==NULL) DispError("Still can't open process. (Sure it exists ?)", DIE);
    printf("Injecting DLL %s in Pid: %d...", argv[2], ProcPid);
    InjectDll(hProc, argv[2]);
    printf(" OK\n");


    return 0;

The if and else statements show that the program will take 2 different paths depending on the result of the if test.

In a disassembler, execution flow can be visualized in a tool like IDA-Pro:


The x86 architecture

Central Processing Unit (CPU)
  • The Control Unit gets instructions to be executed from RAM using the Instruction Pointer (EIP).
  • The Arithmetic Logic Unit executes instructions fetched from RAM by the Control Unit and stores the results in Registers or in RAM.
  • Registers are the CPU's basic data storage units used to save time so that the CPU doesn't need to access RAM
Main Memory (RAM)
  • Data: section of the memory that contains the program initial values (static, global)
  • Code: controls what the program does and how it does
  • Heap: dynamic memory: create (allocate) new values , destroy (free) values
  • Stack: local variables and function parameters
Input/Output (I/O) devices hard drive, keyboard, monitor, ...

The stack



High level logic (functions, if-else, switch, loop, AND, OR)


WORDs Size
(in bytes)
(in bits)
Max value Example (registers)
BYTE (DB) 1 byte 8 bits 255 AL, BL, CL
WORD (DW) 2 bytes 16 bits 65,535 AX, BX, CX
DWORD (DD) 4 bytes 32 bits 4,294,967,295 EAX, EBX, ECX
QWORD (DQ) 8 bytes 64 bits 18,446,744,073,709,551,615
  • In 32-bit: EDX:EAX
  • In 64-bit: RAX


Type Value Result
dd 2DF01h 0002DF01
dw 0 0000
dw 0 0000
db 0C0h, 6 dup(0), 46h C000-0000000046

The resulting CLSID is 2DF01-0000-0000-C000-000000000046

Type Value Result
dd 0D30C1661h D30C1661
dw 11D0h 11D0
db 8Ah, 3Eh, 0, 0C0h, 4Fh, 0C9h, 0E2h, 6Eh 8A3E00C04FC9E26E

The resulting IID is D30C1661-CDAF-11D0-8A3E-00C04FC9E26E.

For a complete list of Windows Data Types, you can refer to this link.

Signed vs unsigned numbers


Unsigned numbers can only be positive. All bits are used for the number itself.

Binary  Decimal        Binary  Decimal
------  -------        ------  -------
 0000      0            1000      8 
 0001      1            1001      9
 0010      2            1010     10
 0011      3            1011     11
 0100      4            1100     12
 0101      5            1101     13
 0110      6            1110     14
 0111      7            1111     15


Signed numbers can be negative or positive. Signed numbers use the left-most bit as a flag to identify the sign (0 = positive / 1 = negative).

Signed positive        Signed negative
---------------        ---------------
Binary  Decimal        Binary  Decimal
------  -------        ------  -------
 0000      0            1000     -0 
 0001      1            1001     -1
 0010      2            1010     -2
 0011      3            1011     -3
 0100      4            1100     -4
 0101      5            1101     -5
 0110      6            1110     -6
 0111      7            1111     -7

Memory addressing modes

direct, indirect, immediate, register, memory, implied

The accesses can be:

mov eax, 0xEBFE
mov eax, dword_1234
mov eax, [0x1234]
mov eax, [ebx+ecx*2+4]

There are several addressing modes to access memory:

mov eax, 0xEBFE
Copies the value 0xEBFE into the EAX register
mov eax, edx
Copies the content of EDX into EAX
mov eax, dword_0x1234
mov eax,[0x1234]
Copies the 4 bytes (32 bits) at the memory location 0x1234 into EAX
implied (use of base, scaled index and displacement)
mov eax,[ebp+ecx*2+4]
Copies the 4 bytes (32 bits) at the memory location specified by the result of the equation ebp+ecx*2+4 into EAX

Base, scaled index and displacement example

C source Assembly
#include <stdio.h>

int main()
    char *weekdays[7] = {
    int daynum;
    printf ("Day number? ");
    scanf("%d", &daynum);
    if (daynum > 0 && daynum < 8) {
        printf("Day #%d of week is %s\n", daynum, weekdays[daynum-1]);
    } else {
        printf("Invalid value!\n");
.text:0804847C                 mov     [ebp+weekdays], offset aMonday ; "monday"
.text:08048483                 mov     [ebp+weekdays+4], offset aTuesday ; "tuesday"
.text:0804848A                 mov     [ebp+weekdays+8], offset aWednesday ; "wednesday"
.text:08048491                 mov     [ebp+weekdays+0Ch], offset aThursday ; "thursday"
.text:08048498                 mov     [ebp+weekdays+10h], offset aFriday ; "friday"
.text:0804849F                 mov     [ebp+weekdays+14h], offset aSaturday ; "saturday"
.text:080484A6                 mov     [ebp+weekdays+18h], offset aSunday ; "sunday"
.text:080484AD                 sub     esp, 0Ch
.text:080484B0                 push    offset format   ; "Day number? "
.text:080484B5                 call    _printf
.text:080484BA                 add     esp, 10h
.text:080484BD                 sub     esp, 8
.text:080484C0                 lea     eax, [ebp+daynum]
.text:080484C3                 push    eax
.text:080484C4                 push    offset aD       ; "%d"
.text:080484C9                 call    ___isoc99_scanf
.text:080484CE                 add     esp, 10h
.text:080484D1                 mov     eax, [ebp+daynum]
.text:080484D4                 test    eax, eax
.text:080484D6                 jle     short invalid
.text:080484D8                 mov     eax, [ebp+daynum]
.text:080484DB                 cmp     eax, 7
.text:080484DE                 jg      short invalid
.text:080484E0                 mov     eax, [ebp+daynum]
.text:080484E3                 sub     eax, 1          ; eax = daynum - 1
.text:080484E6                 mov     edx, [ebp+eax*4+weekdays]
.text:080484EA                 mov     eax, [ebp+daynum]
.text:080484ED                 sub     esp, 4
.text:080484F0                 push    edx
.text:080484F1                 push    eax
.text:080484F2                 push    offset aDayDOfWeekIsS ; "Day #%d of week is %s\n"
.text:080484F7                 call    _printf


The x86 Intel architecture is little endian whereas network data is big endian.

Here is an example for an IPv4 (4 bytes): 0x366410AC

0x36 0x64 0x10 0xAC
---- ---- ---- ----
 |    |    |    |__ 0xAC = 172
 |    |    |_______ 0x10 =     16
 |    |____________ 0x64 =        100
 |_________________ 0x36 =            54


Decryption routine


Pages in this category

Pages in category "Architecture/x86-assembly"

The following 71 pages are in this category, out of 71 total.