试图在 32 位 ELF 中找到隐藏的字符串

trying to find a hidden string in a 32-bit ELF

别担心,我不会问答案的。

我试图在一个简单的 1 函数 32 位 exe 中找到隐藏的字符串(也许是电子邮件?)

文件中已有 运行 个字符串,没有任何用处。

我已经将文件反编译为 ASCII 并找到了主要功能。

文件显示它是 GCC 可执行文件。

这里是主要函数的汇编:

        ; ================ B E G I N N I N G   O F   P R O C E D U R E ================

        ; Variables:
        ;    arg_0: int, 4


             main:
080489cc         lea        ecx, dword [esp+arg_0]                              ; Begin of unwind block (FDE at 0x80d6cb8), DATA XREF=_start+23
080489d0         and        esp, 0xfffffff0
080489d3         push       dword [ecx-4]
080489d6         push       ebp
080489d7         mov        ebp, esp
080489d9         push       esi
080489da         push       ebx
080489db         push       ecx
080489dc         sub        esp, 0x2c
080489df         call       __x86.get_pc_thunk.cx                               ; __x86.get_pc_thunk.cx
080489e4         add        ecx, 0xa261c
080489ea         mov        eax, dword [gs:0x14]
080489f0         mov        dword [ebp-0x1c], eax
080489f3         xor        eax, eax
080489f5         mov        eax, esp
080489f7         mov        esi, eax
080489f9         mov        dword [ebp-0x2c], 0x15
08048a00         mov        eax, dword [ebp-0x2c]
08048a03         lea        edx, dword [eax-1]
08048a06         mov        dword [ebp-0x28], edx
08048a09         shl        eax, 0x2
08048a0c         lea        edx, dword [eax+3]
08048a0f         mov        eax, 0x10
08048a14         sub        eax, 0x1
08048a17         add        eax, edx
08048a19         mov        ebx, 0x10
08048a1e         mov        edx, 0x0
08048a23         div        ebx
08048a25         imul       eax, eax, 0x10
08048a28         sub        esp, eax
08048a2a         mov        eax, esp
08048a2c         add        eax, 0x3
08048a2f         shr        eax, 0x2
08048a32         shl        eax, 0x2
08048a35         mov        dword [ebp-0x24], eax
08048a38         mov        eax, dword [ebp-0x24]
08048a3b         mov        dword [eax], 0x2391
08048a41         mov        eax, dword [ebp-0x24]
08048a44         mov        dword [eax+4], 0x239d
08048a4b         mov        eax, dword [ebp-0x24]
08048a4e         mov        dword [eax+8], 0x239d
08048a55         mov        eax, dword [ebp-0x24]
08048a58         mov        dword [eax+0xc], 0x2399
08048a5f         mov        eax, dword [ebp-0x24]
08048a62         mov        dword [eax+0x10], 0x239c
08048a69         mov        eax, dword [ebp-0x24]
08048a6c         mov        dword [eax+0x14], 0x2363
08048a73         mov        eax, dword [ebp-0x24]
08048a76         mov        dword [eax+0x18], 0x2358
08048a7d         mov        eax, dword [ebp-0x24]
08048a80         mov        dword [eax+0x1c], 0x2358
08048a87         mov        eax, dword [ebp-0x24]
08048a8a         mov        dword [eax+0x20], 0x2390
08048a91         mov        eax, dword [ebp-0x24]
08048a94         mov        dword [eax+0x24], 0x2398
08048a9b         mov        eax, dword [ebp-0x24]
08048a9e         mov        dword [eax+0x28], 0x2398
08048aa5         mov        eax, dword [ebp-0x24]
08048aa8         mov        dword [eax+0x2c], 0x2357
08048aaf         mov        eax, dword [ebp-0x24]
08048ab2         mov        dword [eax+0x30], 0x2390
08048ab9         mov        eax, dword [ebp-0x24]
08048abc         mov        dword [eax+0x34], 0x2395
08048ac3         mov        eax, dword [ebp-0x24]
08048ac6         mov        dword [eax+0x38], 0x2358
08048acd         mov        eax, dword [ebp-0x24]
08048ad0         mov        dword [eax+0x3c], 0x2377
08048ad7         mov        eax, dword [ebp-0x24]
08048ada         mov        dword [eax+0x40], 0x235e
08048ae1         mov        eax, dword [ebp-0x24]
08048ae4         mov        dword [eax+0x44], 0x2380
08048aeb         mov        eax, dword [ebp-0x24]
08048aee         mov        dword [eax+0x48], 0x237a
08048af5         mov        eax, dword [ebp-0x24]
08048af8         mov        dword [eax+0x4c], 0x2381
08048aff         mov        eax, dword [ebp-0x24]
08048b02         mov        dword [eax+0x50], 0x23a3
08048b09         mov        eax, dword [ebp-0x2c]
08048b0c         sub        esp, 0xc
08048b0f         push       eax                                                 ; argument #1 for method __libc_malloc
08048b10         mov        ebx, ecx
08048b12         call       __libc_malloc                                       ; __libc_malloc
08048b17         add        esp, 0x10
08048b1a         add        eax, 0x1
08048b1d         mov        dword [ebp-0x20], eax
08048b20         mov        dword [ebp-0x30], 0x0
08048b27         jmp        loc_8048b44

08048a35 - 08048b09 行看起来一次移动 1 个字符,我确定它是字符串。

这里的问题是,谁能帮我弄清楚那些字符是什么?它们不是 ASCII 编码,而且我不确定 ASM 是如何真正进行字符编码之类的操作的,所以也许我只是没有看到它。也许它被加密了?

我是新手,并不知道最好的方法。谢谢!

顺序

08048a38         mov        eax, dword [ebp-0x24]
08048a3b         mov        dword [eax], 0x2391
08048a41         mov        eax, dword [ebp-0x24]
08048a44         mov        dword [eax+4], 0x239d

(依此类推)正在 32 位整数数组中的连续位置写入 0x2391、0x239d,...(请参阅间隔为 4 字节的连续偏移量),其指针作为参数传递(指针值被加载 - 每次都莫名其妙 - 从 ebp minus something)。最终其内容将是:

0x2391
0x239d
0x239d
0x2399
0x239c
0x2363
0x2358
0x2358
0x2390
0x2398
0x2398
0x2357
0x2390
0x2395
0x2358
0x2377
0x235e
0x2380
0x237a
0x2381
0x23a3

现在,这不是 ASCII,但第二个和第三个元素的重复(加上后面的其他重复)以及它们几乎都在同一范围内的事实让我认为它们必须全部编码以同样简单的方式,大概是一个求和或具有某个固定值的异或(总是相同的顶部 0x23 字节是一个死赠品);因此,由于您的问题中缺少其余代码(可能已解码此数组),我只是猜测并尝试对它们全部减去相同的值以使它们返回到 ASCII 范围。

我的第一个猜测是上面重复的数字 (0x239d) 必须是 l(在英语中经常成对出现)。因此,我需要一个数字,这样 0x239d 就会变成 l (ASCII 108); 0x239d - 108 = 9009,这就是我减去每个字符的结果。结果全是 ASCII(令人鼓舞 - 如果方案更复杂,除了两个 l 之外我会得到不可读的随机垃圾),但是荒谬。

我选择了一种蛮力方法(最合理的情况是 62 - 大写、小写和数字 - 使用这种方法进行的详尽搜索最多为 256 个情况,通过目视检查仍然可以管理)并尝试了一些相似的数字 - 所有导致 ASCII 字符的东西,但希望更明智。

事实上,一旦我达到 9001:

In [18]: [chr(int(x,16)-9001) for x in s.split()]
Out[18]: 
['h',
 't',
 't',
 'p',
 's',
 ':',
 '/',
 '/',
 'g',
 'o',
 'o',
 '.',
 'g',
 'l',
 '/',
 'N',
 '5',
 'W',
 'Q',
 'X',
 'z']

(s这里是一个字符串,包含这个post的第二个代码块的内容,也就是所有数组值)

尽情享受游戏的下一关吧。 :-)


顺便说一句,那个集会真是太可怕了。其中一些,例如继续从堆栈重新加载相同的值到寄存器

mov eax, dword [ebp-0x24]

会让我考虑一个非优化的、调试器友好的构建; OTOH,有些东西似乎并不是来自编译器:

mov        eax, 0x10
sub        eax, 0x1

在这里,即使以适度的优化常量传播级别进行编译也会产生 mov eax, 0xf,或者,在 -O0,它会在堆栈上执行,而不是在寄存器中执行,以帮助源代码-级单步.

mov        ebx, 0x10
mov        edx, 0x0
div        ebx
imul       eax, eax, 0x10

这在多个层面上都是脑死亡;您永远不会看到编译器发出 mov edx, 0x0 一般 - 即使在 -O0 时,将寄存器归零也几乎总是 xor edx, edx。此外,数据类型存在一些混淆:首先是无符号的 div,然后是有符号的 imul(它映射到类似 ((int)((unsigned)(foo)/16))*16 的东西,我认为这不太可能)。

但最重要的是,gcc 永远不会为 16 的 division/multiplication 发出 divmulit transforms them to a shift even at -O0; clang is the same(尽管在 -O0 时它仍会发出 idiv 用于有符号除法,而不是在更高优化级别上使用的移位 + 符号位旋转)。

最后,如果输入值是无符号的(根据 div),这整个事情归结为屏蔽掉低 4 位,所以所有这些混乱可能只是 and eax, 0xfffffff0.

所以,在我看来,这是一个不太懂汇编的人手写的代码;这种东西似乎 "intentional difficulty" 并没有为了使反汇编变得更加困难而被抛出 - 代码非常简单,只是非常幼稚。