题目描述

菜鸡听说有的程序运行就能拿Flag?

Solution

使用filebinwalkstrings三板斧,得知这个程序是 ELF32 文件,没有加密,同时可打印字符也没有直接显示 Flag,该题可能是 字母表 + 加密变换 来构造出 Flag 的。

打开程序运行,随便输入一串数据后会发送 Segmentation fault。使用 IDA 打开文件,观察main()函数:

009-1.png

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

009-2.png

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

009-3.png

现在我们分析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]

而解码逻辑如下:

009-4.png

我们编写一段 Python 代码来模拟这段流程:

  1. alpha_table = [0x3a, 0x36, 0x37, 0x3b, 0x80, 0x7a, 0x71, 0x78, 0x63, 0x66, 0x73, 0x67, 0x62, 0x65, 0x73, 0x60, 0x6b, 0x71,
  2. 0x78, 0x6a, 0x73, 0x70, 0x64, 0x78, 0x6e, 0x70, 0x70, 0x64, 0x70, 0x64, 0x6e, 0x7b, 0x76, 0x78, 0x6a, 0x73, 0x7b, 0x80]
  3. digit_table = [1, 2, 3, 4, 5]
  4. ans = ""
  5. for i in range(0, len(alpha_table)):
  6. cur_char = alpha_table[i] - digit_table[i % len(digit_table)]
  7. ans += chr(cur_char)
  8. print(ans)

运行结果:

009-5.png


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

009-6.png