CTF之多元线性方程
字数 1304 2025-08-22 18:37:22
CTF之多元线性方程解析与实战教学
1. 应用初步分析
1.1 应用结构分析
- 应用入口:
com.example.assemgogogo.MainActivity - 关键组件:
- WebView组件(占据整个界面,可见)
- 隐藏的EditText(输入框)
- 隐藏的Button(检查按钮)
- 隐藏的TextView(结果显示)
1.2 关键逻辑流程
- 加载本地库
gogogo(System.loadLibrary("gogogo")) - 调用
sayHello方法获取URL - WebView加载获取的URL
- 点击按钮时调用
check_key方法验证输入
2. URL探索
2.1 关键方法定位
sayHello方法位于native库中- 使用IDA分析
armeabi-v7a/libgogogo.so
2.2 IDC脚本解密URL
#include <idc.idc>
static main() {
auto addr = 0x2d28;
auto i;
for(i = 0; i != 21; ++i) {
Message("%c", Byte(addr + i) ^ 0x66);
}
}
解密结果:http://127.0.0.1:8000
3. 服务端处理函数分析
3.1 JNI_OnLoad分析
- 初始化时对data段中34291字节数据进行异或解密(key=0x67)
- 创建线程监听socket连接
- 收到连接后发送解密后的HTTP响应数据包
3.2 IDC脚本解密数据
#include <idc.idc>
static main() {
auto addr = 0x4004;
auto i = 34291;
while(i) {
--i;
Message("%c", Byte(addr++) ^ 0x67);
}
}
解密结果为HTML页面,包含WebAssembly代码
4. WebAssembly分析
4.1 关键逻辑
- 输入必须为32位长度
- 调用
set_input_flag_len设置长度 - 调用
set_input_flag逐个设置字符 - 调用
check_key验证输入
4.2 提取WebAssembly二进制
import array, struct
hexstring = "\x00\x61\x73\x6D\x01\x00\x00\x00\x01\x1B\x05\x60\x00\x00\x60\x04\x7F\x7F\x7F\x7F\x01\x7F\x60\x02\x7F\x7F\x01\x7F\x60\x01\x7F\x01\x7F\x60\x00\x01\x7F...\x6C\x61\x67\x0A\x12\x73\x65\x74\x5F\x69\x6E\x70\x75\x74\x5F\x66\x6C\x61\x67\x5F\x6C\x65\x6E\x0B\x09\x63\x68\x65\x63\x6B\x5F\x6B\x65\x79\x0C\x03\x78\x78\x78"
f = open('data.bin', 'wb')
f.write(hexstring)
f.close()
4.3 转换为C代码
使用wasm2c工具:
wasm2c.exe data.bin -o test.c
4.4 编译为可分析对象
gcc -c test.c -o test.o
5. 核心验证逻辑分析
5.1 双重加密流程
- 第一重加密:对输入字符进行异或处理
- 第二重验证:32元线性方程组验证
5.2 32元线性方程组解法
使用Z3求解器解决:
from z3 import *
# 定义32个变量
v5 = Int('m53')
v6 = Int('m52')
v7 = Int('m51')
v8 = Int('m50')
[...省略部分变量定义...]
v36 = Int('m54')
# 创建求解器
s = Solver()
# 添加方程约束
s.add(And(
45*v5 + 248*v6 + 20*v7 + 67*v8 + 90*v9 + 135*v10 + 106*v11 + 112*v12 + 40*v13 + 231*v14 + 153*v15 + 233*v16 + 19*v17 + 188*v18 + 232*v19 + 127*v20 + 15*v21 + 67*v22 + 50*v23 + 161*v24 + 103*v25 + 144*v26 + 81*v27 + 126*v28 + 240*v29 + 124*v30 + 194*v31 + 92*v32 + 108*v33 + 111*v34 + 174*v35 + 48*v36 == 359512,
[...省略其他方程...]
244*v5 + 196*v6 + 30*v7 + 100*v8 + 168*v9 + 7*v10 + 249*v11 + 84*v12 + 252*v13 + 171*v14 + 210*v15 + 206*v16 + 108*v17 + 153*v18 + 67*v19 + 189*v20 + 141*v21 + 239*v22 + 177*v23 + 10*v24 + 15*v25 + 164*v26 + 142*v27 + 97*v28 + 27*v29 + 173*v30 + 146*v31 + 133*v33 + 105*v34 + 75*(v32+v35) + 197*v36 == 393331
))
# 检查并输出结果
if s.check() == sat:
m = s.model()
[...处理结果...]
print("".join(t))
else:
print("failed")
5.3 第二重解密
unsigned char c[33] = "S0m3time_l1tt1e_c0de_1s_us3ful33";
unsigned char in[33] = {0};
in[0] = c[0] ^ 0x18;
in[1] = c[1] ^ 0x9;
in[2] = c[2] ^ 0x3;
[...省略部分异或操作...]
in[31] = c[31];
printf((const char*)in);
6. 关键知识点总结
-
WebAssembly逆向:
- wasm二进制提取
- wasm2c转换
- 编译为可分析对象
-
多元线性方程求解:
- Z3求解器使用
- 变量定义与约束添加
- 结果提取与处理
-
Native层分析:
- JNI_OnLoad分析
- IDA静态分析
- IDC脚本编写
-
加密算法分析:
- 异或加密识别
- 多层加密处理
- 加密顺序还原
7. 完整解题流程
- 分析Android应用结构,定位关键native方法
- 解密获取WebView加载的URL
- 分析JNI_OnLoad解密服务端响应
- 提取WebAssembly二进制代码
- 转换为C代码并分析核心验证逻辑
- 使用Z3求解32元线性方程组
- 对结果进行二次解密得到最终flag
8. 工具链
-
逆向工具:
- IDA Pro
- Jadx
- wasm2c
-
求解工具:
- Z3求解器
- Python科学计算栈
-
开发工具:
- GCC编译器
- IDC脚本环境
9. 扩展思考
-
WebAssembly安全:
- 浏览器中执行native代码的安全隐患
- 逆向保护与混淆技术
-
多元方程求解优化:
- 矩阵解法应用
- 性能优化策略
-
CTF出题思路:
- 多层加密设计
- 混合语言编程挑战
- 非标准加密方案