本帖最后由 cu629944 于 2012-4-1 13:20 编辑
【文章标题】: 菜鸟学逆向——简单的反汇编阅读与逆向(1)
【文章作者】: Silence(cu629944,等试用期通过,我会修改ID为Silecne)
【作者邮箱】: mohen_ng@sina.cn
【下载地址】: 自己搜索下载
【编写语言】: VC++6.0
【操作平台】: WIN 7
【软件介绍】: IDA VC++6.0
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
我会写一个系列的文,希望大家能够支持,这是第一篇
我们先启动VC++6.0,输入下面的程序
程序很短,大家看我输入一次,留意成对编码原则,防止对低级的错误
#include <stdio.h>
void Silence(int a,int b)
{
int c =a + b;
}
void main()
{
Silence(1,2);
}
一个简单的有2个形参的Silence()函数,接着在main()主函数调用Silence()函数。
编译成Debug模式,Realse版本会把调试信息等去掉。
我们用VC6.0自带的调试器,复制一个反汇编代码出来(为什么不立即用IDA看呢?因为VC6.0会把源码和反汇编代码一一对应起来,方便我们在IDA对照查看)
void main()
9: {
00401060 push ebp
00401061 mov ebp,esp
00401063 sub esp,40h
00401066 push ebx
00401067 push esi
00401068 push edi
00401069 lea edi,[ebp-40h]
0040106C mov ecx,10h
00401071 mov eax,0CCCCCCCCh
00401076 rep stos dword ptr [edi]
10: Silence(1,2);
00401078 push 2
0040107A push 1
0040107C call @ILT+5(_Silence) (0040100a)
00401081 add esp,8
11: }
00401084 pop edi
00401085 pop esi
00401086 pop ebx
00401087 add esp,40h
0040108A cmp ebp,esp
0040108C call __chkesp (004010b0)
00401091 mov esp,ebp
00401093 pop ebp
00401094 ret
然后我们载入IDA里面。IDA非常智能,载入分析完成后,直接停到了我们的main()函数处。我们就离线分析下他的每句话的作用。
; Attributes: bp-based frame
_main proc near
var_40= byte ptr -40h
push ebp ; 保存EBP
mov ebp, esp ; 原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
; 此时EBP寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),
; 从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,
; 而该地址处又存储着上一层函数调用时的EBP值!
sub esp, 40h ; 为局部变量申请空间,大小为40h(注意40h是16进制数,用IDA看看转换成10进制为多少,为64)
push ebx
push esi
push edi
lea edi, [ebp-40h] ; Var_40是IDA自己分析出来的,表示为局部变量,就是SUB ESP,40h分配的40h个大小,目的是保存局部变量的区域
mov ecx, 10h
mov eax, 0CCCCCCCCh ; 从ebp-40h开始的区域初始化成全部0CCCCCCCCh,就是int3断点
rep stosd ; 拷贝字符串,初始化局部变量空间
; 以上的语句就是在栈中开辟一块空间放局部变量
; 然后把这块空间都初始化为0CCCCCCCCh,就是int3断点,一个中断指令。
; 因为局部变量不可能被执行,执行了就会出错,这时候发生中断提示开发者。
push 2 ;
; 参数2入栈
; 这里就是我们在test.c的源代码里面写的那个Silence(1,2);函数,这里有一个很重要的概念
; 就是调用约定,在 c/c++ 中, 函数的默认调用约定为 cdecl, 它约定参数从右到左入栈,
; 由调用者清理堆栈, 所谓清理, 即调整ESP的值, 使得原来的局部数据不再属于栈
;
push 1 ; 参数1入栈
;
call Func__Silence ; 调用我们定义的Silence函数
; 其实call 指令调用一个过程, 但它有一个小动作
; 在参数入栈以后, 被调用函数执行 之前, 它会将当前函数的下一条指令地址, 即EIP的值压入
;
add esp, 8 ; 调用完函数后恢复/释放栈
pop edi ; 以下三句都是恢复三个保存的寄存器
pop esi
pop ebx
add esp, 40h ; 这句对应的是上面的SUB ESP,40h,恢复堆栈,
cmp ebp, esp ; 检测ESP是否恢复正常,如果不正常将调用下面的Chkesp
call __chkesp ; 处理可能出现的堆栈错误(如果出错,将陷入debug)。
mov esp, ebp ; 还记得上面那句mov ebp,esp吗?EBP里面保存着我们初始状态的ESP值,这句是将栈顶指针放回esp
pop ebp ; 恢复原来的ebp和esp,让上一个调用的函数正常使用
retn ; 将返回地址存入EIP, 转移流程
_main endp ;
; 以上那部分代码在VC的Debug调试版才会有,主要检查栈是否被破坏了。这样就能及时在你出错的地方停下了告诉你。
; 发行版自动消除这些代码(调试产生的)。
; 如果函数有返回值,返回值将放在eax返回(这就是很多软件给秒杀爆破的原因了,因为eax的返回值是可以改的)
下面来看看Silence()函数
; Attributes: bp-based frame
_Silence proc near
var_44= byte ptr -44h
var_4= dword ptr -4
arg_0= dword ptr 8
arg_4= dword ptr 0Ch
push ebp ; 下面的这几句和上面我们分析的一样,所以我们对Silence函数只分析不同的地方
mov ebp, esp
sub esp, 44h ; 这里将局部变量的大小分配为44h
push ebx
push esi
push edi
lea edi, [ebp-44h]
mov ecx, 11h
mov eax, 0CCCCCCCCh
rep stosd
mov eax, [ebp+8] ; 取第一个参数放到EAX里面,即参数a
add eax, [ebp+0Ch] ; 与保存在EBP+0Ch里面的参数b相加
mov [ebp-4], eax ; 返回值放到ebp - 4里面,即最终结果放到参数c里面
;
; 一般而言,ss:[ebp+4]处为返回地址
; ss:[ebp+8]处为第一个参数值(这里是a),ss:[ebp+0Ch]处为第二个参数(这里是b,这里8+4=12=0Ch)
; ss:[ebp-4]处为第一个局部变量(这里是c),ss:[ebp]处为上一层EBP值
; ebp和函数返回值是32位,所以占4个字节
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
retn
_Silence endp
到此处,我们就将这些代码翻译完毕了。有很多收获。
根据我们这些分析,我们就可以逆向出我们的源码了(只看IDA反汇编的部分哈!):
我们可以在IDA里面看到main函数没有返回值,和Cdecl调用约定的规则,我们就可以恢复出来main函数的代码。
void main()
{
Silence(1,2);
}
我们分析Silecne函数的反汇编代码,可以看出在每个局部变量里面,都是用的[EBP - 4],[EBP + 8] ,[EBP + 0Ch]等,我们可以发现都是4的倍数,我们知道INT类型,占4个字节,且这个函数有三个参数,而且也没有返回值,下面我们就可以恢复Silence的函数部分的代码:
void Silence(int a,int b)
{
int c = a + b;
}
然后我们整理下,就可以得到完整的代码:
void Silence(int a,int b)
{
int c = a +b;
}
void main()
{
Silence(1,2);
}
--------------------------------------------------------------------------------
【经验总结】
里面讲了比较重要的,调用约定,大家可以百度下看看什么叫做调用约定。还有局部变量等是怎么在汇编中存在的,已经返回值的保存地址,及如何对返回值修改达到对程序的爆破。这就是一个简单的反汇编阅读和逆向了。我们可以恢复出我们的代码。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于吾爱破解技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2012年04月01日 11:38:05
|