dpr*_*amz 2 x86 assembly 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:
; 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
(依此类推)在32位整数数组的连续位置写入0x2391,0x239d,...(参见间隔4个字节的连续偏移),其指针作为参数传递(指针值被加载 - 莫名其妙地每个每次 - 从ebp 减去一些东西).最终它的内容将是:
0x2391
0x239d
0x239d
0x2399
0x239c
0x2363
0x2358
0x2358
0x2390
0x2398
0x2398
0x2357
0x2390
0x2395
0x2358
0x2377
0x235e
0x2380
0x237a
0x2381
0x23a3
Run Code Online (Sandbox Code Playgroud)
现在,这不是ASCII,但是第二个和第三个元素的重复(以及之后的其他重复)以及它们几乎都在相同范围内的事实使我认为它们必须以相同的简单方式编码,可能是一个总和或xor有一些固定值(总是相同的顶部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']
Run Code Online (Sandbox Code Playgroud)
(s这是一个包含这篇文章第二个代码块内容的字符串,包含所有数组值的内容)
享受下一级游戏的乐趣.:-)
顺便说一句,那个集会真的很可怕.其中一些,例如从堆栈继续重新加载相同的值到寄存器
mov eax, dword [ebp-0x24]
Run Code Online (Sandbox Code Playgroud)
会让我想到一个非优化的,调试器友好的构建; OTOH,有些东西似乎不是来自编译器:
mov eax, 0x10
sub eax, 0x1
Run Code Online (Sandbox Code Playgroud)
在这里,即使在适度的优化常数传播水平上进行编译也会产生mov eax, 0xf,或者,-O0它会在堆栈上而不是在寄存器中执行,以帮助源级单步执行.
mov ebx, 0x10
mov edx, 0x0
div ebx
imul eax, eax, 0x10
Run Code Online (Sandbox Code Playgroud)
这是多层次的脑死亡; 你永远不会看到mov edx, 0x0 一般的编译器- 即使-O0归零寄存器也是如此xor edx, edx.此外,对数据类型存在一些混淆:首先是无符号div,然后是有符号imul(它映射到类似的东西((int)((unsigned)(foo)/16))*16,我觉得不太可能).
但最重要的是,gcc永远不会发出一个div或mul一个除法/乘以16; 它甚至可以将它们转变为一种转变-O0 ; clang是相同的(虽然-O0它仍然会发出一个idiv有符号的分区,而不是在更高的优化级别使用的shift + sign-bit twiddling).
最后,如果输入值是无符号的(根据div),这整个事情归结为掩盖低4位,所以所有这些混乱可能只是
and eax, 0xfffffff0.
所以,在我看来,这是一个不具备装配经验的人的手写代码; 这种事情甚至看起来都不是"故意的困难",使得拆解更加困难 - 代码非常简单,它只是非常天真.
| 归档时间: |
|
| 查看次数: |
284 次 |
| 最近记录: |