阅读IA32汇编代码 - 确定隐藏字符串?

时间:2016-10-26 15:55:01

标签: assembly x86 cpu-registers

我是一名学习IA-32装配的CS学生。对于一个项目,我们已经获得了程序的可执行文件。我们可以使用objdump和其他工具来检查二进制文件,但不允许查看原始源代码。该程序接受一个输入字符串,并将其与另一个神秘字符串进行比较。如果两个字符串 相同,则程序会发出警报,并且我不知道该作业。这将是一项有趣的任务......如果助教又懒得回答我的问题...... Grr ......

所以,如果你不介意给我一些指示,我想询问论坛我是否走在正确的轨道上。当我在CODE可执行文件上运行objdump -d CODE时,我可以向下钻取并在main()函数中看到它:

08048a44 <main>:
...
 8048af6:   e8 d0 08 00 00          call   80493cb <get_string>
 8048afb:   89 04 24                mov    %eax,(%esp)
 8048afe:   e8 ad 00 00 00          call   8048bb0 <test_string>

我有理由确定get_string()从用户那里获取一个字符串 - 它可能是fscanf()或其他东西的包装函数 - 然后指向该字符串的指针被保存到寄存器{{1 }}。下一行将指针移至%eax,然后调用%esp。这是代码:

test_string()

这就是我认为正在发生的事情......

08048bb0 <test_string>:
 8048bb0:   83 ec 1c                sub    $0x1c,%esp
 8048bb3:   c7 44 24 04 6c a4 04    movl   $0x804a46c,0x4(%esp)
 8048bba:   08 
 8048bbb:   8b 44 24 20             mov    0x20(%esp),%eax
 8048bbf:   89 04 24                mov    %eax,(%esp)
 8048bc2:   e8 bd 04 00 00          call   8049084 <cmp_strings>
 8048bc7:   85 c0                   test   %eax,%eax
 8048bc9:   74 05                   je     8048bd0 <test_string+0x20>
 8048bcb:   e8 bc 07 00 00          call   804938c <alarm>
 8048bd0:   83 c4 1c                add    $0x1c,%esp
 8048bd3:   c3                      ret    

所以...如果我是对的,第2行是重要的一个。我怀疑神秘字符串存储在内存地址08048bb0 <test_string>: 8048bb0: sub $0x1c,%esp // Adjusts %esp for new function 8048bb3: movl $0x804a46c,0x4(%esp) // test_string is stored at $0x804a46c; move that pointer into %esp 8048bba: // ??? 8048bbb: mov 0x20(%esp),%eax // Moves test_string ptr to %eax 8048bbf: mov %eax,(%esp) // Moves test_string ptr to %esp - not sure why...? 8048bc2: call 8049084 <cmp_strings> // Calls cmp_strings(), probably with %eax and %esp as argument strings 8048bc7: test %eax,%eax // %eax is the returned value 8048bc9: je 8048bd0 <test_string+0x20> // Should we jump to alarm()? 8048bcb: call 804938c <alarm> // If we reach here, I flunk 8048bd0: add $0x1c,%esp // restores %esp to original value 8048bd3: ret // exits 中。但我不确定。我还注意到,当我使用字符串工具时,我看到了:

$0x804a46c

这很有希望......但不能令人信服。内存地址[linux]$ strings -t x CODE | grep 46c 246c My dog has fleas. [linux]$ 不是$0x804a46c

所以...为冗长的帖子道歉,但是人们可以告诉我,我是否在正确的轨道上?任何见解或智慧都非常受欢迎!

非常感谢! -RAO

2 个答案:

答案 0 :(得分:3)

除非有一些反调试技巧在进行,否则import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; 只接受两个在cmp_strings()内部给出的参数。当然,它们都是字符串,第一个字符串取自常量位置test_string(),而第二个字符串(指向它的指针,当然不是字符串本身)是0x804a46c的参数。在调用之前,堆栈看起来像这样:

test_string()

您可以使用GDB直接在运行时检查«secret»字符串内容(通常,这是必要的,因为此处未显示的代码可能会重写它)。只需 |_______________| ESP: | <your string> | <-- cmp_strings() 1st arg +04: | 0x804a46c | <-- cmp_strings() 2nd arg +08: | ... | +0C: | ... | +10: | ... | +14: | ... | +18: | ... | +1C: | return adress | <-- ESP at the start of test_string() +20: | <your string> | <-- test_string() 1st arg +24: | ... | break *0x8048bc2,然后run

答案 1 :(得分:2)

  

下一行将指针移动到%esp,然后调用test_string()。

mov %eax,(%esp)eax中的值存储到esp所寻址的内存中,即。在堆栈的顶部。要将该指针复制到esp中,您必须执行mov %eax, %esp,这不是一个好主意,因为ss:esp被CPU用作堆栈指针。

  

movl $0x804a46c,0x4(%esp) // test_string is stored at $0x804a46c; move that pointer into %esp

再次,“into esp”在完全错误的程度上是不准确的。这会将值0x804a46c写入地址esp+4的内存中,因此如果您要从堆栈中pop值,则会弹出第二个值(右侧“在堆栈顶部”)。

  

mov 0x20(%esp),%eax // Moves test_string ptr to %eax

将“输入字符串指针”加载到eax。这是eax之前call <test_string>的那个。你可能就是这个意思,写了错误的评论?

  

mov %eax,(%esp) // Moves test_string ptr to %esp - not sure why...?

将它存储在“堆栈顶部”,因此如果您要在此处开始从堆栈中弹出值,则首先弹出输入字符串指针,然后弹出0x804a46c值。有关堆栈内容的ASCII艺术,请参阅hidefromkgb的答案。

然后很可能call 8049084 <cmp_strings>从堆栈中选择那两个指针作为参数,执行某些操作,并为正确的字符串返回零(因为任何非零返回值将使下一个je失败,并触发call <alarm>

您也应该快速查看cmp_strings,看看它是否是普通的C strcmp或它是如何返回零的。

正如杰斯特所指出的那样,objdump也应该有神秘的0x804a46c内容。如果它是一些早期任务,它可能属于具有易于读取的字符串数据的数据部分。

如果这将是更困难的任务,它也可以指向代码段中的伪指令形成一些字符串..或最终甚至不是假指令(虽然产生有意义的asm代码,形成一些短字符串也不是微不足道的在x86上...例如我曾经在我的256B intros .com文件的开头添加“PED”,它只是搞乱堆栈,不影响我的介绍的其余部分......并且在一个大小的编码竞赛中我使用xlat指向代码以获得想要的位模式以在51 bytes中绘制希腊旗帜。