【学习逆向工程,分析机器代码】(二)(C++篇)
2007-04-27 16:16
911 查看
【学习逆向工程,分析机器代码】(二)(C++篇) by dreamerate 1、序 大家好!再一次和大家见面了!我这次要告诉大家的是,一个C++程序产生的机器代码到底长什么样?通过这些代码及注释加以分析,您应该能了解C++程序的一些底层机制及CRT内幕!^_^ 本篇算是根据ATField大侠的文章所衍生的续集!大家可访问ATField大侠的blog: http://blog.csdn.net/atfield/archive/2006/11/14/1382694.aspx,他可是一个很全面的高手哦! 切入主题,由ATField大侠提供的简单C++小程序原代码,本人略作小许修改并重新进行了一次编译,然后再用OllyDbg进行了跟踪分析。发现在反汇编这些代码出入很大哦!终究其原因:编译器的差别(我用VC++6.0E,他用的是VC++8.0)。 例如像D8H的这个分配过程换来的而是8H,就两个MACHINE WORD(32位CPU的机器字。一个机器字占4个字节): 第一个是指向本对象地址,第二个搞不清楚是用来做什么用的(郁闷……),有谁知道吗? 2、一个具体而微的C++小程序 包括内容:一个C++ entry point函数main及一个class。本文的中心思想是分析C++类机制。 ------------------------------------------------------------------------ 源程序如下: #include <windows.h> #include <stdio.h> class my_class { public: my_class() { m_member = 1; } void method( int n ) { m_member = n; } ~my_class() { m_member = 0; } private: int m_member; }; int main( int argc, char** argv ) { my_class a_class; printf( "I'm testor!" ); a_class.method( 0x111 ); return 0; } ------------------------------------------------------------------------ 3、编译 在XP SP2环境下,开一个cmd.exe,键入VC6,进入我们的test.cpp目录,键入bcpp test,完成编译。 以下是vc6.bat及bcpp.bat的内容: VC6.bat ----------------------------------------------------------------------- @echo off set VC6DIR=I:/Program Files/Microsoft Visual Studio/VC98 set include=I:/DXSDK/Include;%VC6DIR%/Include;%VC6DIR%/atl/include;%VC6DIR%/mfc/include set lib=I:/DXSDK/Lib;%VC6DIR%/lib;%VC6DIR%/mfc/lib set path=c:/;I:/Program Files/Microsoft Visual Studio/Common/MSDev98/Bin;%VC6DIR%/Bin set %VC6DIR%= echo on ----------------------------------------------------------------------- bcpp.bat ----------------------------------------------------------------------- @echo off if exist %1.obj del %1.obj if exist %1.exe del %1.exe cl /c /Gz /GX %1.cpp if not exist %1.obj goto EXITFLAG link /machine:x86 /subsystem:console %1.obj user32.lib kernel32.lib gdi32.lib if not exist %1.exe goto EXITFLAG %1.exe :EXITFLAG ----------------------------------------------------------------------- 4、逆向过程 打开OllyDBG,加载test.exe,然后在00401000地址设置断点。按下F9后我们来到断点处,接着便是F8一路逐行分析代码: -------- ---- ------------ ------------------------------------- ---------------------------------------------------- 地址 流程 机器代码 汇编代码 注释 -------- ---- ------------ ------------------------------------- ---------------------------------------------------- 00401000 /$ 55 push ebp ; 保存旧的ebp 00401001 |. 8BEC mov ebp, esp ; ebp保存当前栈的位置 00401003 |. 6A FF push -1 ; 建立SEH链. ERR结构第三成员 00401005 |. 68 69684000 push test.00406869 ; Structured Exception处理程序. ERR结构第二成员 0040100A |. 64:A1 0000000>mov eax, dword ptr fs:[0] ; fs:0指向当前线程的TEB 00401010 |. 50 push eax ; 我们将它备份起来并且设为ERR结构第一成员 00401011 |. 64:8925 00000>mov dword ptr fs:[0], esp ; 建立当前的SEH的ERR结构(利用栈) 00401018 |. 83EC 08 sub esp, 8 ; my_class a_class; 0040101B |. 8D4D F0 lea ecx, dword ptr ss:[ebp-10] ; a_class对象指针ECX ; 它指向值第一个private成员int m_member 0040101E |. E8 4D000000 call test.00401070 ; 呼叫构造函数 00401023 |. C745 FC 00000>mov dword ptr ss:[ebp-4], 0 ; 进入__try块,在Main中有一个隐式的__try/__except块 0040102A |. 68 40804000 push test.00408040 ; ASCII "I'm testor!" 0040102F |. E8 90000000 call test.004010C4 ; printf 00401034 |. 83C4 04 add esp, 4 ; 释放前一个CALL的push 00401037 |. 68 11010000 push 111 ; /Arg1 = 00000111 0040103C |. 8D4D F0 lea ecx, dword ptr ss:[ebp-10] ; | <- a_class对象指针ECX 0040103F |. E8 4C000000 call test.00401090 ; /a_class.method 00401044 |. C745 EC 00000>mov dword ptr ss:[ebp-14], 0 ; 有谁知道这个DWORD是用来干什么的吗? 0040104B |. C745 FC FFFFF>mov dword ptr ss:[ebp-4], -1 ; 标记TRY的正常结束 00401052 |. 8D4D F0 lea ecx, dword ptr ss:[ebp-10] ; a_class对象指针ECX 00401055 |. E8 56000000 call test.004010B0 ; 析构函数 0040105A |. 8B45 EC mov eax, dword ptr ss:[ebp-14] ; ?奇怪哦!最接近ret的eax应该是本函数的返回值! ; 直接在最尾test eax, eax不就行了吗? 为什么要这样... 0040105D |. 8B4D F4 mov ecx, dword ptr ss:[ebp-C] ; 恢复之前保存的TEB 00401060 |. 64:890D 00000>mov dword ptr fs:[0], ecx 00401067 |. 8BE5 mov esp, ebp ; 你知道... 00401069 |. 5D pop ebp 0040106A /. C3 retn ; 恢复CALL影响的STACK及定位EIP -------------------------------------------------------------------------------------------------- 00401070 /$ 55 push ebp ; my_class类构造函数 00401071 |. 8BEC mov ebp, esp 00401073 |. 51 push ecx 00401074 |. 894D FC mov dword ptr ss:[ebp-4], ecx 00401077 |. 8B45 FC mov eax, dword ptr ss:[ebp-4] 0040107A |. C700 01000000 mov dword ptr ds:[eax], 1 00401080 |. 8B45 FC mov eax, dword ptr ss:[ebp-4] 00401083 |. 8BE5 mov esp, ebp 00401085 |. 5D pop ebp 00401086 /. C3 retn -------------------------------------------------------------------------------------------------- 00401090 /$ 55 push ebp ; void my_class::method(int n) 00401091 |. 8BEC mov ebp, esp 00401093 |. 51 push ecx 00401094 |. 894D FC mov dword ptr ss:[ebp-4], ecx 00401097 |. 8B45 FC mov eax, dword ptr ss:[ebp-4] 0040109A |. 8B4D 08 mov ecx, dword ptr ss:[ebp+8] ; 参数int n 0040109D |. 8908 mov dword ptr ds:[eax], ecx 0040109F |. 8BE5 mov esp, ebp 004010A1 |. 5D pop ebp 004010A2 /. C2 0400 retn 4 -------------------------------------------------------------------------------------------------- 004010B0 /$ 55 push ebp ; my_class类析构函数 004010B1 |. 8BEC mov ebp, esp 004010B3 |. 51 push ecx 004010B4 |. 894D FC mov dword ptr ss:[ebp-4], ecx 004010B7 |. 8B45 FC mov eax, dword ptr ss:[ebp-4] 004010BA |. C700 00000000 mov dword ptr ds:[eax], 0 004010C0 |. 8BE5 mov esp, ebp 004010C2 |. 5D pop ebp 004010C3 /. C3 retn -------------------------------------------------------------------------------------------------- 004010C4 /$ 53 push ebx ; CRT函数printf 004010C5 |. 56 push esi 004010C6 |. BE 90804000 mov esi, test.00408090 004010CB |. 57 push edi 004010CC |. 56 push esi 004010CD |. E8 20050000 call test.004015F2 004010D2 |. 8BF8 mov edi, eax 004010D4 |. 8D4424 18 lea eax, dword ptr ss:[esp+18] 004010D8 |. 50 push eax 004010D9 |. FF7424 18 push dword ptr ss:[esp+18] 004010DD |. 56 push esi 004010DE |. E8 D9050000 call test.004016BC 004010E3 |. 56 push esi 004010E4 |. 57 push edi 004010E5 |. 8BD8 mov ebx, eax 004010E7 |. E8 93050000 call test.0040167F 004010EC |. 83C4 18 add esp, 18 004010EF |. 8BC3 mov eax, ebx 004010F1 |. 5F pop edi 004010F2 |. 5E pop esi 004010F3 |. 5B pop ebx 004010F4 /. C3 retn ------------------------------------------------------------------------------------------------------------------- 5、总结 懒得写了,哥们看注释吧!:) |
相关文章推荐
- 【学习逆向工程,分析机器代码】(一)(C语言篇)
- 【MyBatis学习15】MyBatis的逆向工程生成代码
- 利用Rational Rose进行C++代码和数据库逆向工程 结构分析
- <机器学习系统设计>第十章(上)----代码与错误分析
- MyBatis框架的学习(七)——MyBatis逆向工程自动生成代码
- 【MyBatis学习15】MyBatis的逆向工程生成代码
- Mybatis学习(14)-MyBatis的逆向工程生成代码
- 逆向工程核心原理学习笔记(十三):分析abex' crackme #1 的延伸:将参数压入栈
- 逆向工程核心原理学习笔记(十二):分析abex' crackme #1
- 逆向工程核心原理学习笔记(十三):分析abex' crackme #1 的延伸:将参数压入栈
- 机器学习之主成分分析PCA及代码示例
- MyBatis框架的学习(七)——MyBatis逆向工程自动生成代码
- 【MyBatis学习14】MyBatis的逆向工程生成代码
- (转)MyBatis框架的学习(七)——MyBatis逆向工程自动生成代码
- Mybatis学习(3):Mybatis逆向工程生成java代码
- 逆向工程核心原理学习笔记(十二):分析abex' crackme #1
- 机器学习之一:logistic回归分析(含Matlab代码)
- 【MyBatis学习15】MyBatis的逆向工程生成代码
- 【MyBatis学习15】MyBatis的逆向工程生成代码
- w3l.exe逆向之反汇编代码分析篇