Assembly 正在尝试在32位ELF中查找隐藏字符串
别担心,我不会问你答案的 我试图在一个简单的1函数32位exe中找到一个隐藏字符串(可能是电子邮件?) 我已经在文件上运行了字符串,没有任何有用的东西 我已将该文件反编译为ASCII,并找到了主函数 文件显示它是一个GCC可执行文件 以下是主要功能的asm:Assembly 正在尝试在32位ELF中查找隐藏字符串,assembly,x86,reverse-engineering,elf,Assembly,X86,Reverse Engineering,Elf,别担心,我不会问你答案的 我试图在一个简单的1函数32位exe中找到一个隐藏字符串(可能是电子邮件?) 我已经在文件上运行了字符串,没有任何有用的东西 我已将该文件反编译为ASCII,并找到了主函数 文件显示它是一个GCC可执行文件 以下是主要功能的asm: ; ================ B E G I N N I N G O F P R O C E D U R E ================ ; Variables: ;
; ================ 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
(以此类推)正在写入0x2391、0x239d。。。在32位整数数组中的连续位置(参见以4字节间隔的连续偏移量),其指针作为参数传递(指针值每次都从ebp减去某个值加载,令人费解)。最终,其内容将是:
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
这里是一个字符串,包含本文第二个代码块的内容,即包含所有数组值的代码块)
享受游戏的下一关乐趣。:-)
顺便说一句,那次大会真的很可怕。其中的一些,例如继续将相同的值从堆栈重新加载到寄存器
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
,我觉得这不太可能)
但最重要的是,对于16的除法/乘法,gcc永远不会发出div
或mul
;(尽管在-O0
处,它仍然会发出带符号除法的idiv
,而不是在更高优化级别使用的移位+符号位旋转)
最后,如果输入值是无符号的(根据div
),那么整个过程归结为屏蔽掉低4位,因此所有这些混乱可以简单地消除
和eax,0xfffffff0
所以,在我看来,这是一个没有汇编经验的人手写的代码;这类事情似乎并不是为了增加反汇编的难度而故意添加的“困难”-代码非常简单,只是很幼稚。它在移动
dword
,一次移动8个字节。@Barmar:在x86上,dword意味着4个字节…当然,这解释了为什么它会移动eax+4
,eax+8
,等等@dprogramz:你真的不需要读寄存器,它就在那里,你可以清楚地看到,它们甚至已经被排序了。但它看起来像是在用那些奇怪的数字(不是直接的ASCII值)填充一个32位整数值的数组。可能重要的细节在您省略的代码中。最后,您可以看到它正在分配一些内存,这些内存可能用于解码地址。@MatteoItalia非常感谢您!多好的解释啊!我在数组到ASCII编码理论方面取得了进展,但迷路了。我可以问一下,是什么让你想到先减去9009,然后再减去9001?@dprogramz:我想减去一个数字,使0x239d(重复两次)变成l
(ASCII 108);0x239d-108=9009,这就是我减去每个字符的值。结果全是ASCII码(令人鼓舞——如果方案更复杂,除了两个l
,我还会得到无法读取的随机垃圾),但毫无意义。因此,我选择了蛮力方法(最合理的情况只有62个)并尝试了一些类似的数字——所有这些都会产生ASCII字符,但希望更合理。当我到达9001时,上面的字符串出现了;头奖@itachi:从一个有能力的程序中可以看出有意的困难