• 标 题:春节献礼 SantMat's ReverseMe #1 阻止核武器~~~ (7千字)
  • 作 者:RoBa  
  • 时 间:2004-01-21 17:11:32
  • 链 接:http://bbs.pediy.com

SantMat's ReverseMe #1 

下载地址: http://www.reversemes.de/reversemes/rm_santmat.zip

前言:现在的软件破解越来越像做数学题,高三寒假只有十天,我不想把时间花在令人郁闷的算法分析上.哪怕非常简单的保护,想写出一个注册机也得好几个小时吧.忽然发现网上流传的许多ReverseMe十分有趣,内容五花八门,解决起来也不像CRACK那样程式化,非常适合提高技术,建议各位都试试.

废话少说,书归正题:

一个很有趣的ReserverMe,里面是一个小故事,大意是一个邪恶博士手里有这个发射原子弹的程序,你不能完全破坏这个程序,必须给它加上一个口令,使邪恶博士不能进入.(要是他会破解怎么办? ^_^)

没什么思路,先用W32DASM看一下,用串式参考很容易找到那一堆说明,见下:(这里其实是窗口的WndProc入口处)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401111(C)
|
:0040111F 837D0C01                cmp dword ptr [ebp+0C], 00000001
:00401123 0F8593020000            jne 004013BC
:00401129 803D2834400000          cmp byte ptr [00403428], 00
:00401130 0F8579010000            jne 004012AF
:00401136 6A00                    push 00000000
:00401138 FF35F4334000            push dword ptr [004033F4]
:0040113E 6A04                    push 00000004
:00401140 FF7508                  push [ebp+08]
:00401143 6A35                    push 00000035 \
:00401145 681C020000              push 0000021C |这四项可以改改
:0040114A 6A05                    push 00000005 |让界面好看一些
:0040114C 6A00                    push 00000000 /
:0040114E 6804080050              push 50000804   <-关键的属性

* Possible StringData Ref from Data Obj ->"You have just gained access to "
                                        ->"a server containing a program "
                                        ->"capable of setting off a chain "
                                        ->"reaction of nuclear devices across "
                                        ->"the whole world. Now, this program "
                                        ->"is scheduled to be sent to Dr. "
                                        ->"Evil in 1 Month!"
                                  |
:00401153 688D304000              push 0040308D

* Possible StringData Ref from Data Obj ->"edit"     
                                  |
:00401158 686A304000              push 0040306A     <-这个参数说明窗口是EDIT
:0040115D 6A00                    push 00000000

* Reference To: USER32.CreateWindowExA, Ord:0058h
                                  |
:0040115F E8FA030000              Call 0040155E    <-原来他用了CreateWindowEx,看看函数说明:

HWND CreateWindowEx(
    DWORD dwExStyle, // extended window Style
    LPCTSTR lpClassName, // pointer to registered class name
    LPCTSTR lpWindowName, // pointer to window name
    DWORD dwStyle, // window Style
    int x, // horizontal position of window
    int y, // vertical position of window
    int nWidth, // window width
    int nHeight, // window height
    HWND hWndParent, // handle to parent or owner window
    HMENU hMenu, // handle to menu, or child-window identifier
    HINSTANCE hInstance, // handle to application instance
    LPVOID lpParam  // pointer to window-creation data
   );

这是Style里的一些常量的意义:
可以看出我们要把第6位的8去掉,我改为了50800080.先别着急,我们不改这一处,改下面.为什么?接着看.
下面是类似的,创建出一串的EDIT来显示信息,省略.

下一步,想想要进行口令检验用什么函数,从文本框取字串要用GetWindowText,字串比较用lstrcmp.先别着急翻输入表加函数,好好找一找,原来程序已经有这两个函数了,在什么地方呢?见下:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401123(C)
|
:004013BC 817D0C11010000          cmp dword ptr [ebp+0C], 00000111  <-敏感数字,WM_COMMAND
:004013C3 0F8586000000            jne 0040144F
:004013C9 8B4510                  mov eaxdword ptr [ebp+10]
:004013CC 6683F801                cmp ax, 0001
:004013D0 7545                    jne 00401417
:004013D2 C1E810                  shr eax, 10
:004013D5 660BC0                  or axax
:004013D8 753D                    jne 00401417
:004013DA 6800020000              push 00000200
:004013DF 6828344000              push 00403428             <-取得的字串放在403428
:004013E4 FF3500344000            push dword ptr [00403400] <-这是谁的HWND呢?

* Reference To: USER32.GetWindowTextA, Ord:015Bh
                                  |
:004013EA E88D010000              Call 0040157C

* Possible StringData Ref from Data Obj ->"Here is your mission, if you choose "
                                        ->"to accept it:"
                                  |
:004013EF 68F7314000              push 004031F7  <-内定的字串,也就是密码啦,改为自设的字串
:004013F4 6828344000              push 00403428  <-上面从文本框中取出的字串

* Reference To: KERNEL32.lstrcmpA, Ord:02D6h
                                  |
:004013F9 E85A010000              Call 00401558  <-比较,比完后怎么没事了?
:004013FE FF7508                  push [ebp+08]

* Reference To: USER32.DestroyWindow, Ord:008Dh
                                  |
:00401401 E864010000              Call 0040156A  <-主窗口被灭掉
:00401406 6A0A                    push 0000000A
:00401408 6A00                    push 00000000
:0040140A 6A00                    push 00000000
:0040140C FF35F4334000            push dword ptr [004033F4]
:00401412 E853000000              call 0040146A

我想如果对REVERSE比较熟悉的话,对上面的0x111应该比较敏感吧(我还不行,想了半天才弄明白),WM_COMMAND,再加上下面的DestroyWindow,明显是那个按钮按下后的动作.可见我们的判断代码只要加在这里就行了.还有就是那个[4030400]处放的是中间一个EDIT的HANDLE,所以前面只要把第三个EDIT的属性改为可写就可以.当然改哪个完全随你的便,记住看好它的句柄放在哪就行了.

小弟才疏学浅,实在插不进代码去,只好跳到末尾去做手脚.修改后如下:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401123(C)
|
:004013BC 817D0C11010000          cmp dword ptr [ebp+0C], 00000111
:004013C3 0F8586000000            jne 0040144F
:004013C9 8B4510                  mov eaxdword ptr [ebp+10]
:004013CC 6683F801                cmp ax, 0001
:004013D0 7545                    jne 00401417
:004013D2 C1E810                  shr eax, 10
:004013D5 660BC0                  or axax
:004013D8 753D                    jne 00401417
:004013DA E9D3010000              jmp 004015B2  <-强行跳转到后面
:004013DF 6828344000              push 00403428
:004013E4 FF3500344000            push dword ptr [00403400]

自己的代码: (其实是抄上面的:)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004013DA(U)
|
:004015B2 6800020000              push 00000200  <-最大字符数
:004015B7 6828344000              push 00403428  <-字符保存地址
:004015BC FF3500344000            push dword ptr [00403400] <-EDIT的句柄

* Reference To: USER32.GetWindowTextA, Ord:015Bh
                                  |
:004015C2 E8B5FFFFFF              Call 0040157C  <-得到字串
:004015C7 68F0234000              push 004023F0  <-这是我定的密码,奇怪的是用W32DASM显不出来
:004015CC 6828344000              push 00403428  <-文本框里的字串

* Reference To: KERNEL32.lstrcmpA, Ord:02D6h
                                  |
:004015D1 E882FFFFFF              Call 00401558  <-如果相同则EAX=0
:004015D6 85C0                    test eaxeax
:004015D8 0F8420FEFFFF            je 004013FE    <-如果EAX=0即密码正确就跳回去继续执行
:004015DE 6A00                    push 00000000

* Reference To: KERNEL32.ExitProcess, Ord:0075h
                                  |
:004015E0 FF1508204000            Call dword ptr [00402008] <-密码不正确就直接退出
:004015E6 00000000000000000000    BYTE 10 DUP(0)

主要工作完成,剩下的就是把没用的EDIT去掉,把大小调整一下,让界面美观一些之类的事了.我的审美能力很烂,(比方说我看XP还不如98漂亮),所以就不在这里丢人了.


ES_AUTOHSCROLL = 80 
ES_AUTOVSCROLL = 40 
ES_CENTER = 1 
ES_LEFT = 0 
ES_LOWERCASE = 10 
ES_MULTILINE = 4 
ES_NOHIDESEL = 100 
ES_NUMBER = 2000 
ES_OEMCONVERT = 400 
ES_PASSWORD = 20 
ES_READONLY = 800 <--把他去掉就OK ES_RIGHT = 2 ES_UPPERCASE = 8 ES_WANTRETURN = 1000 

也许高手看起来这个非常简单,但却花了我一个上午,如果有什么错误,请批评指正.祝各位猴年快乐,技术精进!