扫雷外挂逆向分析

 

作者:riusksk(泉哥)

 

近日闲来无事,偶得一扫雷外挂,故逆向之。

 

00401000 >/$  68 24334000   PUSH 扫雷外挂.00403324                       ; /Title = "扫雷"
00401005  |.  6A 00         PUSH 0                                   ; |Class = 0
00401007  |.  E8 F0010000   CALL <JMP.&user32.FindWindowA>           ; \FindWindowA
0040100C  |.  A3 0D304000   MOV DWORD PTR DS:[40300D],EAX            ;  先查找名为“扫雷”的窗口,eax为返回的句柄0094083A
00401011  |.  833D 0D304000>CMP DWORD PTR DS:[40300D],0
00401018  |.  75 30         JNZ SHORT 扫雷外挂.0040104A                  ;  若找到扫雷窗口,则跳到0040104A,否则提示“请启动‘扫雷游戏’”
0040101A  |.  68 29334000   PUSH 扫雷外挂.00403329                       ; /Format = "请启动‘扫雷游戏’"
0040101F  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; |s = 扫雷外挂.00403380
00401024  |.  E8 CD010000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
00401029  |.  83C4 08       ADD ESP,8
0040102C  |.  68 1D304000   PUSH 扫雷外挂.0040301D                       ; /StringToAdd = "
"
00401031  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; |ConcatString = "横向:9 纵向:9 地雷总数 10"
00401036  |.  E8 DF010000   CALL <JMP.&kernel32.lstrcatA>            ; \lstrcatA
0040103B  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; /Arg1 = 00403380
00401040  |.  E8 DB010000   CALL 扫雷外挂.00401220                       ; \扫雷外挂.00401220
00401045  |.  E9 7A010000   JMP 扫雷外挂.004011C4
0040104A  |>  68 15304000   PUSH 扫雷外挂.00403015                       ; /pProcessID = 扫雷外挂.00403015
0040104F  |.  FF35 0D304000 PUSH DWORD PTR DS:[40300D]               ; |hWnd = 0094083A ('扫雷',class='扫雷')
00401055  |.  E8 A8010000   CALL <JMP.&user32.GetWindowThreadProcess>; \GetWindowsThreadProcessId,获取扫雷窗口的进程ID
0040105A  |.  FF35 15304000 PUSH DWORD PTR DS:[403015]               ; /ProcessId = 9C4
00401060  |.  6A 00         PUSH 0                                   ; |Inheritable = FALSE
00401062  |.  6A 10         PUSH 10                                  ; |Access = VM_READ
00401064  |.  E8 A5010000   CALL <JMP.&kernel32.OpenProcess>         ; \OpenProcess,打开扫雷进程
00401069  |.  A3 19304000   MOV DWORD PTR DS:[403019],EAX            ;  保存进程ID:34
0040106E  |.  C705 84344000>MOV DWORD PTR DS:[403484],10056AC
00401078  |.  6A 00         PUSH 0                                   ; /pBytesRead = NULL
0040107A  |.  6A 04         PUSH 4                                   ; |BytesToRead = 4
0040107C  |.  68 88344000   PUSH 扫雷外挂.00403488                       ; |Buffer = 扫雷外挂.00403488
00401081  |.  FF35 84344000 PUSH DWORD PTR DS:[403484]               ; |pBaseAddress = 10056AC
00401087  |.  FF35 19304000 PUSH DWORD PTR DS:[403019]               ; |hProcess = 00000034 (window)
0040108D  |.  E8 82010000   CALL <JMP.&kernel32.ReadProcessMemory>   ; \ReadProcessMemory,读取地址为10056AC的4字节内容,并保存在00403488
00401092  |.  C705 84344000>MOV DWORD PTR DS:[403484],10056A8
0040109C  |.  6A 00         PUSH 0                                   ; /pBytesRead = NULL
0040109E  |.  6A 04         PUSH 4                                   ; |BytesToRead = 4
004010A0  |.  68 8C344000   PUSH 扫雷外挂.0040348C                       ; |Buffer = 扫雷外挂.0040348C
004010A5  |.  FF35 84344000 PUSH DWORD PTR DS:[403484]               ; |pBaseAddress = 10056A8
004010AB  |.  FF35 19304000 PUSH DWORD PTR DS:[403019]               ; |hProcess = 00000034 (window)
004010B1  |.  E8 5E010000   CALL <JMP.&kernel32.ReadProcessMemory>   ; \ReadProcessMemory,读取地址为10056A8的4字节内容,并保存在0040348C,纵向方格数
004010B6  |.  C705 84344000>MOV DWORD PTR DS:[403484],1005330
004010C0  |.  6A 00         PUSH 0                                   ; /pBytesRead = NULL
004010C2  |.  6A 04         PUSH 4                                   ; |BytesToRead = 4
004010C4  |.  68 20304000   PUSH 扫雷外挂.00403020                       ; |Buffer = 扫雷外挂.00403020
004010C9  |.  FF35 84344000 PUSH DWORD PTR DS:[403484]               ; |pBaseAddress = 1005330
004010CF  |.  FF35 19304000 PUSH DWORD PTR DS:[403019]               ; |hProcess = 00000034 (window)
004010D5  |.  E8 3A010000   CALL <JMP.&kernel32.ReadProcessMemory>   ; \ReadProcessMemory,读取地址为1005330的4字节内容,并保存在00403020,即为地雷总数
004010DA  |.  C705 84344000>MOV DWORD PTR DS:[403484],1005361
004010E4  |.  6A 00         PUSH 0                                   ; /pBytesRead = NULL
004010E6  |.  68 00030000   PUSH 300                                 ; |BytesToRead = 300 (768.)
004010EB  |.  68 24304000   PUSH 扫雷外挂.00403024                       ; |Buffer = 扫雷外挂.00403024
004010F0  |.  FF35 84344000 PUSH DWORD PTR DS:[403484]               ; |pBaseAddress = 1005361
004010F6  |.  FF35 19304000 PUSH DWORD PTR DS:[403019]               ; |hProcess = 00000034 (window)
004010FC  |.  E8 13010000   CALL <JMP.&kernel32.ReadProcessMemory>   ; \ReadProcessMemory,读取地址为1005361的4字节内容,并保存在00403024,即为横向方格数
00401101  |.  FF35 20304000 PUSH DWORD PTR DS:[403020]               ; /<%d> = A (10.)
00401107  |.  FF35 8C344000 PUSH DWORD PTR DS:[40348C]               ; |<%d> = 9
0040110D  |.  FF35 88344000 PUSH DWORD PTR DS:[403488]               ; |<%d> = 9
00401113  |.  68 3C334000   PUSH 扫雷外挂.0040333C                       ; |Format = "横向:%d 纵向:%d 地雷总数 %d"
00401118  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; |s = 扫雷外挂.00403380
0040111D  |.  E8 D4000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
00401122  |.  83C4 14       ADD ESP,14

00401125  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; /Arg1 = 00403380
0040112A  |.  E8 F1000000   CALL 扫雷外挂.00401220                       ; \扫雷外挂.00401220
0040112F  |.  68 1D304000   PUSH 扫雷外挂.0040301D                       ; /Arg1 = 0040301D ASCII "
"
00401134  |.  E8 E7000000   CALL 扫雷外挂.00401220                       ; \扫雷外挂.00401220
00401139  |.  BE 24304000   MOV ESI,扫雷外挂.00403024                    ;  横向方格数存入esi
0040113E  |.  33C0          XOR EAX,EAX                              ;  eax清零
00401140  |.  A3 94344000   MOV DWORD PTR DS:[403494],EAX
00401145  |>  33C0          /XOR EAX,EAX
00401147  |.  A3 90344000   |MOV DWORD PTR DS:[403490],EAX
0040114C  |>  8A06          |/MOV AL,BYTE PTR DS:[ESI]               ;  [esi]='@',ASCII=40
0040114E  |.  46            ||INC ESI
0040114F  |.  3C 8F         ||CMP AL,8F                              ;  当al=8F时,表示存在地雷
00401151  |.  75 14         ||JNZ SHORT 扫雷外挂.00401167
00401153  |.  68 5A334000   ||PUSH 扫雷外挂.0040335A                     ; /Format = "1 "
00401158  |.  68 80334000   ||PUSH 扫雷外挂.00403380                     ; |s = 扫雷外挂.00403380
0040115D  |.  E8 94000000   ||CALL <JMP.&user32.wsprintfA>           ; \wsprintfA,存在地雷就输出1,否则输出0
00401162  |.  83C4 08       ||ADD ESP,8
00401165  |.  EB 12         ||JMP SHORT 扫雷外挂.00401179
00401167  |>  68 5D334000   ||PUSH 扫雷外挂.0040335D                     ; /Format = "0 "
0040116C  |.  68 80334000   ||PUSH 扫雷外挂.00403380                     ; |s = 扫雷外挂.00403380
00401171  |.  E8 80000000   ||CALL <JMP.&user32.wsprintfA>           ; \wsprintfA
00401176  |.  83C4 08       ||ADD ESP,8
00401179  |>  68 80334000   ||PUSH 扫雷外挂.00403380                     ; /Arg1 = 00403380
0040117E  |.  E8 9D000000   ||CALL 扫雷外挂.00401220                     ; \标准输出stdout
00401183  |.  FF05 90344000 ||INC DWORD PTR DS:[403490]              ;  计数器
00401189  |.  A1 90344000   ||MOV EAX,DWORD PTR DS:[403490]
0040118E  |.  3B05 88344000 ||CMP EAX,DWORD PTR DS:[403488]          ;  比较eax是否等于9
00401194  |.  73 02         ||JNB SHORT 扫雷外挂.00401198                ;  当eax大于等于9时,则跳到00401198,否则跳回0040114C
00401196  |.^ EB B4         |\JMP SHORT 扫雷外挂.0040114C                ;  eax小于9时,循环操作
00401198  |>  68 1D304000   |PUSH 扫雷外挂.0040301D                      ; /Arg1 = 0040301D ASCII "
"
0040119D  |.  E8 7E000000   |CALL 扫雷外挂.00401220                      ; \标准输出
004011A2  |.  B8 20000000   |MOV EAX,20
004011A7  |.  2B05 88344000 |SUB EAX,DWORD PTR DS:[403488]
004011AD  |.  03F0          |ADD ESI,EAX
004011AF  |.  FF05 94344000 |INC DWORD PTR DS:[403494]
004011B5  |.  A1 94344000   |MOV EAX,DWORD PTR DS:[403494]
004011BA  |.  3B05 8C344000 |CMP EAX,DWORD PTR DS:[40348C]           ;  DS:[0040348C]=09
004011C0  |.  73 02         |JNB SHORT 扫雷外挂.004011C4
004011C2  |.^ EB 81         \JMP SHORT 扫雷外挂.00401145
004011C4  |>  68 60334000   PUSH 扫雷外挂.00403360                       ; /Format = ".....程序结束,回车键退出"
004011C9  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; |s = 扫雷外挂.00403380
004011CE  |.  E8 23000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
004011D3  |.  83C4 08       ADD ESP,8
004011D6  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; /Arg1 = 00403380
004011DB  |.  E8 40000000   CALL 扫雷外挂.00401220                       ; \扫雷外挂.00401220
004011E0  |.  68 04010000   PUSH 104                                 ; /Arg2 = 00000104
004011E5  |.  68 80334000   PUSH 扫雷外挂.00403380                       ; |Arg1 = 00403380
004011EA  |.  E8 69000000   CALL 扫雷外挂.00401258                       ; \扫雷外挂.00401258
004011EF  |.  6A 00         PUSH 0                                   ; /ExitCode = 0
004011F1  \.  E8 12000000   CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess