题目描述
菜鸡听说有的程序运行就能拿Flag?
Solution
使用file、binwalk、strings三板斧,得知这个程序是 ELF32 文件,没有加密,同时可打印字符也没有直接显示 Flag,该题可能是 字母表 + 加密变换 来构造出 Flag 的。
打开程序运行,随便输入一串数据后会发送 Segmentation fault。使用 IDA 打开文件,观察main()函数:

主流程很简单,我们直接进入authenticate()函数分析:

authenticate()函数先解码一个字符串,然后从标准输入(Stdin)中读取用户输入,如果输入的字符串和解码后的字符串相等,则打印Success! Welcome back!。注意,本题的字符串是宽字符(每个字符有 4 bytes),当你双击进入&unk_8048BA4的时候要掠过一些零:

现在我们分析decrypt()函数。函数的两个参数分别是宽字符(按 D 修改显示格式为db):
[0x3a, 0x36, 0x37, 0x3b, 0x80, 0x7a, 0x71, 0x78, 0x63, 0x66, 0x73, 0x67, 0x62, 0x65, 0x73, 0x60, 0x6b, 0x71, 0x78, 0x6a, 0x73, 0x70, 0x64, 0x78, 0x6e, 0x70, 0x70, 0x64, 0x70, 0x64, 0x6e, 0x7b, 0x76, 0x78, 0x6a, 0x73, 0x7b, 0x80][0x1, 0x2, 0x3, 0x4, 0x5]
而解码逻辑如下:

我们编写一段 Python 代码来模拟这段流程:
alpha_table = [0x3a, 0x36, 0x37, 0x3b, 0x80, 0x7a, 0x71, 0x78, 0x63, 0x66, 0x73, 0x67, 0x62, 0x65, 0x73, 0x60, 0x6b, 0x71,0x78, 0x6a, 0x73, 0x70, 0x64, 0x78, 0x6e, 0x70, 0x70, 0x64, 0x70, 0x64, 0x6e, 0x7b, 0x76, 0x78, 0x6a, 0x73, 0x7b, 0x80]digit_table = [1, 2, 3, 4, 5]ans = ""for i in range(0, len(alpha_table)):cur_char = alpha_table[i] - digit_table[i % len(digit_table)]ans += chr(cur_char)print(ans)
运行结果:

本题的另一个方法是使用动态调试。我们刚才分析了,decrypt()函数会返回 Flag,在authenticate()里和用户输入进行比较。我们使用 GDB 在authenticate()下断点,观察decrypt()执行完后的返回值(位于 EAX 寄存器):

