cpo*_*el2 5 c assembly reverse-engineering
我想知道是否有人可以帮助我解决我在学校参加的入门讲习班中的一个讲座幻灯片时遇到的问题.我遇到的问题是不了解程序集,它是如何根据程序集对C源代码进行排序的.我将发布我正在讨论的片段,也许我会更清楚地谈论我的内容.
C来源:
int arith(int x, int y, int z)
{
int t1 = x+y;
int t2 = z+t1;
int t3 = x+4;
int t4 = y * 48;
int t5 = t3 + t4;
int rval = t2 * t5;
return rval;
}
Run Code Online (Sandbox Code Playgroud)
大会给出:
arith:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
movl 12(%ebp),%edx
leal (%edx,%eax),%ecx
leal (%edx,%edx,2),%edx
sall $4,%edx
addl 16(%ebp),%ecx
leal 4(%edx,%eax),%eax
imull %ecx,%eax
movl %ebp,%esp
popl %ebp
ret
Run Code Online (Sandbox Code Playgroud)
我只是觉得我应该能够辨别出例如在汇编代码之后的汇编中第二行(在源代码中)添加z + t1(z + x + y)y * 48的例子,或者例如那个x + 4是第3行,当它在汇编时它本身甚至不是一行,它与最后一个leal声明混合在一起.当我有源代码时对我有意义但是我应该能够重现测试的源代码并且我确实理解编译器优化了一些东西但是如果有人有办法考虑可以帮助我的逆向工程如果他们能够引导我完成思考过程,我将不胜感激.
谢谢.
我已经分解了反汇编,以显示如何从C源生成程序集.
8(%ebp)= x,12(%ebp)= y,16(%ebp)=z
arith:
Run Code Online (Sandbox Code Playgroud)
创建堆栈框架:
pushl %ebp
movl %esp,%ebp
Run Code Online (Sandbox Code Playgroud)
x到eax,y到edx:
movl 8(%ebp),%eax
movl 12(%ebp),%edx
Run Code Online (Sandbox Code Playgroud)
t1 = x + y.leal(加载有效地址)将添加edx和eax,并将t1在ecx:
leal (%edx,%eax),%ecx
Run Code Online (Sandbox Code Playgroud)
int t4 = y * 48;在下面的两个步骤中,乘以3,然后乘以16. t4最终将在edx:
乘以edx2,并添加edx到结果,即.edx = edx * 3:
leal (%edx,%edx,2),%edx
Run Code Online (Sandbox Code Playgroud)
向左移4位,即.乘以16:
sall $4,%edx
Run Code Online (Sandbox Code Playgroud)
int t2 = z+t1;.ecx 最初持有t1,z在16(%ebp)指令结束时ecx将持有t2:
addl 16(%ebp),%ecx
Run Code Online (Sandbox Code Playgroud)
int t5 = t3 + t4;.t3很简单x + 4,而不是计算和存储t3,表达式t3是内联的.这条指令必不可少(x+4) + t4,与t3+ 相同t4.它添加edx(t4)和eax(x),并添加4作为偏移量来实现该结果.
leal 4(%edx,%eax),%eax
Run Code Online (Sandbox Code Playgroud)
int rval = t2 * t5;相当直截了当; ecx代表t2并eax代表t5.返回值通过传递给调用者eax.
imull %ecx,%eax
Run Code Online (Sandbox Code Playgroud)
esp并ebp:
movl %ebp,%esp
popl %ebp
Run Code Online (Sandbox Code Playgroud)
ret
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,你无法从反汇编中完全回到源头.这取决于阅读程序集的人的解释,以提出等效的C代码.
编译调试信息(-g),它将嵌入源:
gcc -c -g arith.c
Run Code Online (Sandbox Code Playgroud)
如果您使用的是64位计算机,则可以告诉编译器使用该-m32标志创建一个32位二进制文件(我在下面的示例中这样做).
使用objdump转储目标文件,其源交错:
objdump -d -S arith.o
Run Code Online (Sandbox Code Playgroud)
-d=反汇编,-S=显示源.-M intel-mnemonic如果您喜欢使用英特尔ASM语法,则可以添加以使用您的示例使用的AT&T语法.
输出:
arith.o: file format elf32-i386
Disassembly of section .text:
00000000 <arith>:
int arith(int x, int y, int z)
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 20 sub $0x20,%esp
int t1 = x+y;
6: 8b 45 0c mov 0xc(%ebp),%eax
9: 8b 55 08 mov 0x8(%ebp),%edx
c: 01 d0 add %edx,%eax
e: 89 45 fc mov %eax,-0x4(%ebp)
int t2 = z+t1;
11: 8b 45 fc mov -0x4(%ebp),%eax
14: 8b 55 10 mov 0x10(%ebp),%edx
17: 01 d0 add %edx,%eax
19: 89 45 f8 mov %eax,-0x8(%ebp)
int t3 = x+4;
1c: 8b 45 08 mov 0x8(%ebp),%eax
1f: 83 c0 04 add $0x4,%eax
22: 89 45 f4 mov %eax,-0xc(%ebp)
int t4 = y * 48;
25: 8b 55 0c mov 0xc(%ebp),%edx
28: 89 d0 mov %edx,%eax
2a: 01 c0 add %eax,%eax
2c: 01 d0 add %edx,%eax
2e: c1 e0 04 shl $0x4,%eax
31: 89 45 f0 mov %eax,-0x10(%ebp)
int t5 = t3 + t4;
34: 8b 45 f0 mov -0x10(%ebp),%eax
37: 8b 55 f4 mov -0xc(%ebp),%edx
3a: 01 d0 add %edx,%eax
3c: 89 45 ec mov %eax,-0x14(%ebp)
int rval = t2 * t5;
3f: 8b 45 f8 mov -0x8(%ebp),%eax
42: 0f af 45 ec imul -0x14(%ebp),%eax
46: 89 45 e8 mov %eax,-0x18(%ebp)
return rval;
49: 8b 45 e8 mov -0x18(%ebp),%eax
}
4c: c9 leave
4d: c3 ret
Run Code Online (Sandbox Code Playgroud)
如您所见,没有优化,编译器会生成比您拥有的示例更大的二进制文件.你可以玩的是和编译时添加一个编译器优化标志(即-O1,-O2,-O3).优化级别越高,反汇编看起来就越抽象.
例如,只使用1级优化(gcc -c -g -O1 -m32 arith.c1),生成的汇编代码要短得多:
00000000 <arith>:
int arith(int x, int y, int z)
{
0: 8b 4c 24 04 mov 0x4(%esp),%ecx
4: 8b 54 24 08 mov 0x8(%esp),%edx
int t1 = x+y;
8: 8d 04 11 lea (%ecx,%edx,1),%eax
int t2 = z+t1;
b: 03 44 24 0c add 0xc(%esp),%eax
int t3 = x+4;
int t4 = y * 48;
f: 8d 14 52 lea (%edx,%edx,2),%edx
12: c1 e2 04 shl $0x4,%edx
int t5 = t3 + t4;
15: 8d 54 11 04 lea 0x4(%ecx,%edx,1),%edx
int rval = t2 * t5;
19: 0f af c2 imul %edx,%eax
return rval;
}
1c: c3 ret
Run Code Online (Sandbox Code Playgroud)
您无法重现原始来源,您只能重现等效来源.
在您的情况下,计算t2可以出现在t1之前和之后的任何地方retval.
源可能只是一个表达式:
return (x+y+z) * ((x+4) + (y * 48));
Run Code Online (Sandbox Code Playgroud)