欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

逆向改出不死版扫雷

程序员文章站 2022-06-28 08:28:13
文章作者:Fypher  摘自于邪恶八进制 上个学期搞过一段时间逆向,把windows的扫雷改成了个不死版的(纯属无聊消遣,呵呵)。今晚睡不着,把当时的思路总结了一下写出来。 首...

文章作者:Fypher  摘自于邪恶八进制

上个学期搞过一段时间逆向,把windows的扫雷改成了个不死版的(纯属无聊消遣,呵呵)。
今晚睡不着,把当时的思路总结了一下写出来。

首先OD载入,来到此处:
复制内容到剪贴板
代码:
01003F90   . E8 5BE2FFFF   CALL winmine.010021F0                    ; winmine.010021F0
01003F95   . 8BF0          MOV ESI,EAX
01003F97   . 8975 84       MOV DWORD PTR SS:[EBP-7C],ESI
01003F9A   . 395D E4       CMP DWORD PTR SS:[EBP-1C],EBX
01003F9D   . 75 07         JNZ SHORT winmine.01003FA6
01003F9F   . 56            PUSH ESI                                 ; /status
01003FA0   . FF15 94110001 CALL DWORD PTR DS:[<&msvcrt.exit>]       ; exit
01003FA6   > FF15 9C110001 CALL DWORD PTR DS:[<&msvcrt._cexit>]     ; [msvcrt._cexit
由C运行期库的退出函数可知,winmine.010021F0应该是扫雷的main函数,跟入!

来到窗口注册的地方:
复制内容到剪贴板
代码:
0100228B |. 50            PUSH EAX                                 ; /pWndClass = 0007FED0
0100228C |. 897D D4       MOV DWORD PTR SS:[EBP-2C],EDI            ; |
0100228F |. 8975 D8       MOV DWORD PTR SS:[EBP-28],ESI            ; |
01002292 |. FF15 CC100001 CALL DWORD PTR DS:[<&USER32.RegisterClas>; RegisterClassW
这是RegisterClass的原型:ATOM RegisterClass( CONST WNDCLASS *lpWndClass);

其参数是指向WNDCLASS的指针。我们MSDN一下:
复制内容到剪贴板
代码:
typedef struct {
    UINT style;
    WNDPROC lpfnWndProc;
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance;
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;
呵呵,4~7字节就是窗口回调函数的地址!马上到0007FED0去看看:
复制内容到剪贴板
代码:
0007FED0 00 00 00 00 C9 1B 00 01 ....?.
嘿嘿~回调函数地址是0x01001BC9~跳过去看看回调函数吧。下面是一些比较有趣的消息处理case~:
复制内容到剪贴板
代码:
01001FDF |> 33FF          XOR EDI,EDI                              ; 左/中/右键弹起; Cases 202 (WM_LBUTTONUP),205 (WM_RBUTTONUP),208 (WM_MBUTTONUP) of switch 01001F5F
01001FE1 |. 393D 40510001 CMP DWORD PTR DS:[1005140],EDI
01001FE7 |. 0F84 BC010000 JE winmine.010021A9                      ; 如果是右键弹起(什么都不做,因为是在按下时画旗)
01001FED |> 893D 40510001 MOV DWORD PTR DS:[1005140],EDI
01001FF3 |. FF15 D8100001 CALL DWORD PTR DS:[<&USER32.ReleaseCaptu>; [ReleaseCapture
01001FF9 |. 841D 00500001 TEST BYTE PTR DS:[1005000],BL
01001FFF |. 0F84 B6000000 JE winmine.010020BB
01002005 |. E8 D7170000   CALL winmine.010037E1                    ; 处理左键
跟进去!毕竟我们最关心的是左键,如果点到了雷怎么办?嘿嘿~
复制内容到剪贴板
代码:
010038B1 |. E8 5CFCFFFF   CALL winmine.01003512
再跟!
复制内容到剪贴板
代码:
01003512 /$ 8B4424 08     MOV EAX,DWORD PTR SS:[ESP+8]
01003516 |. 53            PUSH EBX
01003517 |. 55            PUSH EBP
01003518 |. 56            PUSH ESI
01003519 |. 8B7424 10     MOV ESI,DWORD PTR SS:[ESP+10]            ; ESI中表示单击的格子在第几列
0100351D |. 8BC8          MOV ECX,EAX
0100351F |. C1E1 05       SHL ECX,5
01003522 |. 8D9431 405300>LEA EDX,DWORD PTR DS:[ECX+ESI+1005340]   ; EDX中存放的就是当前格子的内存地址!
01003529 |. F602 80       TEST BYTE PTR DS:[EDX],80
0100352C |. 57            PUSH EDI
0100352D |. 74 66         JE SHORT winmine.01003595                ; 如果是雷则不跳
0100352F |. 833D A4570001>CMP DWORD PTR DS:[10057A4],0             ; 中招!!
01003536 |. 75 50         JNZ SHORT winmine.01003588
……
01003588 |> 6A 4C         PUSH 4C
0100358A |. 50            PUSH EAX
0100358B |. 56            PUSH ESI
0100358C |. E8 1AF9FFFF   CALL winmine.01002EAB                    ; 挂~!
01003591 |. 6A 00         PUSH 0
01003593 |. EB 16         JMP SHORT winmine.010035AB
01003595 |> 50            PUSH EAX                                 ; /Arg2
01003596 |. 56            PUSH ESI                                 ; |Arg1
01003597 |. E8 E8FAFFFF   CALL winmine.01003084                    ; winmine.01003084 ;若不是雷,行列压栈,此call用来在打开的格子上写数字等等处理
0100359C |. A1 A4570001   MOV EAX,DWORD PTR DS:[10057A4]
010035A1 |. 3B05 A0570001 CMP EAX,DWORD PTR DS:[10057A0]
010035A7 |. 75 07         JNZ SHORT winmine.010035B0
010035A9 |. 6A 01         PUSH 1
010035AB |> E8 CCFEFFFF   CALL winmine.0100347C
010035B0 |> 5F            POP EDI
010035B1 |. 5E            POP ESI
010035B2 |. 5D            POP EBP
0100