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

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

2006-3-22 18:13
17585
一个简单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     ebpesp
.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      eaxeax        ;收到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     ebpesp
.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    offset aNotReversed ; "Not Reversed"
.text:0040118B                 push    offset aButton  ; "button"
.text:00401190                 push    0               ; dwExStyle
.text:00401192                 call    CreateWindowExA
.text:00401197                 mov     hButton, eax

在文本编辑控件的下面创建一个按钮

.text:0040119C                 jmp     return

以上一段是处理WM_CREATE消息的代码, 亦即窗口初始化代码. 这段代码创建了一个文本编辑控件和一个按钮, 就是主程序上所看到的两个控件

.text:004011A1
.text:004011A1 loc_4011A1:                             ; CODE XREF: WndProc+19j
.text:004011A1                 cmp     [ebp+Msg], WM_COMMAND
.text:004011A8                 jnz     loc_401317
        else if (Msg == WM_COMMAND)

以下是处理WM_COMMAND消息的代码, 冗长复杂, 后面我还会详细分析

.text:004011AE                 mov     eax, [ebp+wParam]
.text:004011B1                 cmp     [ebp+lParam], 0 ; Is this message from a control?
.text:004011B5                 jnz     loc_4012F6
.text:004011BB                 cmp     ax, ID_BUTTON   ; Yes, it is from a control
.text:004011BF                 jnz     short loc_4011EA

.text:004011C1                 push    offset String   ; "Edit Box Is Good Mmmmkay ?"
.text:004011C6                 push    hEdit           ; hWnd
.text:004011CC                 call    SetWindowTextA

.text:004011D1                 push    0               ; lParam
.text:004011D3                 push    '#'             ; wParam
.text:004011D5                 push    WM_KEYDOWN      ; Msg
.text:004011DA                 push    hEdit           ; hWnd
.text:004011E0                 call    SendMessageA

.text:004011E5                 jmp     return

.text:004011EA
.text:004011EA loc_4011EA:                             ; CODE XREF: WndProc+AFj
.text:004011EA                 cmp     ax, ID_EDIT
.text:004011EE                 jnz     short loc_401202
.text:004011F0                 push    NULL            ; lpString
.text:004011F2                 push    hEdit           ; hWnd
.text:004011F8                 call    SetWindowTextA
.text:004011FD                 jmp     return

这一段很有趣, 程序首先判断消息是否来自一个子窗口控件(什么?你问为什么?那么我问你, WM_COMMND消息的lParam是什么含义? 对, 发送消息的控件句柄, 如果不是来自控件这个参数就是0啦), 如果不是则分别处理消息来自按钮,文本控件和一个未知ID的情况, 如果消息来自按钮则把Edit控件的文本设置为:"Edit Box Is Good Mmmmkay ?", 然后向Edit控件发送一个WM_KEYDOWN消息. 如果消息来自Edit, 程序会清除Edit控件的内容
问题是, 明知消息不是来自控件却要处理消息来自控件的情况, 这是干什么? 还有....

.text:00401202
.text:00401202 loc_401202:                             ; CODE XREF: WndProc+DEj
.text:00401202                 cmp     ax, ID_WHATID
.text:00401206                 jnz     loc_4012EC

.text:0040120C                 mov     eaxoffset loc_40123B
.text:00401211                 jmp     eax

ID_WHATID(=3)是什么控件的ID? 不得而知. 如果这里跳走的话就会结束程序(下面会调用DestroyWindow函数)
到现在已经有很多疑问了, 我们不管, 继续向下看,

.text:00401213                 push    200h
.text:00401218                 push    offset szTextBuffer ; lpString
.text:0040121D                 push    hEdit           ; hWnd
.text:00401223                 call    GetWindowTextA

.text:00401228                 push    MB_OK           ; uType
.text:0040122A                 push    offset Caption  ; "ReverseMe #1"
.text:0040122F                 push    offset szTextBuffer ; lpText
.text:00401234                 push    NULL            ; hWnd
.text:00401236                 call    MessageBoxA

这一段代码是永远也不可能执行了(jmp eax), 它作用是获取Edit的内容并用一个MessageBox把获取的内容显示出来

.text:0040123B
.text:0040123B loc_40123B:                             ; DATA XREF: WndProc+FCo
.text:0040123B                 push    MB_OK           ; uType
.text:0040123D                 push    offset Caption  ; "ReverseMe #1"
.text:00401242                 push    offset aOkayForNowMiss ; "Okay, for now, mission failed !"
.text:00401247                 push    NULL            ; hWnd
.text:00401249                 call    MessageBoxA

显示一个"Okay, for now, mission failed !"对话框, 就是我们运行程序时看到的

.text:0040124E                 push    200h            ; nMaxCount
.text:00401253                 push    offset szTextBuffer ; lpString
.text:00401258                 push    hEdit           ; hWnd
.text:0040125E                 call    GetWindowTextA
.text:00401263                 mov     ecxeax

这时ecx存放有字符个数, 因为GetWindowTextA返回值(eax)为字符个数

.text:00401265                 xor     edxedx        ; edx 清零
.text:00401267                 or      ebx, 0FFFFFFFFh
.text:0040126A                 inc     ebx             ; ebx 清零

.text:0040126B                 mov     eaxoffset szTextBuffer

让eax指向字符串
怎么?要做字符串处理了呀, 此时eax指向字符串, ebx, edx为0

.text:00401270
.text:00401270 loc_401270:                             ; CODE XREF: WndProc+183j
.text:00401270                 mov     bl, [eax]
.text:00401272                 cmp     byte ptr [eax], 0
.text:00401275                 jz      short loc_401295
.text:00401277                 cmp     byte ptr [eax], '0'
.text:0040127A                 jl      short loc_401295
.text:0040127C                 cmp     byte ptr [eax], '9'
.text:0040127F                 ja      short loc_401295

验证字符串合法性, 如果发现了空字符串或者有除了0~9之外的字符就提示错误

.text:00401281                 add     edxebx        ;ebx和edx相加
.text:00401283                 shl     edx, 14h        ;相加的结果左移20位
.text:00401286                 add     edxecx        ;再和字符个数相加
.text:00401288                 inc     eax
.text:00401289                 add     ecx, -1        ;处理下一个字符
.text:0040128C                 test    edxedx
.text:0040128E                 jnz     short loc_401291
.text:00401290                 inc     edx        ;edx如果是0的话则设置为1
.text:00401291
.text:00401291 loc_401291:                             ; CODE XREF: WndProc+17Ej
.text:00401291                 test    ecxecx        ;结束否?
.text:00401293                 jnz     short loc_401270

以上一段算法可以用C语言描述为:

int i = NumberOfChars;
char* str = StringFromEditControl;
int tmp = 0;

do {
    tmp += (int) *str;
    tmp <<= 20;
    tmp += i;
    str++;
    i--;
    if (tmp == 0) tmp++;
}
while (i != 0);

.text:00401295
.text:00401295 loc_401295:                             ; CODE XREF: WndProc+165j
.text:00401295                                         ; WndProc+16Aj ...
.text:00401295                 test    edx, 0        
.text:0040129B                 jg      short loc_4012B6
.text:0040129D                 jz      short loc_4012CB

.text:0040129F                 push    MB_OK               ; uType
.text:004012A1                 push    offset Caption  ; "ReverseMe #1"
.text:004012A6                 push    offset aThatNotANumber ; "That not a number ! CHEATHER !"
.text:004012AB                 push    NULL               ; hWnd
.text:004012AD                 call    MessageBoxA
.text:004012B2                 leave
.text:004012B3                 retn    10h

test edx, 0 ??!! 这意味着jg永远不能执行而jz会执行, 不过实际上这两个跳转之后都有一句jmp到ret处, 实际上都一样

.text:004012B6
.text:004012B6 loc_4012B6:                             ; CODE XREF: WndProc+18Bj
.text:004012B6                 jmp     short locret_4012E0

.text:004012B8                 push    MB_OK
.text:004012BA                 push    offset Caption  ; "ReverseMe #1"
.text:004012BF                 push    offset aGoodNumber ; "Good Number"
.text:004012C4                 push    NULL               ; hWnd
.text:004012C6                 call    MessageBoxA
.text:004012CB
.text:004012CB loc_4012CB:                             ; CODE XREF: WndProc+18Dj
.text:004012CB                 jmp     short locret_4012E0
 
.text:004012CD                 push    MB_OK
.text:004012CF                 push    offset Caption  ; "ReverseMe #1"
.text:004012D4                 push    offset aBadNumber ; "Bad Number"
.text:004012D9                 push    NULL               ; hWnd
.text:004012DB                 call    MessageBoxA
.text:004012E0
.text:004012E0 locret_4012E0:                          ; CODE XREF: WndProc:loc_4012B6j
.text:004012E0                                         ; WndProc:loc_4012CBj
.text:004012E0                 leave
.text:004012E1                 retn    10h
 
.text:004012E4                 pop     ebp
.text:004012E5                 push    eax
.text:004012E6                 leave
.text:004012E7                 retn    10h
 
.text:004012EA                 jmp     short return
 
.text:004012EC
.text:004012EC loc_4012EC:                             ; CODE XREF: WndProc+F6j
.text:004012EC                 push    [ebp+hWnd]      ; hWnd
.text:004012EF                 call    DestroyWindow
.text:004012F4                 jmp     short return
 
刚才提到过了

.text:004012F6
.text:004012F6 loc_4012F6:                             ; CODE XREF: WndProc+A5j
.text:004012F6                 cmp     ax, ID_BUTTON
.text:004012FA                 jnz     short loc_401315
.text:004012FC                 shr     eax, 10h
.text:004012FF                 or      axax
.text:00401302                 jnz     short loc_401315

.text:00401304                 push    0               ; lParam
.text:00401306                 push    ID_WHATID       ; wParam
.text:00401308                 push    WM_COMMAND      ; Msg
.text:0040130D                 push    [ebp+hWnd]      ; hWnd
.text:00401310                 call    SendMessageA

.text:00401315
.text:00401315 loc_401315:                             ; CODE XREF: WndProc+1EAj
.text:00401315                                         ; WndProc+1F2j
.text:00401315                 jmp     short return
 
这里终于知道ID_WHATID的来源了, 原来是这个SendMessage函数!

.text:00401317
.text:00401317 loc_401317:                             ; CODE XREF: WndProc+98j
.text:00401317                 push    [ebp+lParam]    ; lParam
.text:0040131A                 push    [ebp+wParam]    ; wParam
.text:0040131D                 push    [ebp+Msg]       ; Msg
.text:00401320                 push    [ebp+hWnd]      ; hWnd
.text:00401323                 call    DefWindowProcA
.text:00401328                 leave
.text:00401329                 retn    10h
 
.text:0040132C
.text:0040132C return:                                 ; CODE XREF: WndProc+10j
.text:0040132C                                         ; WndProc+8Cj ...
.text:0040132C                 xor     eaxeax
.text:0040132E                 leave
.text:0040132F                 retn    10h
.text:0040132F WndProc         endp

四. 回顾

程序结束了, 现在回过头来看看程序中的微妙之处.

程序首先用标准的方法建立了一个窗口, 在窗口函数中, 程序处理了WM_CREATE, WM_DESTROY和WM_COMMAND这3个消息. 在处理WM_CREATE时, 程序分别建立了一个Edit控件和一个按钮; 在WM_COMMAND消息的处理中, 如果程序侦测到消息是按钮发出的, 则以ID_WHATID(等于3)为WPARAM, 0为LPARAM向自身发送WM_COMMAND消息. 由于在WM_COMMAND消息处理的开头, 程序会判断消息的来源, 仅当消息不是从子窗口控件发出时才处理(004011AE和004011FD之间的代码实际上不会执行), 所以00401213到004012EA的这段代码(就是那段算法代码)名义上是处理ID为ID_WHATID的"控件"发出的消息, 实质上是按钮消息处理过程的延续而已
关于那段算法代码, 由于不管结果是多少最后都要和0做and运算, 结果毫无疑问都是0, 亦即那句jz将肯定会执行. 所以这段算法是没有多大意义的. 但是这个程序毕竟是ReverseMe, 就是要求大家把不正确的内容修改正确. 至于到底怎么修改就看大家自由发挥了.

明白了这些, 相信大家再看<<加密与解密>>第2版P89~P91内容时应该觉得不难了吧

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

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

有加色工具
雪    币: 260
活跃值: (214)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
andy00 4 2006-3-25 00:39
5
0
好,多谢了!
雪    币: 210
活跃值: (136)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cmosa 2006-4-2 15:47
6
0
这么详细,辛苦了
雪    币: 433
活跃值: (176)
能力值: ( LV13,RANK:1250 )
在线值:
发帖
回帖
粉丝
冲天剑 31 2006-8-31 12:04
7
0
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...”把手工转换的符号常数填进去就行了。
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
moyer 2006-8-31 16:55
8
0
不得不回复啊,很受用,学到很多。支持一下。谢谢
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
WAKU 7 2006-8-31 20:13
9
0
thebutterfly很少在这个版发帖子啊
雪    币: 291
活跃值: (208)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
thebutterfly 5 2006-9-1 02:16
10
0
最初由 WAKU 发布
thebutterfly很少在这个版发帖子啊


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