MFC之暴力破解

来源:互联网 发布:蓝牙耳机生产测试软件 编辑:程序博客网 时间:2024/04/27 16:20

原文链接:http://user.qzone.qq.com/386520874/blog/1389369892

=======================================================================================================

                                        随意篡改别人的代码,是一种不道德的行为,不过Hacker是个例外。
                                                                                                                                    ---------------过客

         很久很久以前,看到同事在用simcap.exe这个软件,但是只是一个Demo版,老是觉得人家老外写的算法牛X上天了,不愿意自己开发算法,年关将至,哥也不那么忙了,就花了点时间把这个软件给爆破了。
这个软件的官网是http://www.umetrics.com/,可以去下载,但要注册加monney,看样子是瑞典人在1987年(那时候真不知道我在哪里游荡)就开始工作了,那时候微软的MFC小组应该还没成立,打开这个软件后,你会发现里面的菜单多的很,真是目不暇接啊,反正我是不管那么多的,我的目的只是破解,而不是使用。就像玩CS一样,你得知道地图的哪个地方可以蹲坑,哪个地方路过就掉血。破解也一样,得先跑一遍软件,知道大概多少步可以到达最后的窗口。闲话少扯,正式开始,爆破开始之前你得先准备一个无比牛X的ollyDbg,这是一个工作在Ring3级的远古神器(向开发它的人致以崇高的敬意)。

=======================================================================================================
simcap.exe这个软件有以下4个地方需要爆破:

1.      免费试用时间只有1个月

2.      右键菜单“Save Plot As ...”被禁用

3.      右键菜单Save List As ...或者 Copy Ctrl+C 被禁用

4.      背景图片中含有”Demo”字样水印版权信息

 

========= 1. 修改时间 ==========

先来说说怎么将只能免费使用1个月的时间修改成我们想要的时间。

首先得找到设置时间限制的代码,首先用ollydbg打开simcap.exe,先不要用附加方式打开,因为一般软件都是在最开始检测注册时间,注册时间未超过1个月的话,就正常启动,否则就弹出一个叫你掏腰包的对话框,因为我是在2013.12.23号安装的这个软件,要到2014.1.23才过期,而现在还早着捏,有的高手是先找到那个超时的对话框,然后根据对话框的字符串用odb右键菜单的“搜索-->所有参考字符串”反向查找某个字符串在整个exe里面的引用,在所有参考引用处一个一个的下断,理论上来说,这是正确的破解思路,但是我第一次用这个软件,并且还没满1个月,难道要让我等到1个月过后,先观察这厮的反应,再开始爆破吗,别这么笨蛋好不好,那条判断超时的语句一定就在simcap.exe里面,这点一定要坚信,好了,废话不多说,先看odb加载后的图,

图中最左边黑色那一行是整个exe的入口点,

地址        HEX 数据            指令                                      

0058C664   E8 0D040000   call simcap.0058CA76

第一列0058C664是程序入口地址

第二列E8 0D040000是程序的一条二进制源代码,共5个字节

第三列call simcap.0058CA76是上面5个字节对应的汇编指令,这条指令的意思是说让CPUEIP寄存器跳到地址为0x0058CA76的地方,这实际上就是C语言的函数调用,这条call指令调用的函数是没有参数的,怎么判断一个函数有木有参数呢,很简单,编译器会规定参数都必须存在于栈中(堆中不知行不行),一个参数入栈,一般都是push指令,可能mov指令也可以模仿一下push指令,唉,不扯这么远了。到达上面的画面后,如果你什么断点都没设,按一下F9后,先出现下面


注意图中的”January 23, ”,其实是” January 23, 2014”,后面这个2014没输出来,可能是该软件的一个失误吧,这句话的意思就是说,你最多能用到2014.1.23,然后就玩完,请注意,这是一个很重要的信息,先拿笔记下来,然后接着在按一下F9,出现以下画面,


很明显我们已经错过检查时间的代码段,肿么办,我的办法关掉,重来,然后是不断的按F8(注意不是F9),不断的观察odb4个窗口的变化,这个过程是很无聊的,我按了半天,直到遇到了下图,


00587086 |.  68 AC316000   push offset simcap.006031AC ; /Arg1 = ASCII"TimeKey.txt"

居然看到了time字样,哈哈,那个兴奋啊,现在想急切的知道这个"TimeKey.txt"住在哪里,继续按F8,直到下面的地方停住(最好慢慢按,否则会错过什么的哦)

====================================================================

00587E4A |.  8D4D E8       lea ecx,[ebp-18]                                ;|"C:\Documents and Settings\All Users\ApplicationData\Umetrics\SIMCA-P\11.5 Demo\TimeKey.txt"

00587E4D |.  FF15 3CB25C00 call dword ptrds:[<&MFC80.#876>]              ; |

00587E53 |.  50       push eax        ; |Arg1= ASCII "C:\Documents and Settings\All Users\ApplicationData\Umetrics\SIMCA-P\11.5 Demo\TimeKey.txt"

00587E54 |.  8D8D 1CFFFFFF leaecx,[ebp-0E4]                              ; |

00587E5A |.  FF15 D4BA5C00 call dword ptrds:[<&MSVCP80.?open@?$basic_fstr ;\MSVCP80.?open@?$basic_fstream@DU?$char_traits@D@std@@@std@@QAEXPBDHH@Z

00587E60 |.  8B85 1CFFFFFF mov eax,dwordptr ss:[ebp-0E4]

00587E66 |.  8B48 04       mov ecx,dword ptr ds:[eax+4]

00587E69 |.  F6840D 24FFFF test byte ptrss:[ecx+ebp-0DC],06

00587E71 |.^ 75 85         jne shortsimcap.00587DF8

00587E73 |.  68 C8000000   push 0C8                                        ; /Arg2= 0C8

00587E78 |.  8D55 00       lea edx,[ebp]                                   ; |

00587E7B |.  52            push edx                                        ; |Arg1=> offset LOCAL.51

00587E7C |.  8D8D 1CFFFFFF leaecx,[ebp-0E4]                              ; |

00587E82  |. FF15 D8BA5C00 call dword ptr ds:[<&MSVCP80.?getline@?$basic_i ;\MSVCP80.?getline@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@PADH@Z

00587E88 |.  8D45 00       lea eax,[ebp]

00587E8B |.  50            push eax                                        ; /Arg1=> offset LOCAL.51

00587E8C  |.  8D4DE4       lea ecx,[ebp-1C]                                ; |

00587E8F |.  FF15 A8B25C00 call dword ptrds:[<&MFC80.#784>]              ; \MFC80.781F42AE

00587E95 |.  8D56 5C       lea edx,[esi+5C]

00587E98 |.  51            push ecx                                        ; /Arg2

00587E99 |.  8BCC          mov ecx,esp                                     ; |

00587E9B |.  8965 B8       mov dword ptr ss:[ebp-48],esp                   ; |

00587E9E |.  52            push edx                                        ; |/Arg1

00587E9F |.  FF15 A4B25C00 call dword ptrds:[<&MFC80.#297>]              ; |\MFC80.781F3E65

00587EA5 |.  C645 FC 05    mov byte ptr ss:[ebp-4],5                       ; |

00587EA9 |.  8D45 E4       lea eax,[ebp-1C]                                ; |

00587EAC |.  50            push eax                                        ; |Arg1=> offset LOCAL.58

00587EAD |.  C645 FC 04    mov byte ptr ss:[ebp-4],4                       ; |

00587EB1 |.  8BCE          mov ecx,esi                                     ; |

00587EB3  |.  E878EBFFFF   call simcap.00586A30                            ; \simcap.00586A30,解码时间TimeKey.txt

00587EB8 |.  8D8D 1CFFFFFF leaecx,[ebp-0E4]

00587EBE |.  FF15 DCBA5C00 call dword ptrds:[<&MSVCP80.?close@?$basic_fst ;[MSVCP80.?close@?$basic_fstream@DU?$char_traits@D@std@@@std@@QAEXXZ

====================================================================

 

很明显答案就在"C:\Documents and Settings\All Users\ApplicationData\Umetrics\SIMCA-P\11.5 Demo\TimeKey.txt"里面,打开看看先,里面是如下内容,


你能读懂吗,反正我是一开始没读懂,不过很显然的是这一定跟时间有关,到底什么关捏,继续按F8,然后在00587EB3停住,然后按F7,进入到被调用的函数入口处,然后按F8单步运行到下图处:


注意到ECX寄存器的变化了吗,哈哈,原先的“,.%*%(.$*$”现在变成了“13%*%(.$*$”,当你按F8运行到00586AE4,就跳出了这个循环,这个循环了10次,也就是那个字符串的长度,此时ECX的值变成了0A75DF40 这是一个字符串地址指针,内容为”1387853979”,很显然循环里面就是对每个字符做了一次xor(异或)运算(汗!这就算是加密了?太低端了吧),一路往下F8,到下面代码处:

00587FCF  |. FF15 10BD5C00 call dword ptr ds:[<&MSVCR80._time64>]          ; \MSVCR80._time64

00587FD5 |.  83C4 04       add esp,4

00587FD8 |.  8945 BC       mov dword ptr ss:[ebp-44],eax

…………………

0058800C |.  6A 00         push 0                                          ;/Arg3 = 0

0058800E  |. 3B4D BC       cmp ecx,dword ptrss:[ebp-44]                   ; |将注册时间(2013-12-24 10:59:39)与当前时间(2014-01-07 10:39:14)进行比较

CPU Disasm

地址        HEX 数据            指令                                              注释

00588011 |. /7E 64         jle shortsimcap.00588077                       ; |

00588013 |. |6A 10         push 10                                         ;|Arg2 = 10

00588015 |. |68 50326000   push offsetsimcap.00603250                 ;|Arg1 = ASCII "Time warp detected!" //哥英语不太好,没法翻译这一句

0058801A |. |E8 07320000   call<jmp.&MFC80.#1123>                         ; \MFC80.78239E6C AfxMessageBox(charconst *,unsigned int,unsigned int)

注意上面调用了_time64(…),即获得电脑的当前时间,当然你每次运行该软件之前,把你的电脑时间设置到注册的第二天,然后运行,然后再把电脑时间改回来,哈哈,笨蛋才用的笨方法。

……………..

CPU Disasm

地址        HEX 数据            指令                                              注释

00588077 |> \6A 00         push 0                                          ; |Arg3 = 0

00588079 |.  6A 00         push 0                                          ;|Arg2 = 0

0058807B |.  50            push eax                                        ; |Arg1

0058807C |.  8D4D AC       lea ecx,[ebp-54]                                ; |

0058807F |.  E8 5CEBFFFF   call simcap.00586BE0                            ; \simcap.00586BE0,计算时间?很奇怪

00588084 |.  8B08          mov ecx,dword ptr ds:[eax]

00588086 |.  8B40 04       mov eax,dword ptr ds:[eax+4]

00588089 |.  014D DC       add dword ptr ss:[ebp-24],ecx                   ; 0x52B8F89B + 0x00278D00 限时1个月,这个地方非常重要

 

继续按F8到下面处:

CPU Disasm

地址        HEX 数据            指令                                              注释

004128E8 |.  8B4424 40     mov eax,dword ptr ss:[esp+40]                   ; |

004128EC |.  52            push edx                                        ; |Arg2

004128ED |.  50            push eax                                        ;|Arg1, eax=0x7DE = 2014

004128EE |.  8D4C24 34     lea ecx,[esp+34]                                ; |

004128F2 |.  E8 39D3FFFF   call simcap.0040FC30                            ; \simcap.0040FC30

004128F7 |.  8B4C24 1C     mov ecx,dword ptr ss:[esp+1C]

004128FB |.  8B5424 18     mov edx,dword ptr ss:[esp+18]

004128FF |.  51            push ecx                                        ;/Arg2, 0

00412900 |.  52            push edx                                        ;|Arg1, edx=0x52E13C7F;  // Thursday,January 23, 2014

00412901 |.  8D4C24 28     lea ecx,[esp+28]                                ;|ecx=[0x0013F6FC]=0x52CA651B // Monday, January 06, 2014

00412905 |.  E8 06D4FFFF   call simcap.0040FD10                            ; \simcap.0040FD10

0041290A  |. 84C0          test al,al                                      ; al=0表示未超时,否则超时

0041290C |.  0F84 BC000000 jesimcap.004129CE

好了,游览到此处,基本上是摸清这个软件的注册时间的运行机制了,下面到了篡改代码的时候了,上面从入口处跑了老远,肯定早就错过了设置1个月时间的相关代码了,肿么办,回头呗,顺着上面的路往回倒车,怎么倒,你该不会希望odb有这个逆天的功能吧,两个办法,一个是你每路过一个你觉得重要的地方,做个“哥到此一游”的标记,在odb里面就是F2键啦,然后顺着标记找往回找代码,另一种就是关掉,重头再来(看成败,人生豪迈,只不过是重头再来 ),这一次就慢慢的按F8(你够聪明的话就按F9),直到遇到下面的代码

004127D9 |.  FF15 5CE55C00 call dword ptrds:[<&SIMCAutlwin.?SetRegistryLo ;[SIMCAutlwin.?SetRegistryLocation@UmApp@@QAEXXZ

004127DF  |.  6A1E         push 1E         ; /Arg1 = 1E ,很不起眼的1E哟,它就是十进制的30啊,是30天啊,找你找得好辛苦-_-!!!

004127E1 |.  8D8C24 800500 leaecx,[esp+580]                              ; |

004127E8 |.  E8 03471700   call simcap.00586EF0                            ; \simcap.00586EF0

找到这儿过后,也许猴急的你,马上把”6A 1E”改成”6A FE”,你或许天真的以为FE就是254天啊,我可以多用7个月了,等你保存存后,再运行simcap.exe,你会很后悔的,摆在你面前的是以下画面:


这下好了,人家说你只能用到2013.12.22,晕了吧,既然不对再改呗,当你改成”6A 7F”的时候,就ok了,它会告诉你,你可以用到2014.4.30号,爽吧,嚯嚯嚯,出现这个情况的原因很简单,就是7F80的区别,即intunsiged int的区别,FF就是-1啊,当然是23-1=22日啊。

也许你觉得多免费使用4个月好得不得了,但是我是想用100年的哦,在寒冷的瑞典,当地的人们是这样将30天换算成秒的,30*24*60*60,在遥远的东方人们酱紫换算的127*127*127*127^_^反正我可以多用8年了。

有代码为证:

CPU Disasm

地址        HEX 数据            指令                                              注释

00586BE0 /$  8B4424 04     mov eax,dword ptr ss:[esp+4]                    ; 真正计算时间限制的代码(arg1=0x1E=30)

00586BE4 |.  56            push esi

00586BE5 |.  57            push edi

00586BE6 |.  6A 00         push 0                                          ;/Arg4 = 0

00586BE8 |.  99            cdq                                             ; |

00586BE9  |.  6A18         push 18                                         ;|Arg3 = 180x18=24小时

00586BEB |.  52            push edx                                        ; |Arg2

00586BEC |.  50            push eax                                        ; |Arg1=> [ARG.1]

00586BED |.  8BF1          mov esi,ecx                                     ; |

00586BEF |.  E8 0C570000   call simcap.0058C300                            ; \simcap.0058C300

…….

00586C01  |.  6A3C         push 3C                                         ;|Arg3 = 3C, 0x3C=60分钟

…….

00586C19  |.  6A3C         push 3C                                         ;|Arg3 = 3C, 0x3C=60秒钟

 

========= 2. 修改右键菜单“Copy Ctrl+C ==========

上面时间已经搞定了,下面说说怎么修改右键菜单“Copy Ctrl+C”,因为这个软件是用MFC开发的(当你在odb中看到call dword ptr ds:[<&MFC80.#876>]这种调用就一切明白了,什么?还不明白,赶快对着墙壁立正),对了,忘了说这个软件是没有加壳的,不用费那劲去脱壳,MFC里面的右键菜单,一般会调用TrackPopupMenu,第一件事要做的就是,拦截WM_RBUTTONUP消息,怎么拦截捏,在odb里面,你得先找到每个窗口的入口地址,按”Alt+W”就会弹出被调试软件已经打开的所有窗口列表,跟Spy++类似的功能,然后找到你要找的那个窗口的句柄,右键选择“跟随ClassProc”,然后odb就会跳到WinProc(…)程序入口处,但有的窗口没有重载这个函数,那就会跳到user32.dll的领空,

77D2C17E /$  6A 14         push 14          ;LRESULT USER32.DefWindowProcA(guessed hWnd,Msg,wParam,lParam)

这是默认的窗口过程函数,遇到它很多次后,你会觉得这个函数除了浪费时间一点意思都莫得,好,废话不多说,我现在要爆破下面图中的”Plot/List Plot [M1]”窗口的右键菜单的’Copy Ctrl+C”功能,默认情况下,这一菜单项是变灰的,由于菜单很难截图,就没放菜单的图片了,下面第一步要做的是拦截WM_RBUTTONUP,怎么拦截捏,在odb中设条件断点,最好是在MFC80.dll领空,消息分发处设,如下:

782027A0 55   push ebp   ;CWnd:: OnWndMsg(UINT message,WPARAM wParam,LPARAM lParam,LRESULT* pResult);

设置条件断点为: [esp+4]==205 (注意:WM_RBUTTONUP = 0x0205)

然后一直按F8跟随吧,


反正我是找了2天,才找着真正的消息搬运工:

BOOL CCmdTarget::OnCmdMsg(UINT nID, intnCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)

如下图:


而我又已经知道了"Copy Ctrl+C"对应的资源id号为0xE122,至于怎么知道的,可以用PEView.exe直接找到exe的全部资源信息,当然pexplorer.exe更强大,在MFC80领空0x7822AFDB处下条件断点:[ESP+4]==E122,至于为什么这样下就不多说了,最后你会发现下面寻她千百度的画面:


这个0x006927D0地址处对应的是结构

struct AFX_MSGMAP_ENTRY

 {

  UINT nMessage;  //Windows消息ID,对应图中0x00000111WM_COMMAND

  UINT nCode;   //对应图中0xFFFFFFFF=-1=CN_UPDATE_COMMAND_UI

  UINT nID;  //对应图中0x0000E122” CopyCtrl+C”的资源id

  UINT nLastID;  //对应图中0x0000E122

  UINT nSig;   //对应图中0x00000040

  AFX_PMSG pfn;  //对应图中0x004668E0,这个地址非常重要

 };

接下来就跳转到simcap.exe领空的0x004668E0处,然后就可以干坏事了,呵呵


修改后就可以使用拷贝这个功能了,太帅了

========= 3. 修改右键菜单Save List As ...Save Plot As ... ==========

和修改“Copy Ctrl+C”一样的道理,修改这两项,不过道路要曲折得多了,全靠你的耐心去发现所有的AFX_MSGMAP_ENTRY这样的结构,不仅仅是在simcap.exe这个文件里面找这个结构喔,还得到可能调用的40dll文件里面搜索这个结构啊,这个过程是漫长的并且无聊的。不过一份付出就一份收获是万万没错的。反正我是在茫茫的40dll找到了所有涉及到响应“Save List As ...Save Plot As ...”这两个IDAFX_MSGMAP_ENTRY

========= 4. 修改图片中”Demo”字样水印 ==========

其实修改图片中”Demo”字样水印是最难的,一开始我并不知道有这么难,一开我将所有的dll导出的函数中凡是含有”Draw”,”Plot”关键字样的函数全部下断,结果一无所获,3天就这么被浪费了,后来改变了策略,考虑到画图一定会调用BitBlt,TextOutA,LoadBitmapAAPI,我就专门在这些地方蹲点,结果除了一遍遍的观摩这些API,全是在崩溃的边缘徘徊,木有办法,只有使用最后的绝招,狂按F8,最后umch2d.dll这个魂淡露出了圆型,


奶奶个熊,原来是用StretchDIBits(…)这么变态的函数来画图,哥以前从未用过这个API,并且塔凉的那张图片居然不是以明码方式存储的图片,更BT的是它是被放在"C:\Documents and Settings\dell\ApplicationData\Umetrics\SIMCA-P\11.5 Demo\dd.dll"这个塔儿,尼玛更更BT的是,这个dd.dll看起来是个dll,实际上是个锤子,而那张含”Demo”字样图片的数据就存在这个文件里面,我勒个擦,真想说张话,只要让哥找到你丫的藏身之处,那你就乖乖的占到墙角吧,然后顺藤摸瓜把umch2d.dll(另一个umch3d.dll里面居然是用OpenGL画的图,也被我发现了,哈哈)里面对应的代码改掉,就一下子天变得那么蓝,乌云变得那么白,今晚的月亮妹妹是多么的冻人啊,啦啦啦,啦啦啦,我是卖报的小行家,……… 收工回家



 

                                       --------作者:过客

                                       --------邮箱:  386520874@qq.com

                                       --------时间:2014.01.10凌晨于深圳盐田  

========================================================================
simcap.exe下载链接:http://pan.baidu.com/s/1AHq8Y
 


0 1
原创粉丝点击