《coredump问题原理探究》Linux x86版4.2节函数的逆向之顺序结构
来源:互联网 发布:若水软件 免费软件 编辑:程序博客网 时间:2024/05/16 13:02
先看一下例子:
#include <stdio.h>int main(){ int a = 0, b = 0, c = 0, d = 0; scanf( "%d,%d", &a,&b ); a += b; scanf( "%d", &c ); a += c; scanf( "%d", &d ); a += d; return a;}
看一下main函数的汇编:
(gdb) disassemble mainDump of assembler code for function main: 0x08048570 <+0>: push %ebp 0x08048571 <+1>: mov %esp,%ebp 0x08048573 <+3>: and $0xfffffff0,%esp 0x08048576 <+6>: sub $0x20,%esp 0x08048579 <+9>: movl $0x0,0x1c(%esp) 0x08048581 <+17>: movl $0x0,0x18(%esp) 0x08048589 <+25>: movl $0x0,0x14(%esp) 0x08048591 <+33>: movl $0x0,0x10(%esp) 0x08048599 <+41>: lea 0x18(%esp),%eax 0x0804859d <+45>: mov %eax,0x8(%esp) 0x080485a1 <+49>: lea 0x1c(%esp),%eax 0x080485a5 <+53>: mov %eax,0x4(%esp) 0x080485a9 <+57>: movl $0x80486b4,(%esp) 0x080485b0 <+64>: call 0x8048440 <scanf@plt> 0x080485b5 <+69>: mov 0x1c(%esp),%edx 0x080485b9 <+73>: mov 0x18(%esp),%eax 0x080485bd <+77>: add %edx,%eax 0x080485bf <+79>: mov %eax,0x1c(%esp) 0x080485c3 <+83>: lea 0x14(%esp),%eax 0x080485c7 <+87>: mov %eax,0x4(%esp) 0x080485cb <+91>: movl $0x80486ba,(%esp) 0x080485d2 <+98>: call 0x8048440 <scanf@plt> 0x080485d7 <+103>: mov 0x1c(%esp),%edx 0x080485db <+107>: mov 0x14(%esp),%eax 0x080485df <+111>: add %edx,%eax 0x080485e1 <+113>: mov %eax,0x1c(%esp) 0x080485e5 <+117>: lea 0x10(%esp),%eax 0x080485e9 <+121>: mov %eax,0x4(%esp) 0x080485ed <+125>: movl $0x80486ba,(%esp) 0x080485f4 <+132>: call 0x8048440 <scanf@plt> 0x080485f9 <+137>: mov 0x1c(%esp),%edx 0x080485fd <+141>: mov 0x10(%esp),%eax 0x08048601 <+145>: add %edx,%eax 0x08048603 <+147>: mov %eax,0x1c(%esp) 0x08048607 <+151>: mov 0x1c(%esp),%eax 0x0804860b <+155>: jmp 0x8048615 <main+165> 0x0804860d <+157>: mov %eax,(%esp) 0x08048610 <+160>: call 0x8048460 <_Unwind_Resume@plt> 0x08048615 <+165>: leave 0x08048616 <+166>: ret End of assembler dump.
区区十来行代码,就变成了非常多的汇编语句,非常令人害怕。实际上,不需要那么害怕。
先看一下call指令的地方,由于call指令是调用函数的,所以,用它可以大致定一下这样的范围。
先看一下三个call指令的地址:
0x080485b0 <+64>: call 0x8048440 <scanf@plt> 0x080485d2 <+98>: call 0x8048440 <scanf@plt> 0x080485f4 <+132>: call 0x8048440 <scanf@plt>
可以知道,
0x08048570 <+0>: push %ebp 0x08048571 <+1>: mov %esp,%ebp 0x08048573 <+3>: and $0xfffffff0,%esp 0x08048576 <+6>: sub $0x20,%esp 0x08048579 <+9>: movl $0x0,0x1c(%esp) 0x08048581 <+17>: movl $0x0,0x18(%esp) 0x08048589 <+25>: movl $0x0,0x14(%esp) 0x08048591 <+33>: movl $0x0,0x10(%esp) 0x08048599 <+41>: lea 0x18(%esp),%eax 0x0804859d <+45>: mov %eax,0x8(%esp) 0x080485a1 <+49>: lea 0x1c(%esp),%eax 0x080485a5 <+53>: mov %eax,0x4(%esp) 0x080485a9 <+57>: movl $0x80486b4,(%esp)
这一段汇编的地址少于第一个call指令地址0x080485b0,所以,它们大概对应于代码:
int a = 0, b = 0, c = 0, d = 0;
而
0x080485b5 <+69>: mov 0x1c(%esp),%edx 0x080485b9 <+73>: mov 0x18(%esp),%eax 0x080485bd <+77>: add %edx,%eax 0x080485bf <+79>: mov %eax,0x1c(%esp) 0x080485c3 <+83>: lea 0x14(%esp),%eax 0x080485c7 <+87>: mov %eax,0x4(%esp) 0x080485cb <+91>: movl $0x80486ba,(%esp)
这一段汇编由于地址大于0x080485b0,小于0x080485d2,所以,它们大致对应于代码:
a += b;
再
0x080485d7 <+103>: mov 0x1c(%esp),%edx 0x080485db <+107>: mov 0x14(%esp),%eax 0x080485df <+111>: add %edx,%eax 0x080485e1 <+113>: mov %eax,0x1c(%esp) 0x080485e5 <+117>: lea 0x10(%esp),%eax 0x080485e9 <+121>: mov %eax,0x4(%esp) 0x080485ed <+125>: movl $0x80486ba,(%esp)
这一段汇编地址大于0x080485d2,小于0x080485f4,所以,它们大致对应于代码:
a += c;
而
0x080485f9 <+137>: mov 0x1c(%esp),%edx 0x080485fd <+141>: mov 0x10(%esp),%eax 0x08048601 <+145>: add %edx,%eax 0x08048603 <+147>: mov %eax,0x1c(%esp) 0x08048607 <+151>: mov 0x1c(%esp),%eax 0x0804860b <+155>: jmp 0x8048615 <main+165> 0x0804860d <+157>: mov %eax,(%esp) 0x08048610 <+160>: call 0x8048460 <_Unwind_Resume@plt> 0x08048615 <+165>: leave 0x08048616 <+166>: ret
这一段汇编地址大于0x080485f4,所以,它们对应于代码:
a += d;return a;
看,分析汇编,并不是那么让人恐怖。但上面由于有一些指令是编译器生成的,有一些是函数调用时把参数入栈的指令,所以,要筛选出这些指令,仅以第一段汇编为例(即第一个scanf调用前的汇编):
0x08048570 <+0>: push %ebp 0x08048571 <+1>: mov %esp,%ebp 0x08048573 <+3>: and $0xfffffff0,%esp 0x08048576 <+6>: sub $0x20,%esp 0x08048579 <+9>: movl $0x0,0x1c(%esp) 0x08048581 <+17>: movl $0x0,0x18(%esp) 0x08048589 <+25>: movl $0x0,0x14(%esp) 0x08048591 <+33>: movl $0x0,0x10(%esp) 0x08048599 <+41>: lea 0x18(%esp),%eax 0x0804859d <+45>: mov %eax,0x8(%esp) 0x080485a1 <+49>: lea 0x1c(%esp),%eax 0x080485a5 <+53>: mov %eax,0x4(%esp) 0x080485a9 <+57>: movl $0x80486b4,(%esp)
由第三章可知,
0x08048570 <+0>: push %ebp 0x08048571 <+1>: mov %esp,%ebp
是属于函数开头的特征指令,所以,这是由编译器自动生成的。
而
0x08048573 <+3>: and $0xfffffff0,%esp 0x08048576 <+6>: sub $0x20,%esp
则是用来调整esp和分配局部变量空间的,也是编译器自动生成的。所以,第一段汇编只剩下
0x08048579 <+9>: movl $0x0,0x1c(%esp) 0x08048581 <+17>: movl $0x0,0x18(%esp) 0x08048589 <+25>: movl $0x0,0x14(%esp) 0x08048591 <+33>: movl $0x0,0x10(%esp) 0x08048599 <+41>: lea 0x18(%esp),%eax 0x0804859d <+45>: mov %eax,0x8(%esp) 0x080485a1 <+49>: lea 0x1c(%esp),%eax 0x080485a5 <+53>: mov %eax,0x4(%esp) 0x080485a9 <+57>: movl $0x80486b4,(%esp)
是和
int a = 0, b = 0, c = 0, d = 0;
对应。由于
scanf( "%d,%d", &a,&b );
是有三个参数,根据第三章内容,
0x08048599 <+41>: lea 0x18(%esp),%eax 0x0804859d <+45>: mov %eax,0x8(%esp) 0x080485a1 <+49>: lea 0x1c(%esp),%eax 0x080485a5 <+53>: mov %eax,0x4(%esp) 0x080485a9 <+57>: movl $0x80486b4,(%esp)
刚好是把scanf的三个参数入栈的操作,可以通过运行时得到0x80486b4指向的内容:
gdb) tbreak *0x080485b0Temporary breakpoint 1 at 0x80485b0(gdb) rStarting program: /home/buckxu/work/4/1/xuzhina_dump_c4_s1 Temporary breakpoint 1, 0x080485b0 in main ()(gdb) x /s 0x80486b40x80486b4 <__dso_handle+4>: "%d,%d"
也就是说,只有
0x08048579 <+9>: movl $0x0,0x1c(%esp) 0x08048581 <+17>: movl $0x0,0x18(%esp) 0x08048589 <+25>: movl $0x0,0x14(%esp) 0x08048591 <+33>: movl $0x0,0x10(%esp)
才是和
int a = 0, b = 0, c = 0, d = 0;
对应的。
小结:
由于顺序结构的逆向非常考验汇编基础,但如果是有函数调用的话,先找call指令,根据call指令来划分范围,筛选出编译器自动生成的指令。
- 《coredump问题原理探究》Linux x86版4.2节函数的逆向之顺序结构
- 《coredump问题原理探究》Linux x86版4.3节函数的逆向之条件结构
- 《coredump问题原理探究》Linux x86版4.4节函数的逆向之循环结构
- 《coredump问题原理探究》Linux x86版4.5节函数的逆向之coredump例子
- 《coredump问题原理探究》Linux x86版4.1节函数的逆向之序言
- 《coredump问题原理探究》Linux x86版6.5节虚函数的coredump例子
- 《coredump问题原理探究》Linux x86版3.2节栈布局之函数桢
- 《coredump问题原理探究》Linux x86版3.4节栈布局之函数参数
- 《coredump问题原理探究》Linux x86版3.4节栈布局之函数参数 .
- 《coredump问题原理探究》Linux x86版3.8节栈布局之栈溢出coredump例子
- 《coredump问题原理探究》Linux x86版6.3节有成员变量的类coredump例子
- 《coredump问题原理探究》Linux x86版5.7节C风格数据结构内存布局之结构体数组
- 《coredump问题原理探究》Linux x86版5.8节C风格数据结构内存布局之结构体数组结构体coredump
- 《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体
- 《coredump问题原理探究》Linux x86版5.6节C风格数据结构内存布局之复合类型构成的结构体
- 《coredump问题原理探究》Linux x86版6.4节虚函数
- 《coredump问题原理探究》Linux x86版3.1节栈布局之概述
- 《coredump问题原理探究》Linux x86版3.3节栈布局之局部变量
- 一万以内的回文数
- 利用Gallery和ImageView实现图片浏览器
- 读《JavaServer Faces 核心编程(第3版)》一书的记录—— 第 3 章 导航——案例 javaquiz-rest
- android ResolveInfo运用
- XP局域网远程登录2003server的问题
- 《coredump问题原理探究》Linux x86版4.2节函数的逆向之顺序结构
- windows下的两个免费资源编辑器
- java 连接 sqlServer2008 图文详解
- 图的遍历大神的代码
- VB代码生成标准dll
- 我与黑莓共同成长!
- 删除ubuntu冗余的开机启动菜单
- 2012总结——数不尽的第一次...
- Servlet 运行原理