[Week 2] BabyUPX
- EXE Info查看发现有UPX套壳,用工具脱壳
- 脱壳后再次检查发现干净了
- IDA打开,查看是输入加密后与密文比对
- 加密本质为将一个字节的高4位与低4位互换
- 提取密文,编写解密脚本
encdata = [
0x03, 0x87, 0x74, 0x16, 0xD6, 0x56, 0xB7, 0x63,
0x83, 0x46, 0x66, 0x66, 0x43, 0x53, 0x83, 0xD2,
0x23, 0x93, 0x56, 0x53, 0xD2, 0x43, 0x36, 0x36,
0x03, 0xD2, 0x16, 0x93, 0x36, 0x26, 0xD2, 0x93,
0x73, 0x13, 0x66, 0x56, 0x36, 0x33, 0x33, 0x83,
0x56, 0x23, 0x66, 0xD7
]
def decode(encoded_data):
decoded_str = ""
for encoded_val in encoded_data:
original_val = ((encoded_val & 0xF) << 4) | (encoded_val >> 4)
decoded_str += chr(original_val)
return decoded_str
decoded = decode(encdata)
print("decode:", decoded)
- 0xGame{68dff458-29e5-4cc0-a9cb-971fec338e2f}
[Week 2] FirstSight-Jar
- 文件是已经打包好的jar文件,用工具或者网站反编译,我使用的是网站
- 分析文件是对在字母表中的字符索引进行处理
var3 = (var3 * 5 + 3) % 16
- 由于取膜后不好还原,所以直接写脚本将全部字母表都进行处理,产生明文与密文对照的字典
- 编写脚本
Alphabat = "0123456789abcdef"
ans = {}
c = "ab50e920-4a97-70d1-b646-cdac5c873376"
result = ''
for n,i in enumerate(Alphabat):
m = (n*5+3)%16
ans[Alphabat[m]]=i
for i in c:
if i in Alphabat:
result += ans[i]
else:
result += i
print("0xGame{",result,"}",sep="")
- 0xGame{b8a9fe39-dbe4-4926-87d7-52b5a5140047}
[Week 2] FisrtSight-Pyc
- pyc是py文件在被import调用时候生成的类似缓存文件,可以加速下次调用
- 使用工具或者网站反编译,我使用的网站
- 得到反编译后的python文件,并手动修改不当语句
- 由于本身是作为库调用的,这里将return删去,然后就可以直接运行了
- 分析源码发现当输入为Ciallo~时继续下一步操作
- 最终得到0xGame{2f0ef0217bf3a7c598d381b077672e09}
[Week 2] Xor::Ramdom
- IDA打开分析
- 能发现是随机数与flag加密
- 注意到有init_random(void)函数,用来定义随机数种子
srand(0x77u);
- 同时注意密文是小端序,要重排
- 据此手搓脚本
- 还要注意,这里生成的随机数使用c++生成,不存在范围限制
- 而python生成的随机数有范围限制,因此只能用c++编写脚本
#include <iostream>
#include <string>
#include <array>
#include <cstdlib>
const std::array<unsigned char, 30> expected_values = {
0x0C, 0x4F, 0x10, 0x1F, 0x4E, 0x16, 0x21, 0x12,
0x4B, 0x24, 0x10, 0x4B, 0x0A, 0x24, 0x1F, 0x17,
0x09, 0x4F, 0x07, 0x08, 0x21, 0x5C, 0x2C, 0x1A,
0x10, 0x1F, 0x11, 0x16, 0x59, 0x5A
};
void generate_flag(std::string& flag) {
flag = "0xGame{";
int random_value = rand();
for (size_t i = 0; i < 30; ++i) {
char ch;
if (i % 2 != 0) {
ch = random_value;
}
else {
ch = random_value + 3;
}
ch ^= expected_values[i];
flag += ch;
}
flag += '}';
}
int main() {
std::string flag;
srand(0x77u);
rand();
generate_flag(flag);
std::cout << "Generated flag: " << flag << std::endl;
return 0;
}
- (第一次写c++脚本,要废了呜呜呜
- 得到0xGame{r4nd0m_i5_n0t_alw4ys_’Random’!}
[Week 2] ZzZ
- 函数很多啊,根本找不到
- 尝试运行下发现输出Please enter your flag,然后去搜索查找这段字符所在函数
- 或者Shift+F12也能看见
- 主函数sub_140011AA0()
- 分析逻辑发现是当满足如下方程的时候输出正确
11 * v11 + 14 * v10 - v12 == 0x48FB41DDD
9 * v10 - 3 * v11 + 4 * v12 == 0x2BA692AD7
((v12 - v11) >> 1) + (v10 ^ 0x87654321) == 0xCDBDFAAC
- 其中v10,v11,v12是从flag中划分出来的字符转长整型,flag结构如下
- 0xGame{v13-v10-v11-v12-v14},其中v13和v14已知,分别为E544267D和D085A85201A4
- 用z3编写脚本,Sage中比较难处理右移位以及异或运算
from z3 import *
from Crypto.Util.number import *
# 创建 Z3 变量
v10 = BitVec('v10',32)
v11 = BitVec('v11',32)
v12 = BitVec('v12',32)
# 创建 Z3 求解器
solver = Solver()
# 添加方程
solver.add(11 * v11 + 14 * v10 - v12 == 0x48FB41DDD)
solver.add(9 * v10 - 3 * v11 + 4 * v12 == 0x2BA692AD7)
solver.add(((v12 - v11) >> 1) + (v10 ^ 0x87654321) == 0xCDBDFAAC)
# 求解
if solver.check() == sat:
model = solver.model()
def bit_to_str(val):
return long_to_bytes(model[val].as_long()).decode('ascii')[::-1]
v10,v11,v12 = map(bit_to_str,[v10,v11,v12])
print("0xGame"+f"{{E544267D-{v10}-{v11}-{v12}-D085A85201A4}}".lower())
else:
print("无解")
- 其中注意最终算出的结果是小端序,要倒序下
- 得到0xGame{e544267d-7812-44b3-a35d-d085a85201a4}