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