攻防世界 Pwn pwn-100

本文详细分析了一个64位程序的栈溢出漏洞,通过IDA逆向工程揭示了程序结构,并利用DynELF库泄露libc地址。通过精心构造的payload,实现了控制程序流程,最终获取了系统的控制权。过程中涉及了x64下的函数调用机制、ROP链构造及/bin/sh的注入技巧。

1.题目下载地址

点击下载

2.checksec

在这里插入图片描述

64位程序,目前还什么都看不出看来,直接拉近IDA看看

3.IDA分析

在这里插入图片描述

在这里插入图片描述

  • 整个程序由3个嵌套的程序组成

  • 我们可以看到sub_40063D是主要的程序,接受单个字符并存储到传入的参数a1所指向的空间之内

  • 同时分析sub_40068E发现sub_40063D中a1就是sub_40068E中的v1

  • 并且v1的栈空间大小就只有0x40,而sub_40063D接受的输入量有0x200个字节,这样就存在栈溢出漏洞了。

  • 在这里插入图片描述

  • 通过分析函数列表,里面有puts这个库函数,联系pwntools中的DynELF,我们可以将libc的地址泄露出来,再来构造ROP

  • 64位程序构造ROP与32位程序不一样
    x86中,函数调用是直接将参数压栈,需要用的时候直接将参数放在栈上,调用的函数就能直接取得参数并运算。如图:
    在这里插入图片描述

调用read函数的时候,参数直接放入栈中,但是x64的程序不一样,x64的gcc优化了x86的传参方式,x64程序设立了几个寄存器李存放参数,调用函数的时候先向寄存器之中放参数,当参数的数量大于寄存器的时候,才会向栈中放参数。
在这里插入图片描述

这是本题中的sub_40068E函数,可以看到其参数是放在rdi和esi两个寄存器之中的,这就是两种结构的不一样,如果要在x64的程序之中构造rop,我们就必须向寄存器存放参数。
在这里插入图片描述

可看出只要rbx和rbp不相同就会跳转回去循环,这是我们不允许的,我们需要控制程序流ret到我们需要的地方去,故预先设置rbx=0,rbp=1即可让程序继续执行我们构造的ROP链。故可以构造payload1=‘a’*0x48+p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main) 泄露puts的地址,从而确定libc和libcbase
在这里插入图片描述
经过查找发现不存在/bin/sh,需要自己写入,gdb中vmmap发现0x601000为基址的地址可写,到ida查找,选择0x601040进行写入
在这里插入图片描述

4.exp

from pwn import *
# context.log_level = 'debug'
io = remote(
### 关于攻防世界PWN-100目的解答 #### 解决方案概述 对于攻防世界PWN-100目,通常涉及的是基础的缓冲区溢出攻击。这类目旨在测试参赛者对Linux防护机制的理解程度以及绕过这些保护措施的能力。常见的技术包括但不限于返回导向编程(Return-Oriented Programming, ROP)、重定向到已知位置的shellcode执行(ret2shellcode)或是利用动态链接库中的函数实现系统命令调用(ret2libc)[^1]。 #### 技术细节 当面对没有启用地址空间布局随机化(ASLR)且未开启不可执行堆栈(NX bit off)的情况时,可以直接采用`ret2shellcode`的方式解决问。此方法要求选手能够找到足够的空间放置自定义的shellcode,并通过控制EIP指向这段代码来完成最终的目标——通常是打开一个远程shell连接给攻击者[^3]。 如果遇到开启了NX位但是禁用了位置独立可执行文件(PIE),那么可以考虑使用`ret2libc`策略。这种方法依赖于将返回地址设置为标准C库(glibc)内的某个有用功能的位置,比如system()函数,从而间接地触发所需的恶意操作而无需注入新的机器码片段。 针对具体环境下的不同情况,还需要掌握诸如IDA Pro这样的反汇编工具来进行二进制分析工作;同时熟悉GDB调试技巧以便更好地理解程序内部逻辑并定位潜在的安全漏洞所在之处。 ```python from pwn import * # 连接到远程服务 conn = remote('challenge.ctf.games', PORT) # 发送payload前先接收初始消息 print(conn.recvline()) # 构造payload offset = 64 # 假设偏移量为64字节 junk = b'A' * offset return_address = pack('<I', 0xdeadbeef) # 替换为目标地址 exploit_payload = junk + return_address # 发送payload conn.send(exploit_payload) # 接收响应数据 result = conn.recvall() print(result.decode()) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

==Microsoft==

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

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

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

打赏作者

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

抵扣说明:

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

余额充值