-
-
[原创]SantMat-ReverseMe #2另类解法
-
发表于:
2007-4-26 22:35
6608
-
[原创]SantMat-ReverseMe #2另类解法
【文章标题】: SantMat-ReverseMe #2另类解法
【文章作者】: Nukou.G
【软件名称】: SantMat-ReverseMe #2
【软件大小】: 7K
【下载地址】: 《加密与解密》附书光盘
【加壳方式】: 无
【使用工具】: OllyDBG
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这个reverseme有三个任务:
1.去掉交代任务的这个"memo dialog"
2.完成两个按钮的单击事件:单击一个按钮的时候,生成一个1-100之间的随机数字并显示在该按扭之上的文本框中。并且两个玩家都点击过按钮之后,比较两个玩家得到的数字,比较大的那个玩家得一分,直到有一个玩家得到50分为止。
3.为两个按扭增加快捷键:Player 1-z,Player 2-m
------------
我不知道怎么生成随机数,所以我自己写了个DLL文件来实现任务要求的各个功能,这个DLL有2个输出函数:
EXPORT DWORD CALLBACK Generator(void)
{//返回一个1-100之间的整数
return ((rand() % 100)+1);
}
EXPORT DWORD CALLBACK ChangeText(PDWORD pplayer2, HWND hwnd, DWORD nId, PDWORD pplayer1, DWORD dwnum)
{//将hwnd上的nId的文本修改为dwnum,根据nId的值修改*pplayer1或*pplayer2的值
//player1赢了返回1,player2赢了返回2,否则返回0
//(*pplayer1) = 当前点数+是否按过按钮*1000+赢的次数*100
TCHAR szBuffer[10];
wsprintf(szBuffer, TEXT("%i"), dwnum);
SetDlgItemText(hwnd, nId, szBuffer);
if (nId == 0x3f0)
{//赋值并标记已经按过按钮
(*pplayer1) = 1000 + ((*pplayer1)/100)*100 + dwnum;
}
else if (nId == 0x3ef)
{
(*pplayer2) = 1000 + ((*pplayer2)/100)*100 + dwnum;
}
if (((*pplayer1)/1000 != 0) && ((*pplayer2)/1000 != 0))
{//player1和player2都点了按扭
//点数大的人赢的次数加一,并把两个玩家都标记为未按过按钮的状态
if ((*pplayer1)%100 < (*pplayer2)%100)
{//player1的点数比player2的点数小
(*pplayer2) += 100;
}
else if ((*pplayer1)%100 > (*pplayer2)%100)
{//player1的点数比player2的点数大
(*pplayer1) += 100;
}
(*pplayer1) -= 1000;
(*pplayer2) -= 1000;
//判断是否有玩家赢了
if ((*pplayer1)/100 == 5)
{
return(1);
}
else if ((*pplayer2)/100 == 5)
{
return(2);
}
}
return(0);
}
-------------------------
为两个按键添加快捷键,我“作弊”了:用eXescope加...(顺便给个eXescope的注册码:A191012344)
然后在程序的相应位置添加字符串:
0402130 "Generator.dll"
0402140 "_Generator@0"
0402150 "_ChangeText@20"
0402160 "Player1 Win!"
0402170 "Player2 Win!"
最后就是写代码了,这里我发现了一个小窍门:直接在OllyDBG里写汇编代码,然后Dump debugged process,然后用UEdit从Dump出来的文件里复制机器码来替换原文件的相应位置的机器码。这样比用Hiew快一点。
下面是修改后的代码:
00401000 >/$ 6A 00 push 0 ; /pModule = NULL
00401002 |. E8 59010000 call <jmp.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401007 |. A3 9C304000 mov dword ptr [40309C], eax
;获得我写的DLL文件中的两个函数的地址
0040100C |. 68 30214000 push 00402130 ; /FileName = "Generator.dll"
00401011 |. FF15 04204000 call dword ptr [<&KERNEL32.LoadLibrar>; \LoadLibraryA
00401017 |. A3 00314000 mov dword ptr [403100], eax
0040101C |. 68 40214000 push 00402140 ; /ProcNameOrOrdinal = "_Generator@0"
00401021 |. FF35 00314000 push dword ptr [403100] ; |hModule = NULL
00401027 |. FF15 08204000 call dword ptr [<&KERNEL32.GetProcAdd>; \GetProcAddress
0040102D |. A3 10314000 mov dword ptr [403110], eax
00401032 |. 68 50214000 push 00402150 ; /ProcNameOrOrdinal = "_ChangeText@20"
00401037 |. FF35 00314000 push dword ptr [403100] ; |hModule = NULL
0040103D |. FF15 08204000 call dword ptr [<&KERNEL32.GetProcAdd>; \GetProcAddress
00401043 |. A3 20314000 mov dword ptr [403120], eax
;初始化
00401048 |. 33C0 xor eax, eax
0040104A |. A3 40314000 mov dword ptr [403140], eax
0040104F |. A3 50314000 mov dword ptr [403150], eax
;Game窗口
00401054 |. 50 push eax ; /lParam => NULL
00401055 |. 68 BF104000 push 004010BF ; |DlgProc = Reversed.004010BF
0040105A |. 50 push eax ; |hOwner => NULL
0040105B |. 68 05304000 push 00403005 ; |pTemplate = "GAME"
00401060 |. FF35 9C304000 push dword ptr [40309C] ; |hInst = NULL
00401066 |. FF15 20204000 call dword ptr [<&USER32.DialogBoxPar>; \DialogBoxParamA
;释放DLL文件
0040106C |. 68 00314000 push 00403100 ; /hLibModule = 00403100
00401071 |. FF15 00204000 call dword ptr [<&KERNEL32.FreeLibrar>; \FreeLibrary
00401077 |. 50 push eax ; /ExitCode
00401078 \. FF15 0C204000 call dword ptr [<&KERNEL32.ExitProces>; \ExitProcess
;=========================处理按钮事件的函数
0040107E /$ 55 push ebp
0040107F |. 8BEC mov ebp, esp
;调用 _Generator@0生成随机数
00401081 |. FF15 10314000 call dword ptr [403110]
;调用 _ChangeText@20修改相应窗口的文字,并返回游戏处理结果
00401087 |. 50 push eax
00401088 |. FF75 14 push dword ptr [ebp+14]
0040108B |. FF75 10 push dword ptr [ebp+10]
0040108E |. FF75 0C push dword ptr [ebp+C]
00401091 |. FF75 08 push dword ptr [ebp+8]
00401094 |. FF15 20314000 call dword ptr [403120]
;对返回结果做处理
0040109A |. 83F8 01 cmp eax, 1
0040109D |. 72 1C jb short 004010BB
0040109F |. B8 60214000 mov eax, 00402160 ; ASCII "Player1 Win!"
004010A4 |. 77 06 ja short 004010AC
004010A6 |. 90 nop
004010A7 |. B8 70214000 mov eax, 00402170 ; ASCII "Player2 Win!"
004010AC |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
004010AE |. 68 0A304000 push 0040300A ; |Title = "Number Game"
004010B3 |. 50 push eax ; |Text
004010B4 |. 6A 00 push 0 ; |hOwner = NULL
004010B6 |. E8 93000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
004010BB |> C9 leave
004010BC \. C2 0400 retn 4
;=========================Game窗口的窗口过程
004010BF /. 55 push ebp
004010C0 |. 8BEC mov ebp, esp
004010C2 |. 817D 0C 10010>cmp dword ptr [ebp+C], 110
004010C9 |. 74 6D je short 00401138
004010CB |. 837D 0C 10 cmp dword ptr [ebp+C], 10
004010CF |. 75 0C jnz short 004010DD
004010D1 |. 6A 00 push 0 ; /Result = 0
004010D3 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
004010D6 |. E8 6D000000 call <jmp.&USER32.EndDialog> ; \EndDialog
004010DB |. EB 5B jmp short 00401138
004010DD |> 817D 0C 11010>cmp dword ptr [ebp+C], 111
004010E4 |. 75 4C jnz short 00401132
004010E6 |. 8B45 10 mov eax, dword ptr [ebp+10]
004010E9 |. 66:3D ED03 cmp ax, 3ED
004010ED |. 75 1E jnz short 0040110D
004010EF |. C1E8 10 shr eax, 10
004010F2 |. 09C0 or eax, eax
004010F4 |. 75 17 jnz short 0040110D
004010F6 |. 68 40314000 push 00403140
004010FB |. 68 F0030000 push 3F0
00401100 |. FF75 08 push dword ptr [ebp+8]
00401103 |. 68 50314000 push 00403150
00401108 |. E8 71FFFFFF call 0040107E
0040110D |> 66:3D EE03 cmp ax, 3EE
00401111 |. 75 25 jnz short 00401138
00401113 |. C1E8 10 shr eax, 10
00401116 |. 66:09C0 or ax, ax
00401119 |. 75 1D jnz short 00401138
0040111B |. 68 40314000 push 00403140
00401120 |. 68 EF030000 push 3EF
00401125 |. FF75 08 push dword ptr [ebp+8]
00401128 |. 68 50314000 push 00403150
0040112D |. E8 4CFFFFFF call 0040107E
00401132 |> 33C0 xor eax, eax
00401134 |. C9 leave
00401135 |. C2 1000 retn 10
00401138 |> B8 01000000 mov eax, 1
0040113D |. C9 leave
0040113E \. C2 1000 retn 10
--------------------------------------------------------------------------------
【经验总结】
这个文章是前段时间写的,因为是书中的习题,所以一直在权衡是否值得发到论坛上来,考虑到我是用编程的方式解决的,自我感觉良好:P,终于还是鼓起勇气发上来了....
还有,文中提及的小窍门,略过吧,一般情况下用下面的方法更方便:
在OllyDBG中直接把代码在相应位置写好,在代码里点右键>复制到可执行文件>所有修改>全部复制,然后在新窗口里点右键>保存文件>保存。这样就OK了。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年04月26日 22:29:08
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)