首页
社区
课程
招聘
[原创](逆向)一个ReverseMe的完全分析
发表于: 2006-3-22 18:13 18490

[原创](逆向)一个ReverseMe的完全分析

2006-3-22 18:13
18490

一个简单ReverseMe的完全分析



这个ReverseMe是<<加密与解密>>第2版P89提到的ReverseMe01.exe, 但是书上并没有给出完全分析, 在本文中给出.


阅读本文之前读者应当熟悉窗口程序的基本结构和基本API函数


为了方便新手阅读, 代码尽量保持良好的可读性, 这样做同时也是因为本文是采用纯静态反汇编分析的方法


文章很菜, 还望各位不吝赐教



一. 工欲善其事, 必先利其器


首先准备好工具, 这里我们需要3样工具, 他们是:


1. Stud_PE或PEiD...............获取欲逆向文件的第一手信息, 包括编写语言, 是否加壳等


2. IDA.........................强大的逆向工程工具, 把它用在单纯的破解上可以说是杀鸡用牛刀了


3. MSDN........................我们是新手, 有不懂的地方它永远是最好的老师



二. 知彼知己, 百战不殆



工具准备好了, 可以正式开始了, 不过在开始之前, 我们要问自己以下几个问题:


1.这个程序行为如何?


运行之, 出现一小窗口, 上有一按钮和一文本框, 按钮上有

"not reversed"

几个字, 单击按钮会弹出对话框

"Ok, for now, mission failed"

.



2.这个程序是否加壳?是何语言编写?该语言编写的程序有什么特点?


Peid显示为无壳, 汇编语言编写, 汇编语言编写的程序反汇编结果基本与源码一致, 可读性很好.



3.这个程序用到了哪些API?各是干什么的?


用Peid查看其输入表, 结果如下, 我一一作简要的解释供参考, 详细解释请查阅Msdn


基本上都是很基本的窗口程序API



USER32.dll


    

DestroyWindow

  ord:141 rva: 00002010


    清除一个窗口并导致一个WM_DESTROY消息


    GetWindowTextA  ord:347 rva: 00002014


    获取窗口标题(或者按钮, 文本框)文本


    LoadCursorA  ord:407 rva: 00002018


    装载光标


    LoadIconA  ord:411 rva: 0000201C


    装载图标


    MessageBoxA  ord:443 rva: 00002020


    不用多说了, 大家都知道


    

PostQuitMessage

  ord:477 rva: 00002024


    在消息队列里加入一条WM_QUIT消息


    DispatchMessageA  ord:148 rva: 00002028


    向窗口过程分发消息, 窗口程序基本API之一


    GetMessageA  ord:296 rva: 0000202C


    取消息队列消息, 基本函数


    

SetFocus

  ord:555 rva: 00002030


    设置窗口焦点


    SetWindowTextA  ord:601 rva: 00002034


    设置窗口文本


    

ShowWindow

  ord:613 rva: 00002038


    设置窗口显隐状态


    

TranslateMessage

  ord:637 rva: 0000203C


    翻译消息


    

UpdateWindow

  ord:651 rva: 00002040


    刷新窗口


    DefWindowProcA  ord:131 rva: 00002044


    消息默认处理函数, 基本函数之一


    CreateWindowExA  ord:88 rva: 00002048


    建立窗口


    RegisterClassExA  ord:495 rva: 0000204C


    注册类


    SendMessageA  ord:528 rva: 00002050


    向窗口过程发送消息, 阻塞型函数


    


KERNEL32.dll


    GetModuleHandleA  ord:273 rva: 00002000


    获取模块句柄, 基本函数


    GetCommandLineA  ord:182 rva: 00002004


    获取命令行


    

ExitProcess

  ord:117 rva: 00002008


    退出进程



三. 实战



下面我们开始逆向之旅



我们目的是完全逆向这个程序, 由于程序很简单, 从入口来分析是合理的



         start           

proc

 near


.text:00401000                 

push

    NULL            

; lpModuleName


.text:00401002                 

call

    GetModuleHandleA


.text:00401007                 

mov

     hInstance, 

eax



.text:0040100C                 

call

    GetCommandLineA



.text:00401011                 

push

    SW_SHOWDEFAULT  

; nCmdShow


.text:00401013                 

push

    lpCmdLine       

; lpCmdLine


.text:00401019                 

push

    NULL            

; hPrevInstance


.text:0040101B                 

push

    hInstance       

; hInstance


.text:00401021                 

call

    WinMain



.text:00401026                 

push

    

eax

             

; uExitCode


.text:00401027                 

call

    

ExitProcess


.text:00401027 start           

endp



很标准的入口初始化过程: 首先获取本模块句柄, 然后获取命令行指针, 再启动WinMain主函数, 最后ExitProcess退出.


不知大家注意到没, 这个入口过程有一个小错误, 看出来了吗?就是那个lpCmdLine参数不正确, 应当push eax才对



我们看看WinMain里有什么



 

; int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPCSTR lpCmdLine,int nCmdShow)


.text:0040102C WinMain         

proc

 near               

; CODE XREF: start+21p


.text:0040102C


.text:0040102C hWnd            = 

dword

 

ptr

 -50h


.text:0040102C stMsg           = MSG 

ptr

 -4Ch


.text:0040102C stWndClassex    = WNDCLASSEXA 

ptr

 -30h


.text:0040102C hInstance       = 

dword

 

ptr

  8


.text:0040102C hPrevInstance   = 

dword

 

ptr

  0Ch


.text:0040102C lpCmdLine       = 

dword

 

ptr

  10h


.text:0040102C nCmdShow        = 

dword

 

ptr

  14h


.text:0040102C


.text:0040102C                 

push

    

ebp


.text:0040102D                 

mov

     

ebp

esp


.text:0040102F                 

add

     

esp

, -50h



.text:00401032                 

mov

     [

ebp

+stWndClassex.cbSize], 

SIZEOF

 WNDCLASSEX


.text:00401039                 

mov

     [

ebp

+stWndClassex.style], 3


.text:00401040                 

mov

     [

ebp

+stWndClassex.lpfnWndProc], 

offset

 WndProc


.text:00401047                 

mov

     [

ebp

+stWndClassex.cbClsExtra], 0


.text:0040104E                 

mov

     [

ebp

+stWndClassex.cbWndExtra], 0


.text:00401055                 

push

    [

ebp

+hInstance]


.text:00401058                 

pop

     [

ebp

+stWndClassex.hInstance]


.text:0040105B                 

mov

     [

ebp

+stWndClassex.hbrBackground], 0Fh + 1h


.text:00401062                 

mov

     [

ebp

+stWndClassex.lpszMenuName], 

offset

 aWhatmenu 

; "WhatMenu"


.text:00401069                 

mov

     [

ebp

+stWndClassex.lpszClassName], 

offset

 ClassName 

; "SupremeDickHead"



.text:00401070                 

push

    IDI_APPLICATION 

; lpIconName


.text:00401075                 

push

    NULL            

; hInstance


.text:00401077                 

call

    LoadIconA


.text:0040107C                 

mov

     [

ebp

+stWndClassex.hIcon], 

eax


.text:0040107F                 

mov

     [

ebp

+stWndClassex.hIconSm], 

eax



.text:00401082                 

push

    IDC_ARROW       

; lpCursorName


.text:00401087                 

push

    NULL            

; hInstance


.text:00401089                 

call

    LoadCursorA


.text:0040108E                 

mov

     [

ebp

+stWndClassex.hCursor], 

eax



以上一段代码初始化窗口类, 类名为

"SupremeDickHead"

, 窗口程序为WndProc, 由于反汇编代码已经最大程度的整理过了, 所以如果读者熟悉窗口程序的话应该很容易看明白, 我就不作解释了



.text:00401091                 

lea

     

eax

, [

ebp

+stWndClassex]


.text:00401094                 

push

    

eax

             

; WNDCLASSEXA *


.text:00401095                 

call

    RegisterClassExA



注册窗口类



.text:0040109A                 

push

    NULL            

; lpParam


.text:0040109C                 

push

    [

ebp

+hInstance] 

; hInstance


.text:0040109F                 

push

    NULL            

; hMenu


.text:004010A1                 

push

    NULL            

; hWndParent


.text:004010A3                 

push

    0C8h            

; nHeight


.text:004010A8                 

push

    12Ch            

; nWidth


.text:004010AD                 

push

    0C8h            

; Y


.text:004010B2                 

push

    0C8h            

; X


.text:004010B7                 

push

    80C80000h       

; dwStyle


.text:004010BC                 

push

    

offset

 Caption  

; "ReverseMe #1"


.text:004010C1                 

push

    

offset

 ClassName 

; "SupremeDickHead"


.text:004010C6                 

push

    0               

; dwExStyle


.text:004010C8                 

call

    CreateWindowExA


.text:004010CD                 

mov

     [

ebp

+hWnd], 

eax



创建窗口, 窗口标题为 

"ReverseMe #1"

, 没有菜单



.text:004010D0                 

push

    SW_SHOWNORMAL   

; nCmdShow


.text:004010D2                 

push

    [

ebp

+hWnd]      

; hWnd


.text:004010D5                 

call

    

ShowWindow



显示窗口



.text:004010DA                 

push

    [

ebp

+hWnd]      

; hWnd


.text:004010DD                 

call

    

UpdateWindow


.text:004010E2



刷新窗口



.text:004010E2 MessageLoop:                            

; CODE XREF: WinMain+DBj


.text:004010E2                 

push

    0               

; wMsgFilterMax


.text:004010E4                 

push

    0               

; wMsgFilterMin


.text:004010E6                 

push

    NULL            

; hWnd


.text:004010E8                 

lea

     

eax

, [

ebp

+stMsg]


.text:004010EB                 

push

    

eax

             

; lpMsg


.text:004010EC                 

call

    GetMessageA



.text:004010F1                 

or

      

eax

eax

        

;收到WM_QUIT消息就退出


.text:004010F3                 

jz

      short Exit



.text:004010F5                 

lea

     

eax

, [

ebp

+stMsg]


.text:004010F8                 

push

    

eax

             

; lpMsg


.text:004010F9                 

call

    

TranslateMessage



.text:004010FE                 

lea

     

eax

, [

ebp

+stMsg]


.text:00401101                 

push

    

eax

             

; lpMsg


.text:00401102                 

call

    DispatchMessageA



.text:00401107                 

jmp

     short MessageLoop



消息循环



.text:00401109


.text:00401109 Exit:                                   

; CODE XREF: WinMain+C7j


.text:00401109                 

mov

     

eax

, [

ebp

+stMsg.wParam]


.text:0040110C                 

leave


.text:0040110D                 

retn

    10h


.text:0040110D WinMain         

endp



这个WinMain是非常标准的窗口程序主函数, 很可惜, 没有什么特别之处, 我就不多说了, 如果读者还是不理解原理请参考Windows程序设计相关书籍, 论坛置顶帖有介绍的



重点在WndProc函数处, 下面我们一起来看看这个函数



; int __stdcall WndProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)


.text:00401110 WndProc         

proc

 near               

; DATA XREF: WinMain+14o


.text:00401110


.text:00401110 hWnd            = 

dword

 

ptr

  8


.text:00401110 Msg             = 

dword

 

ptr

  0Ch


.text:00401110 wParam          = 

dword

 

ptr

  10h


.text:00401110 lParam          = 

dword

 

ptr

  14h


.text:00401110


.text:00401110                 

push

    

ebp


.text:00401111                 

mov

     

ebp

esp


.text:00401113                 

cmp

     [

ebp

+Msg], WM_DESTROY


.text:00401117                 

jnz

     short loc_401125


        

;if (Msg == WM_DESTROY)


.text:00401119                 

push

    0               

; nExitCode


.text:0040111B                 

call

    

PostQuitMessage


.text:00401120                 

jmp

     return



如果窗口关闭则发送退出消息使主程序退出消息循环


 


.text:00401125 loc_401125:                             

; CODE XREF: WndProc+7j


.text:00401125                 

cmp

     [

ebp

+Msg], WM_CREATE


.text:00401129                 

jnz

     short loc_4011A1


        else if   (Msg == WM_CREATE)


.text:0040112B                 

push

    0               

; lpParam


.text:0040112D                 

push

    hInstance       

; hInstance


.text:00401133                 

push

    ID_EDIT         

; nControlID


.text:00401135                 

push

    [

ebp

+hWnd]      

; hWndParent


.text:00401138                 

push

    19h             

; nHeight


.text:0040113A                 

push

    0C8h            

; nWidth


.text:0040113F                 

push

    23h             

; Y


.text:00401141                 

push

    32h             

; X


.text:00401143                 

push

    50800080h       

; dwStyle


.text:00401148                 

push

    NULL            

; lpWindowName


.text:0040114A                 

push

    

offset

 aEdit    

; "edit"


.text:0040114F                 

push

    WS_EX_CLIENTEDGE 

; dwExStyle


.text:00401154                 

call

    CreateWindowExA


.text:00401159                 

mov

     hEdit, 

eax



在窗口中创建一个Edit控件



.text:0040115E                 

push

    hEdit           

; hWnd


.text:00401164                 

call

    

SetFocus



并设置焦点



.text:00401169                 

push

    NULL            

; lpParam


.text:0040116B                 

push

    hInstance       

; hInstance


.text:00401171                 

push

    ID_BUTTON       

; nControlID


.text:00401173                 

push

    [

ebp

+hWnd]      

; hWndParent


.text:00401176                 

push

    19h             

; nHeight


.text:00401178                 

push

    8Ch             

; nWidth


.text:0040117D                 

push

    46h             

; Y


.text:0040117F                 

push

    4Bh             

; X


.text:00401181                 

push

    50000001h       

; dwStyle


.text:00401186                 

push


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (10)
雪    币: 56043
活跃值: (21220)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
论坛上写ReverseMe文章不多,希望更多的朋友也参与进来。
2006-3-22 21:21
0
雪    币: 260
活跃值: (274)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
3
楼主,请问你的文字颜色是怎么样弄出来的
该不会是在网而上一个词一个词编辑的吧????
2006-3-24 19:37
0
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
4
最初由 andy00 发布
楼主,请问你的文字颜色是怎么样弄出来的
该不会是在网而上一个词一个词编辑的吧????

有加色工具
2006-3-24 19:44
0
雪    币: 260
活跃值: (274)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
5
好,多谢了!
2006-3-25 00:39
0
雪    币: 206
活跃值: (251)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
这么详细,辛苦了
2006-4-2 15:47
0
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
7
CreateWindowEx里的参数dwStyle = 50800080h怎么没有转换为符号

50000000h = 40000000h or 10000000h
40000000h = WS_CHILD
10000000h = WS_VISIBLE
800000h = WS_BORDER
80h = ES_AUTOHSCROLL
∴ 50800080h = WS_CHILD or WS_VISIBLE or WS_BORDER or  ES_AUTOHSCROLL

是不是因为ES_AUTOHSCROLL跟WS_XXX不在同一个enum里边,查找符号常量的时候找不到?这也不是很难啊,这个窗口是基于Edit类建立的,除了WS_XXX以外的风格那就肯定只能是ES_XXX了,只要找到等于80的ES_XXX常量,添加它所在的enum,然后把代码里的常数选择“Manual...”把手工转换的符号常数填进去就行了。
2006-8-31 12:04
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不得不回复啊,很受用,学到很多。支持一下。谢谢
2006-8-31 16:55
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
9
thebutterfly很少在这个版发帖子啊
2006-8-31 20:13
0
雪    币: 291
活跃值: (213)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
10
最初由 WAKU 发布
thebutterfly很少在这个版发帖子啊


嗯, 毕竟逆向破解只是我的业余爱好
2006-9-1 02:16
0
雪    币: 51
活跃值: (632)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
11
大佬 能提供一下reverseMe.exe吗
2019-5-6 08:51
0
游客
登录 | 注册 方可回帖
返回