|
马上加入TC
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
[ 本帖最后由 minews 于 2018-4-18 23:24 编辑 ]\n\nXP版扫雷 内存call分析过程和TC源代码第一次发帖排版有点乱,将就着看
这个排版真是醉了 文档直接放word文档里面了
[hide]分析雷的数据的思路1.开局的时候初始化雷的位置肯定会读取地图的宽高,找到宽高的地址后下硬件断点;2.开局的时候随机布雷,可能会调用随机函数,对rand函数下断我们用第二种方法输入bp rand 按回车
点击开局按钮程序断下来了
反汇编窗口中跟随 010036A6 |> \5B pop ebx ; winmine.01003946010036A7 |. A3 34530001 mov dword ptr ds:[0x1005334],eax010036AC |. 890D 38530001 mov dword ptr ds:[0x1005338],ecx010036B2 |. E8 1EF8FFFF call winmine.01002ED5010036B7 |. A1 A4560001 mov eax,dword ptr ds:[0x10056A4] ; 总雷数010036BC |. 893D 60510001 mov dword ptr ds:[0x1005160],edi010036C2 |. A3 30530001 mov dword ptr ds:[0x1005330],eax010036C7 |> FF35 34530001 push dword ptr ds:[0x1005334] ; 穿棋盘宽度010036CD |. E8 6E020000 call winmine.01003940 ; rand函数010036D2 |. FF35 38530001 push dword ptr ds:[0x1005338] ; 传入棋盘高度010036D8 |. 8BF0 mov esi,eax010036DA |. 46 inc esi ; user32.PtInRect010036DB |. E8 60020000 call winmine.01003940 ; rand函数010036E0 |. 40 inc eax010036E1 |. 8BC8 mov ecx,eax010036E3 |. C1E1 05 shl ecx,0x5010036E6 |. F68431 405300>test byte ptr ds:[ecx+esi+0x1005340],0x8>; [y+x+0x1005340]&0x80!=0就是雷010036EE |.^ 75 D7 jnz short winmine.010036C7 ; 本格已经是雷跳转重新放雷010036F0 |. C1E0 05 shl eax,0x5010036F3 |. 8D8430 405300>lea eax,dword ptr ds:[eax+esi+0x1005340]
简单的分析可以得知这个就是初始化放雷的函数过程
用伪代码可以表示为while(总雷数==0) x=取随机数(1,格子宽) y=取随机数(1,格子高) if(是否为雷(x,y)==真) else 设置为雷(x,y) 总雷数=总雷数-1 Endend
//[(y+1)<<5+(x+1)+0x1005340]&0x80 !=0 则横坐标x,纵坐标y处是雷
function getType(x, y)//为真是雷 x = x + 1 y = y + 1 y = 位左移(y, 5) var addr = y + x + #1005340 addr = strformat("%x", addr) var type = dm.ReadInt(hwnd, addr, 2) return 位与(type, #80) != 0end
跟踪挖雷call思路挖雷是在点鼠标的时候触发的,于是在windowproc函数里面的分支去找windowproc类似于tc里面的消息路由里面对各种windows消息做处理观察游戏可以发现鼠标左键按下去的时候并不会触发挖雷,只有鼠标左键弹起的时候才会触发所以直接找 WM_LBUTTONUP =0x202 这个消息的对应处理即可 01001FDF |> \33FF xor edi,edi ; Cases 202 (WM_LBUTTONUP),205(WM_RBUTTONUP),208 (WM_MBUTTONUP) of switch 01001F5F01001FE1 |. 393D 40510001 cmp dword ptr ds:[0x1005140],edi01001FE7 |. 0F84 BC010000 je winmine.010021A901001FED |> 893D 40510001 mov dword ptr ds:[0x1005140],edi01001FF3 |. FF15 D8100001 call dword ptr ds:[<&USER32.ReleaseCaptu>;[ReleaseCapture01001FF9 |. 841D 00500001 test byte ptr ds:[0x1005000],bl01001FFF |. 0F84 B6000000 je winmine.010020BB01002005 |. E8D7170000 call winmine.010037E10100200A |. E99A010000 jmp winmine.010021A90100200F |> 393D 48510001 cmp dword ptr ds:[0x1005148],edi ; Case 204 (WM_RBUTTONDOWN) of switch 01001F5F01002015 |.^ 0F85 69FFFFFF jnz winmine.01001F84
可以看到一共只有2个call 第一个是系统函数ReleaseCapture,所以肯定在第二个call里面 现在对 call 010037E1 这一句下断单步跟踪进入
010037E1 /$ A1 18510001 mov eax,dword ptr ds:[0x1005118]010037E6 |. 85C0 test eax,eax010037E8 |. 0F8E C8000000 jle winmine.010038B6010037EE |. 8B0D1C510001 mov ecx,dword ptr ds:[0x100511C]010037F4 |. 85C9 test ecx,ecx010037F6 |. 0F8E BA000000 jle winmine.010038B6010037FC |. 3B05 34530001 cmp eax,dword ptr ds:[0x1005334]01003802 |. 0F8F AE000000 jg winmine.010038B601003808 |. 3B0D 38530001 cmp ecx,dword ptr ds:[0x1005338]0100380E |. 0F8F A2000000 jg winmine.010038B601003814 |. 53 push ebx01003815 |. 33DB xor ebx,ebx01003817 |. 43 inc ebx01003818 |. 833D A4570001>cmp dword ptr ds:[0x10057A4],0x00100381F |. 754A jnz short winmine.0100386B01003821 |. 833D 9C570001>cmp dword ptr ds:[0x100579C],0x001003828 |. 7541 jnz short winmine.0100386B0100382A |. 53 push ebx0100382B |. E8BD000000 call winmine.010038ED01003830 |. FF05 9C570001 inc dword ptr ds:[0x100579C]01003836 |. E87AF0FFFF call winmine.010028B50100383B |. 6A00 push 0x0 ; /Timerproc =NULL0100383D |. 68E8030000 push 0x3E8 ; |Timeout =1000. ms01003842 |. 53 push ebx ; |TimerID =0x401003843 |. FF35 245B0001 push dword ptr ds:[0x1005B24] ; |hWnd = 001E2BFA ('扫雷',class='扫雷')01003849 |. 891D 64510001 mov dword ptr ds:[0x1005164],ebx ; |0100384F |. FF15 B4100001 call dword ptr ds:[<&USER32.SetTimer>] ; \SetTimer01003855 |. 85C0 test eax,eax01003857 |. 7507 jnz short winmine.0100386001003859 |. 6A04 push 0x40100385B |. E8F0000000 call winmine.0100395001003860 |> A1 18510001 mov eax,dword ptrds:[0x1005118]01003865 |. 8B0D 1C510001 mov ecx,dword ptr ds:[0x100511C]0100386B |> 841D 00500001 test byte ptr ds:[0x1005000],bl01003871 |. 5B pop ebx ; winmine.0100394601003872 |. 7510 jnz short winmine.0100388401003874 |. 6AFE push -0x201003876 |. 59 pop ecx ; winmine.0100394601003877 |. 8BC1 mov eax,ecx01003879 |. 890D 1C510001 mov dword ptr ds:[0x100511C],ecx0100387F |. A318510001 mov dword ptrds:[0x1005118],eax01003884 |> 833D 44510001>cmp dword ptr ds:[0x1005144],0x00100388B |. 7409 je short winmine.010038960100388D |. 51 push ecx0100388E |. 50 push eax0100388F |. E823FDFFFF call winmine.010035B701003894 |. EB20 jmp short winmine.010038B601003896 |> 8BD1 mov edx,ecx01003898 |. C1E2 05 shl edx,0x50100389B |. 8A9402 405300>mov dl,byte ptr ds:[edx+eax+0x1005340]010038A2 |. F6C2 40 test dl,0x40010038A5 |. 750F jnz short winmine.010038B6010038A7 |. 80E2 1F and dl,0x1F010038AA |. 80FA 0E cmp dl,0xE010038AD |. 7407 je short winmine.010038B6010038AF |. 51 push ecx010038B0 |. 50 push eax010038B1 |. E85CFCFFFF call winmine.01003512010038B6 |> FF35 60510001 push dword ptr ds:[0x1005160]010038BC |. E852F0FFFF call winmine.01002913010038C1 \. C3 retn
整理为tc代码functionmineByPos(x, y)//挖雷call dm.AsmClear() dm.AsmAdd("push 0x" &strformat("%x", (y + 1))) dm.AsmAdd("push 0x" &strformat("%x", (x + 1))) dm.AsmAdd("call 01003512") dm.AsmCall(hwnd, 1)end 标记call同理找鼠标右键按下消息分析代码整理为tc代码如下function mark(x, y)//标记call dm.AsmClear() dm.AsmAdd("push 0x" & strformat("%x", (y + 1))) dm.AsmAdd("push 0x" & strformat("%x", (x + 1))) dm.AsmAdd("call 0100374F") dm.AsmCall(hwnd, 1)end[/hide] |
|