首页
社区
课程
招聘
[原创]SantMat-ReverseMe #2另类解法
发表于: 2007-4-26 22:35 6608

[原创]SantMat-ReverseMe #2另类解法

2007-4-26 22:35
6608

【文章标题】: 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期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
ReverseMe 文章论坛比较少,欢迎这样的文章
2007-4-26 22:57
0
雪    币: 110
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
先看看再说,顶
2007-4-27 00:12
0
雪    币: 234
活跃值: (25)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
用C语言构造随机数要用到 srand()和 rand()这两个函数。
我曾写过一个注册机的文章中用到过随机数,文章地址如下:
http://bbs.pediy.com/showthread.php?t=35951
你可以参考一下随机数的实现过程。
另外,其他其它编程语言也都有生成随机数的方法。如果你用matlab的话,还可以生成随机矩阵
rand(n)这个命令就可以生成n阶随机矩阵。生成一个(0,1)的随机数就是rand(1)。
你的文章不错,支持!
2007-4-30 19:39
0
雪    币: 328
活跃值: (10)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
5
呵呵,我说的是我不知道怎么直接修改程序调用静态库的函数,不是说怎么通过编程来生成随机数,你误解我的意思了

我去看了遍你的精华贴,发现你的数学很强哦。我就不大敢跟算法,数学太差,我高等数学补考来着....

谢谢你的支持
2007-5-2 09:30
0
游客
登录 | 注册 方可回帖
返回
//