先查壳,发现是 UPX,直接脱壳就行,随后用 IDA 打开主程序
int __cdecl main(int argc, const char **argv, const char **envp) |
注意循环中 _data_start__
其实是一个数组,跟进查看可发现内容
'}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(',27h,'&%' |
优化一下,把 27h 换成 '
(十六进制的 27 对应着 ASCII 字符的 '
),所以这个数组应该被写成(在 Python 中)
data_start = '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"' |
还有值得注意的点,就是 v7 v8 v9,在程序中都被定义成了 int 类型,而每个 int 变量可以存储 4 个 char 变量,也就是一共 12 个字符
再看一下判断语句 v4[i] != _data_start__[*((char *)v5 + i) - 1]
,实际上可以看成
v4[i] == data_start[ord(flag[i])-1] |
可以理解成 ord(flag[i])-1
就是 v4[i]
在 data_start
中相同元素的索引值
那么逆过来就是
flag[i] == chr(data_start.find(v4[i])+1) |
所以我们可以写出解密脚本
v4 = "*F'\"N,\"(I?+@" |
最后输出结果为 U9X_1S_W6@T?
,就是 Flag 了,很有意思吧!