Hands on x86

Vulnerability

• A bug in a binary that can be leveraged by an exploit

 

Exploit (as a noun)

• Specially crafted data that utilizes vulnerabilities to force the binary into doing something unintended • By this definition, exploits are not explicitly malware

 

0day

• A previously unknown or unpatched vulnerability that can be used by an exploit • An 0day can also be an exploit using the unpatched vuln

Double for 2017

The market

The right bugs (vulnerabilities) found in binaries can be used by exploits to hijack code execution

 

Once code execution is achieved by an attacker...

• Gain privileged information

• Download or install malware

• Steal data

• Wreak any sort of havoc on the machine

• Designed in 1969-1972 for writing UNIX operating system

• Imperative systems programming language

• Very fast, compiled language

• Extremely fine control over memory and the machine

• Compared to modern languages, C is considered a ‘low level’ language

C

What your name?

#include <stdio.h>

int main()
{
    char buffer[20];
    printf("%s", "Enter your name");
    
    scanf("%s", buffer);
    
    printf("%s %s", "Hello ", buffer);
    
    return 0;
}

My name's 

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  • memory corruption
  • Over-riding return address? - A.C.E.

The x86 Assembly

x86-64 vs x86-32 ?

There's way too much information in the matrix. You get used to it, though. Your brain does the translating. I don't even see the code. All I see is blonde, brunette, redhead.” -Cypher, The Matrix

Available registers

  • EAX EBX ECX EDX - General purpose registers.
  • ESP - Stack pointer, “top” of the current stack frame (lower memory).
  • EBP - Base pointer, “bottom” of the current stack frame (higher memory).
  • EIP - Instruction pointer, pointer to the next instruction to be executed by the CPU.

 

  • EFLAGS - stores flag bits
  • ZF - zero flag, set when result of an operation equals zero.
  • CF - carry flag, set when the result of an operation is too large/small.
  • SF - sign flag, set when the result of an operation is negative
mov ebx, eax

• Move the value in eax to ebx

 

mov eax, 0xDEADBEEF

• Move 0xDEADBEEF into eax

 

mov edx, DWORD PTR [0x41424344]

• Move the 4-byte value at address 0x41424344 into edx

 

mov ecx, DWORD PTR [edx]

• Move the 4-byte value at the address in edx, into ecx

 

mov eax, DWORD PTR [ecx+esi*8]

• Move the value at the address ecx+esi*8 into eax

sub edx, 0x11

• edx = edx - 0x11; // subtracts 0x11 from edx

add eax, ebx

• eax = eax + ebx; // add eax and ebx, storing value in eax  

inc edx

• edx++; // increments edx

dec ebx

• ebx--; // decrements ebx  

xor eax, eax

• eax = eax ^ eax; // bitwise xor eax with itself (zeros eax)

push ebx

• Subtract 4 from the stack pointer to move it towards lower memory (zero,) and copy the value in EBX on top of the stack.

sub esp, 4
mov DWORD PTR [esp], ebx  

 

pop ebx

• Copy the value off the top of the stack and into EBX, the add 4 to the stack pointer to move it towards higher memory (0xFFFFFFFF)

mov ebx, DWORD PTR [esp]
add esp, 4
call some_function

• Calls the code at some_function. We need to push the return address onto the stack, then branch to some_function

push eip
mov eip, some_function ; not actually valid

 

ret

• Used to return from a function call. Pops the top of the stack to

eip

pop eip ; not actually valid

 

nop

• ‘no operation’ - does nothing

Human decompiler

How it trickles down

Running

Reverse Engineering Domain

Static

Dynamic

The elusive Stack

How does stack memory allocation work?

int main()
{
    char myname[] = "Mohan"; // 5 bytes
    int myage = 19, date;  // 8 bytes
    
    date = predict_death_date(myname, myage, "07/04/2017"); // 8 + 4 + 10
    
    printf("%d", date); // 4 bytes

    return 0;
}
    
    

Practical x86

By Mohan Agrawal

Practical x86

  • 268