okGIF Movie Gear v3.0.2 破解小谈(附注册机源码)
最近在老罗的坛子里好多人的签名都换成了PL的图片。嘿嘿,偶自然也不愿落后,so便想自己DIY一个英俊潇洒玉树临风貌比潘安才比伯虎的挂上去,可是以前买的Flash MX D版盘怎么也找不到了,于是便到天空那边儿去找做GIF动画的软件,再于是便找到了这个软件,据说是使用简单,方便快捷…
结果,呵呵(冷汗…搞了一个上午也没搞出张像样的图片来)。偷鸡不成,怎么也要抓一把米回来吧,反正今天除了没完成的事儿其它的事儿都做完了… ;)
首先当然是先要看一下人家有没有加壳,结果是另人满意的,过程是另人愉快的,答案是VC6.0的。^_^具然没加壳…
那还等什么呢?点Help菜单中的Register Now…。接着就呼出你埋伏已久的调试器吧,我用的是TRW2000。(随便问一句哥们儿,TRW2000呼出是按Ctrl+N这事儿你知道吧,知道啊。那上海2010年办世博会,这事儿你也知道吧,哦,都知道了,那甲A前天晚上…当!…好好好,我继续就是了)呼出TRW2000后下断点bpx hmemcpy(我用的是98嘛),然后按F5返回。接着在Name处偶输入Suunb[CCG],在Code处输入20030413(呵呵,今天的日期 ^_^) 好的,接下来就按OK吧。
结果是显而易见的,成功被我军爱国者导弹给拦截掉了。之后就一个pmodule导弹过去跳出程序的领空,之后在按F12的时候会发现只按1次就提示出错了。
好的,知道这些后,就再来一遍吧。这次在pmodule返回后就按F10来单步执行,代码如下:
0167:00431972 lea edx,[esp+c4] <--会来到这里!
0167:00431979 push byte +64
0167:0043197b push edx
0167:0043197c push dword 0450
0167:00431981 push esi
0167:00431982 call edi <--看上边儿压进去的参数,这个Call应该是调用API函数GetDlgItem来得到注册码输入框的句柄。
0167:00431984 push eax
0167:00431985 call ebx <--用先前得到的注册码输入框的句柄通过调用GetWindowTextA来得到输入的注册码
0167:00431987 lea eax,[esp+c4] <--用d指令可以知道esp+c4处装的是用户输入的注册码,将这个地址装入eax中
0167:0043198e lea ecx,[esp+60] <--同样用d指令可以知道esp+60处装的是用户输入的注册名,装其地址装入ecx中
0167:00431992 push eax <--注册码地址压栈
0167:00431993 push ecx <--注册名地址压栈
0167:00431994 call 00431590 <--嘿嘿,整个过程就由这个CALL一手操控了
0167:00431999 add esp,byte +08 <--栈顶还原
0167:0043199c test eax,eax <--测试eax中装入的值
0167:0043199e jz near 00431a51 <--为0就跳到00431a51处,跳过去就Over了
0167:004319a4 lea edx,[esp+10] <--从这里开始程序通过调用RegCreateKeyExA、RegSetvalueExA等其它一些注册表相关API来向注册表中写入用户的注册信息。也就是HKEY_CURRENT_USER\Software\gamani\GIFMovieGear\2.0主键下面的RegName3与RegCode3子键。当然这是在你输入的注册码正确的前提下,RegName3中装的是你的注册名,RegCode3中自然就是你输入的册码了…
0167:004319a8 lea eax,[esp+0c]
0167:004319ac push edx
0167:004319ad push eax
0167:004319ae push byte +00
0167:004319b0 push dword 000f003f
0167:004319b5 push byte +00
0167:004319b7 push dword 0044ed14
0167:004319bc push byte +00
0167:004319be push dword 0044b3f8 <--此处可以看一下0044b3f8,得到Software\gamani\GIFMovieGear\2.0
0167:004319c3 push dword 80000001 <--这个值就是HKEY_CURRENT_USER
0167:004319c8 call `ADVAPI32!RegCreateKeyExA` <--API函数RegCreateKeyExA
0167:004319ce lea edi,[esp+60]
0167:004319d2 or ecx,byte -01
0167:004319d5 xor eax,eax
0167:004319d7 mov edx,[esp+0c]
0167:004319db repne scasb
0167:004319dd not ecx
0167:004319df mov ebx,[00448018]
0167:004319e5 push ecx
0167:004319e6 lea ecx,[esp+64]
0167:004319ea push ecx
0167:004319eb push byte +01
0167:004319ed push eax
0167:004319ee push dword 0044d498 <--0044d498处就是字符串RegName3
0167:004319f3 push edx
0167:004319f4 call ebx <--RegSetvalueExA
0167:004319f6 lea edi,[esp+c4]
0167:004319fd or ecx,byte -01
0167:00431a00 xor eax,eax
0167:00431a02 repne scasb
0167:00431a04 not ecx
0167:00431a06 lea eax,[esp+c4]
0167:00431a0d push ecx
0167:00431a0e mov ecx,[esp+10]
0167:00431a12 push eax
0167:00431a13 push byte +01
0167:00431a15 push byte +00
0167:00431a17 push dword 0044d4a4 <--0044d4a4嘛,就是字符串RegCode3
0167:00431a1c push ecx
0167:00431a1d call ebx <--RegSetvalueExA
0167:00431a1f mov edx,[esp+0c]
0167:00431a23 push edx
0167:00431a24 call `ADVAPI32!RegCloseKey`
0167:00431a2a push dword 0044d4b0
0167:00431a2f push dword 80000002
0167:00431a34 call `ADVAPI32!RegDeleteKeyA`
0167:00431a3a push byte +01
0167:00431a3c push esi
0167:00431a3d call `USER32!EndDialog` <--用EndDialog来关掉输入注册码的这个对话框
0167:00431a43 pop edi
0167:00431a44 pop esi
0167:00431a45 xor eax,eax
0167:00431a47 pop ebx
0167:00431a48 add esp,011c
0167:00431a4e ret 10 <--返回
0167:00431a51 push byte +30 <--在前边儿0043199c处如果没通过就会跳到这里,到了这里就一切都玩儿完了 ;)
0167:00431a53 push dword 9d15
0167:00431a58 push dword 9d14
0167:00431a5d push esi
0167:00431a5e call 0040ee90
0167:00431a63 add esp,byte +10
0167:00431a66 push dword 044f
0167:00431a6b push esi
0167:00431a6c call edi
0167:00431a6e push eax
0167:00431a6f call `USER32!SetFocus`
0167:00431a75 pop edi
0167:00431a76 pop esi
0167:00431a77 xor eax,eax
0167:00431a79 pop ebx
0167:00431a7a add esp,011c
0167:00431a80 ret 10
HeHe~~很明显吧,00431994处的那个CALL就是关键的所在嘛。
也就是说如果在00431994处的那个CALL中程序确定注册码是正确的话就会将其与用户名一同输入进注册表,以后每次程序启动的时候都会进行比较。But你输入的是错误的话嘛,程序就懒得去写进注册表了。所以我们尽管可以在0043199c处的时候用r fl z指令来欺骗程序,但一点儿用都没有 (众人:那你说它干嘛)
那接着就再来一遍,这次就可以直接用断点bpx 00431994了。断到后就按F8跟进去吧:
0167:00431590 push ebx
0167:00431591 push ebp
0167:00431592 mov ebp,[esp+10] <--将注册码的地址装入ebp中
0167:00431596 push esi
0167:00431597 push edi
0167:00431598 cmp byte [ebp+00],6d <--ebp+00也就是注册码的第一位,用注册码的第一位与6d相比(6d即m的ASCII码)
0167:0043159c jnz near 00431642 <--第一位不是m就跳到00431642处,跳过去就玩儿完了。呵呵,我输入的是20030413,在这里就挂掉了,再来一遍,这次把前4位改成mg37,即mg3720030413
0167:004315a2 cmp byte [ebp+01],67 <--判断注册码的第2位是否为g
0167:004315a6 jnz near 00431642
0167:004315ac cmp byte [ebp+02],33 <--同理,判断第3位是否为3
0167:004315b0 jnz near 00431642
0167:004315b6 cmp byte [ebp+03],37 <--第4位是否为4
0167:004315ba jnz near 00431642
0167:004315c0 mov ebx,0044d4c4
0167:004315c5 mov edx,[ebx]
0167:004315c7 or ecx,byte -01
0167:004315ca mov edi,edx
0167:004315cc xor eax,eax
0167:004315ce repne scasb
0167:004315d0 not ecx
0167:004315d2 dec ecx
0167:004315d3 mov edi,edx
0167:004315d5 mov esi,ebp
0167:004315d7 xor eax,eax
0167:004315d9 repe cmpsb
0167:004315db jz 00431642
0167:004315dd add ebx,byte +04
0167:004315e0 cmp ebx,0044d4c8
0167:004315e6 jl 004315c5
0167:004315e8 cmp byte [ebp+04],73 <--比较看注册码的第5位是否为s,ebp中装的其实是注册码的地址,这点很重要,后边儿会有说明
0167:004315ec jnz 004315ef <--不是就跳到004315ef处
0167:004315ee inc ebp <--是的话ebp+1
0167:004315ef add ebp,byte +07 <--ebp加上7
0167:004315f2 push ebp <--ebp入栈
0167:004315f3 call 0043f3c8 <--!!
0167:004315f8 mov edx,[esp+18]
0167:004315fc add esp,byte +04
0167:004315ff mov edi,edx
0167:00431601 xor ecx,ecx <--ecx清0
0167:00431603 mov dl,[edx] <--装入注册名中的第一个字符
0167:00431605 mov esi,0bdf <--esi中装入0bdf,即十进制数3039
0167:0043160a test dl,dl <--看dl中是否为0
0167:0043160c jz 00431634
0167:0043160e movsx edx,dl <--霸占整个edx寄存器 ;)
0167:00431611 inc ecx <--ecx加1
0167:00431612 imul edx,ecx <--用edx中此时装入的注册名中的某一位字符乘的ASCII码乘以ecx中的值
0167:00431615 add esi,edx <--用esi中的值加上edx中的值
0167:00431617 cmp esi,17be <--用esi中的值与17be,即十进制数6078比较
0167:0043161d jng 00431625 <---不大于不跳到00431625处
0167:0043161f sub esi,17be <--大于的话就减去它
0167:00431625 cmp ecx,byte +0a <--用A(也就是10)与ecx中的值比较
0167:00431628 jng 0043162c <--不大于就跳到0043162c处
0167:0043162a xor ecx,ecx <--ecx清0
0167:0043162c mov dl,[edi+01] <--dl中装入注册名中的下一个字符
0167:0043162f inc edi <--edi加上1
0167:00431630 test dl,dl <--测试dl
0167:00431632 jnz 0043160e <--不为0就跳加0043160e处继续用下一位来进行计算
0167:00431634 cmp esi,eax <--比较esi与eax中的值,esi中装入的就是前边儿0043160e-00431632处将注册名中各位字符进行计算后的值,而eax中的值是通过004315f3处的这个CALL装进来的,相对于我输入的这个注册名及注册码,它的值是76CD,也就是十进制数30413。
0167:00431636 jnz 00431642 <--不相等就跳到00431642处
0167:00431638 pop edi
0167:00431639 pop esi
0167:0043163a pop ebp
0167:0043163b mov eax,01 <--相等的话就继续执行到这里,并将eax置1,我们已经知道出来后会比较看eax是否为0,是的话就Game Over
0167:00431640 pop ebx
0167:00431641 ret
0167:00431642 pop edi <--从前面跳过来的话就…
0167:00431643 pop esi
0167:00431644 pop ebp
0167:00431645 xor eax,eax <--可恶吧,会将eax置0
0167:00431647 pop ebx
0167:00431648 ret
我认为我有必要讲一下,其实这并不难理解。在004315e8处的时候我们可以通过d指令知道ebp中装的其实就是注册码的地址,在004315e8处的时候会比较注册码的第5位是否为s,是的话就将ebp加上1。而到了004315ef处的时候会将ebp加上7,之后就将这个地址压栈了。过了004315f3处的那个CALL后EAX中的值就会改变了,完全不必要追进去,猜也能猜出来了。呵呵,这个CALL的作用就是将之前004315f2处压入的ebp中的地址处开始的值装入eax中。而ebp中装的就是注册码的第7位的地址,明白过来了吗?注册码从第7位开始的值就是程序真正要用的 ;)可问题是第7位以后还有几位呢?嘿嘿,这个很容易就能发现,在00431617的时候程序不是会判断esi中的值是否大于6078吗?而6078,也就是6078只有4位,所以嘛,注册码的位数就是7+4即11位!不过在004315e8和我们会发现程序会判断注册码的第5位是否为s,是的话就接着将ebp加上1,所以问题就解决了。正确的注册码位数只有两种情况:一种是11位,另一种是12位,这个12位的第5位是一个固定不变的,即s。
呵呵,我们来看一下正确的注册码的格式吧,第一种11位的是mg37XXXXXXX,另一种12位的是mg37sXXXXXXX。
现在我们知道的已经够多了,那就写注册机吧 ;)
这之前再大概说一遍程序注册码的计算过过程:
首先固定不变的是程序注册码的前4位,永远是mg37,然后有一个可有可无的位,即第5位,要这一位的话,就让它为s (注意如果注册码的第5位是s,那就应该在其后再补上3位),否则就不要它而直接在mg37后边儿随便补充3位,就比如说CCG ^_^。而接下来就是最后4位了,这个也是重要的地方所在了 ;) 后4位的计算过程其实也不难,就是用你输入的注册名的首位字符的ASCII码乘以X(X每计算一位字符就加上1,如果值后来一直累加到11,就会还原为0)。再用这个乘积加上3039。并将其保存起来,这里称它为Y,之后比较Y是否大于6078,如果大于就用Y减去6078。接下来第二位字符参加运算,同样用其值乘以X,然后加上Y,再比较Y是否大于6078,再接下来第三位字符参加运算,用其乘以X,然后加上Y…直到所有字符均参加完运算…
BTW:如果字符参加完运算后得到的是一个3位有效值,比如123,就在1的前边儿补上一个0,如0123。
贴的这个是注册机源码是Delphi的,直接声明这个函数就能用了:
function KeyGen(Name: String): String;
var
i,Cnt,vai,ASC:integer;
Serial:String;
begin
Cnt:=3039;
vai:=0;
for i:=1 to Length(Name) do
begin
inc(vai);
ASC:=Ord(Name[i]);
ASC:=ASC*vai;
Cnt:=Cnt+ASC;
if Cnt>6078 then Cnt:=Cnt-6078;
if vai>10 then vai:=0;
end;
Serial:=inttostr(Cnt);
Case Length(Serial) of
3:Serial:='0'+Serial;
2:Serial:='00'+Serial;
1:Serial:='000'+Serial;
end;
Serial:='mg37CCG'+Serial;
Result:=Serial;
end;
OK,就这些。
相关视频
相关阅读 Windows错误代码大全 Windows错误代码查询激活windows有什么用Mac QQ和Windows QQ聊天记录怎么合并 Mac QQ和Windows QQ聊天记录Windows 10自动更新怎么关闭 如何关闭Windows 10自动更新windows 10 rs4快速预览版17017下载错误问题Win10秋季创意者更新16291更新了什么 win10 16291更新内容windows10秋季创意者更新时间 windows10秋季创意者更新内容kb3150513补丁更新了什么 Windows 10补丁kb3150513是什么
热门文章 去除winrar注册框方法
最新文章
比特币病毒怎么破解 比去除winrar注册框方法
华为无线路由器HG522-C破解教程(附超级密码JEB格式文件京东电子书下载和阅读限制破解教UltraISO注册码全集(最新)通过Access破解MSSQL获得数据
人气排行 华为无线路由器HG522-C破解教程(附超级密码JEB格式文件京东电子书下载和阅读限制破解教UltraISO注册码全集(最新)qq相册密码破解方法去除winrar注册框方法(适应任何版本)怎么用手机破解收费游戏华为无线猫HG522破解如何给软件脱壳基础教程
查看所有0条评论>>