当前位置:文档之家› 逆向分析说明

逆向分析说明

------------------------------------------------------------------------------------------------
---------------逆向分析训练练习说明 2010.02.28-----------------
------------------------------------------------------------------------------------------------

00402030 /> \55 PUSH EBP //保存当前堆栈指针 相当于{ //此时在栈顶指向的是保存上一个函
数CALL后的下一个地址,PUSH EBP 后,此时 [ESP+4]就是这个函数的
返回地址。就是常说的保存堆栈环境。
00402031 |. 8BEC MOV EBP,ESP //把当前栈顶的值放EBP里 相当于把当前函数的EBP设当前栈顶的值,
MOV EBP,ESP 后,二个寄存器的值相等,都是同时指向栈顶。这时的
[ESP+4]就是程序的返回地址 [EBP+4] 也就是返回地址
上面的功能是保护上一个调用的EBP堆栈基址和把这一个函数的EBP的
值为ESP的值 就是把这个函数的EBP地址移到ESP上,现在栈底和栈顶
是处于同一个地址上的,函数开始后,寄存器或是参数压入堆栈后,
----------------------------------------------------------------EBP指向的就是栈底,ESP指向的就是栈顶。
00402033 |. 6A FF PUSH -1 //定义一个指针变量 压入堆栈 这个变量的值是FFFFFFFF 我在这里
[EBP-4]就是这个临时变量的地址,也就是保存构造函数和析构函数的
指针。
00402035 |. 68 5B3B4000 PUSH ReverseM.00403B5B //SEH 处理程序安装 //异常处理链安装程序 这里的PUSH 00403B5B
实际上是把异常处理的入口地址压入堆栈 [EBP-8]就是调用这个异常
处理程序的系统回调函数,当发生错误的时候调用[EBP-8]这个系统回
调函数来处理异常,处理的顺序是根据链表层的顺序来进行处理的。
如果处理成功,程序可以继续执行代码,如果处理失败就是弹出系统
错误信息,程序结束。
0040203A |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0] //把FS:[0] 当前线程的结构化异常处理结构(SEH)的地址放到EAX里
FS:[0]实际上就是指向原来的的异常处理链地址。
00402040 |. 50 PUSH EAX //压入EAX 保存 表示把原来的异常处理链地址进行保存起来

----------------------------------------------------------------把原先的异常处理结构

体的指针保护起来
00402041 |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP //把当前异常处理链的地址指向ESP指针 现在的异常入口指向栈顶

----------------------------------------------------------------
00402048 |. 83EC 50 SUB ESP,50 //把ESP指针向上移动20个地址 1个地址是4个字节 相当于现在的ESP=
原来的ESP+50
0040204B |. 53 PUSH EBX //保存原来EBX基地址寄存器
0040204C |. 56 PUSH ESI //保存原来ESI源变址寄存器
0040204D |. 57 PUSH EDI //保存原来EDI目的变址寄存器
0040204E |. 51 PUSH ECX //保存原来ECX寄存器
到这里后算是把堆栈环境保护好 等程序结束里弹出保存信息,恢复
----------------------------------------------------------------堆栈,继续程序运行,已达到程序的完整性。
0040204F |. 8D7D A4 LEA EDI,DWORD PTR SS:[EBP-5C] //把EDI的指针指向 [EBP-5C] 相当于 [ESP-50-0C] 0C=12个字节 是
前面压入三个堆栈的地址数 EDI的指针到了[ESP+20]这个位置 实际
上就是到了压入EBX后EBX的值的指向地址。
00402052 |. B9 14000000 MOV ECX,14 //把ECX寄存器的值赋于14 这时的ECX就是当做循环计数器来使用
00402057 |. B8 CCCCCCCC MOV EAX,CCCCCCCC //把EAX的值写入8个C 相当于4个字节 在汇编里1个字节C表示一个
INT3中断命令
0040205C |. F3:AB REP STOS DWORD PTR ES:[EDI] //在堆栈里的EBX指向的地址后面写入56个int3中断,相当于写了14个
地址的int3中断命令 当写完14个地址的int3中断后,这时的EDI的指
针实际上就是指向了我们在堆栈里原来保存上一个异常处理链地址的
也就是[EBP-C]的地址 这里我们可以把[EBP-C]这个指针看做是上一个
异常处理链结构体的地址指针,[EBP-8]可以看做是这个异常处理链结
构体内的回调函数,[EBP-4]可以看做是这个结构体内的成员变量。
0040205E |. 59 POP ECX //ECX计数器寄存器结束。恢复以前的ECX寄存器的值。此时ESP指针向
下移一个地址 当于现在的ESP地址=原来的ESP+4
0040205F |. 894D F0 MOV DWORD PTR SS:[EBP-10],ECX //继续保护ECX寄存器。就是保存到[EBP-10]这个地址里,原来的int3
中断命令让ECX的值覆盖,相当于在这个地址上取消了4个int3中断命
令。此时的最后一个中断地址就是指向了[EBP-

14]这个地址上了。
----------------------------------------------------------------此时完成所有的环境保护。
00402062 |. 8D4D EC LEA ECX,DWORD PTR SS:[EBP-14] //把最后一个中断地址指针寄存器ECX指向[EBP-14]这个地址 现在ECX
指向了最后一个int3中断命令的地址 实际上ECX就是指向最后一个中
断命令地址的寄存器指针,如果ECX的值发生了变化,最后一个中断地
址也会跟着发生变化。
00402065 |. E8 9E030000 CALL //调用MFC类构造函数 在这里我们可以看做是定义第一个MFC类成员变
量。我在这里可以先看做是 局部变量1 这时就会把这个函数调用的地
址写到[EBP-14]这个地址里,最后一个中断地址就会到[EBP-18]那个
地址上去。
0040206A |. C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0 //把0放到指针变量里 [EBP-4]就是用来这个构造函数的指针,现在可
以看做是指向第一个构造函数的指针。如果要析构这个函数,指针的
指向就是0
------------------------------------------------------------------
00402071 |. 8D4D E8 LEA ECX,DWORD PTR SS:[EBP-18] //把最后一个中断地址指针寄存器ECX指向[EBP-18]这个地址
00402074 |. E8 8F030000 CALL //调用MFC类构造函数 在这里我们可以看做是定义第二个MFC类成员
变量。我在这里可以先看做是 局部变量2 调用后,会把这个调用地址
写到[EBP-18]这个地址上,最后一个中断地址就会跳到[EBP-1C]那个
地址去。
00402079 |. C645 FC 01 MOV BYTE PTR SS:[EBP-4],1 //把1放到指针变量里 [EBP-4]就是用来这个构造函数的指针,现在可
以看做是指向第二个构造函数的指针。如果要析构这个函数,指针的
指向就是1
-------------------------------------------------------------------
0040207D |. 68 40544100 PUSH ReverseM.00415440 //把00415440这个地址压入堆栈 而这个地址上的值是按Reverse反顺
压入的HEX字符
00402082 |. 8D4D E4 LEA ECX,DWORD PTR SS:[EBP-1C] //把最后一个INT3中断命令指针寄存器的指针移到[EBP-1C]这个地址
上,所以现在后一个INT3中断命令的地址是[EBP-1C]
00402085 |. E8 F0030000 CALL //调用MFC类构造函数 参数就是00415440这个地址,可以在这里看做
是定义了 局部变量3,并且把这个类成员变量初始化,这个变量的值
就是00415440取出来的反顺的值,我们在这里把他看做是 局部变量3
0040208A |. C645 FC 02 MOV BYTE PTR SS:[EBP-4],2 //把2放到指针变量里 [EBP-4]就是用来这个构造函数

的指针,现在可
以看做是指向第三个构造函数的指针。如果要析构这个函数,指针的
指向就是2
--------------------------------------------------------------------
0040208E |. 6A 01 PUSH 1 //压入一个为1的整数型参数 可以在这里看做是 参数是真或是1
00402090 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10] //把[EBP-10]地址上的值给ECX 实现上是取回先给[EBP-10]这个地址
上的数据,因为开始是ECX传进去的,现在还是ECX取出来,就应该是
做为下一个函数的调用寄存器来继续使用。
00402093 |. 81C1 E0000000 ADD ECX,0E0 //把ECX加0E0 我在这里可以理解成一个新的地址或是值
00402099 |. E8 D6030000 CALL //调用MFC类函数 执行函数过程。
-------------------------------------------------------------------
0040209E |. 8D45 EC LEA EAX,DWORD PTR SS:[EBP-14] //取出[EBP-14]这个地址给EAX 这个[EBP-14]就是在先定义局部变量1
时压入堆栈的地址。
004020A1 |. 50 PUSH EAX //压入这个地址
004020A2 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10] //取出先前压到堆栈[EBP-10]的值给ECX 实际上就是把以前ECX压入堆
栈的值取出来,还原ECX的值,让这个ECX寄存器给新的调用函数使用
004020A5 |. 81C1 E0000000 ADD ECX,0E0 //把取出来的ECX的值+0E0 也就是[EBP-10]地址里的值+0E0 这个新的
值是要做为调用寄存器让新的函数使用的。
004020AB |. E8 BE030000 CALL //调用MFC类函数,参数是这个MFC类的地址。因为是用这个类成员的
地址作参数,这个函数就应该是设置或是取这个局部变量的属性或是
事件相关的函数。
-------------------------------------------------------------------
004020B0 |. 6A 01 PUSH 1 //再压入一个为1的整数型参数 可以在这里看做是 参数是真的参数
004020B2 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10] //还原ECX的值,再做为新函数的寄存器使用。
004020B5 |. 81C1 A0000000 ADD ECX,0A0 //把存在ECX寄存器里的值+0A0
004020BB |. E8 B4030000 CALL //调用MFC类函数 函数的参数是1 或是真 函数功能分析同上。
-------------------------------------------------------------------
004020C0 |. 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18] //取出局部变量2的地址放到EAX里
004020C3 |. 50 PUSH EAX //把个局部变量2的地址压入堆栈
004020C4 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10] //还原ECX寄存器

的值,供新的函数使用
004020C7 |. 81C1 A0000000 ADD ECX,0A0 //把存在ECX寄存器的值+0A0
004020CD |. E8 9C030000 CALL //调用MFC类函数 把局部变量2的地址做为参数来调用,函数功能分
析同上。
--------------------------------------------------------------------
004020D2 |. C645 FC 01 MOV BYTE PTR SS:[EBP-4],1 //把析构指针变量指向1 就是定义的局部变量2
004020D6 |. 8D4D E4 LEA ECX,DWORD PTR SS:[EBP-1C] //取出局部变量2的地址
004020D9 |. E8 0C030000 CALL //调用MFC类成员函数 参数是局部变量2的地址,进行析构函数。
004020DE |. C645 FC 00 MOV BYTE PTR SS:[EBP-4],0 //把析构指针变量指向0 就是定义的局部变量1
004020E2 |. 8D4D E8 LEA ECX,DWORD PTR SS:[EBP-18] //取出局部变量1的地址
004020E5 |. E8 00030000 CALL //调用MFC类成员函数 参数是局部变量1的地址,进行析构函数。
004020EA |. C745 FC FFFFF>MOV DWORD PTR SS:[EBP-4],-1 //将指针变量还原成FFFF
004020F1 |. 8D4D EC LEA ECX,DWORD PTR SS:[EBP-14] //还原ECX寄存器的值,当调用寄存器供新的函数使用
004020F4 |. E8 F1020000 CALL //用MFC类函数 把局部变量2的地址做为参数来调用,函数功能分
析同上。
004020F9 |. 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-C] //取出保存在堆栈里的上一个异常处理链程序的地址
004020FC |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX //设置异常处理链处理程序的地址为上一个异常处理链程序的入口点
00402103 |. 5F POP EDI //还原EDI变址寄存器
00402104 |. 5E POP ESI //还原ESI变址寄存器
00402105 |. 5B POP EBX //还原EBX基地址寄存器 还原堆栈,POP寄存器后 ESP的指针就向下移
动,把EBX寄存器POP出去后,ESP的指针正好指向开始写入INT3中断命
令的指向地址的地方。
00402106 |. 83C4 5C ADD ESP,5C //把ESP指针向下移动17个地址 ESP移动后,正好和EBP相同。同时指
向栈底。为什么移动17个地址,可以通过计算多少个push和多少个
pop来计算要增加的地址偏移。
00402109 |. 3BEC CMP EBP,ESP //把EBP-ESP的值放到SF和OF二个标志寄存器里 如果为0为没有溢出
如果是正数则表示有溢出现象
0040210B |. E8 70030000 CALL //进入堆栈检查程序,检查ESP有没有发生溢出,如果发生溢出,程序
发生错误,提示溢出

错误,程序关闭
00402110 |. 8BE5 MOV ESP,EBP //如果没有发生溢出,则把把EBP里的值赋给ESP指针,就是相当于把
ESP指针移到EBP里保存的值的地址,而EBP里的值就是下一个ESP要指
向的地址。此时ESP指向EBP地址
00402112 |. 5D POP EBP //还原原来的堆栈情况,POP后,EBP的值就是原来的栈底,ESP就是指
向的地址就是程序的返回地址。
00402113 \. C3 RETN //结束整个子程序 相当于 } 函数结束口 此时程序跳到一下个返回
地址。继续新的子程序的执行。



相关主题
文本预览
相关文档 最新文档