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 eax, dword ptr [ebp+10]
:004013CC 6683F801 cmp ax, 0001
:004013D0 7545 jne 00401417
:004013D2 C1E810 shr eax, 10
:004013D5 660BC0 or ax, ax
: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 eax, dword ptr [ebp+10]
:004013CC 6683F801 cmp ax, 0001
:004013D0 7545 jne 00401417
:004013D2 C1E810 shr eax, 10
:004013D5 660BC0 or ax, ax
: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 eax, eax
: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
也许高手看起来这个非常简单,但却花了我一个上午,如果有什么错误,请批评指正.祝各位猴年快乐,技术精进!