【文章标题】: 超级电话通算法分析及ESP定律操作详解,附内存注册机及如何一步步编写VC完美注册机
【文章作者】: CCDeath
【作者邮箱】: CCDeath@163.com
【软件名称】: 超级电话通3.05
【下载地址】: 自己搜索下载
【加壳方式】: ASPack 1.06b / 1.061b -> Alexey Solodovnikov
【保护方式】: 用户名
【使用工具】: OD+PEid
【操作平台】: 盗版中的最低版本XP
【软件介绍】: 查询...
【作者声明】: 如果有人觉得好用,请支持共享..希望多多批评和建议...CCDeath在此感激不尽
--------------------------------------------------------------------------------
【详细过程】
第四篇破文,高手飘过.....我尽量把每个步骤写的清晰点...天呀,我都快养成这种习惯...
好了,我们来热热身。
一.ESP定律:根据堆栈平衡原理,略说就是物归原主,大跳转的意思,详情请看某位牛人写的<<广义ESP定律>>
用VC一步步编写注册机:先看我前一篇:
第三篇破文【原创】用VC一步一步编写完美注册机(上)----界面篇(附带VC源代码,有美妙的音乐、超酷的动态鼠标 、
华丽的商业皮肤)-也可做VC入门
地址在这: http://bbs.pediy.com/showthread.php?t=52350
完美注册机功能篇(上)最终效果图:
来,我们来干掉她:
二.破解过程:
查壳ASPack 1.06b / 1.061b -> Alexey Solodovnikov,一个字“脱”,我们先在用ESP定律2种操作方式...大侠别笑我,
我很笨滴!
先来第一种了,用OD载入后,出现“不知如何继续,因为内存地址***”,天呀,我怎么知道呀,点确定,忽略异常接着
点否。看右边寄存器ESP:是0012FFC4.按F8,看到ESP又一次变红色,记录ESP地址为:00112FFA4,好了就是她了。看图:
图在这呢,我每张图都有详细的注释:
在命令行Command输入: dd 0012FFC4. 看图,找到这个地方右键"断点"->"硬件访问"->"word".为什么要这么下,置顶贴
有详细说明了。
图在这呢:
按F9运行,哈哈,看到一个jmp要条黄河了,继续按F8。ohoh,这就是传说中的OEP了。好了,右键Dump。有没有注意到现
在的ESP:是0012FFC4.接着dump出来的名称就要注意了,要跟原来一样,把原来那个重名其她名,不然运行时会提示错误
信息了。
OK,我们来第二种
跟上面一样走到ESP变红了,只是下断点方式不同而已了,输入hr 0012FFC4.接下来和上面一样了。
图在这呢:
--------------------------
查壳:Borland Delphi 4.0 - 5.0
伪装码:
用户名 ========CCDeath=======
注册码 ========123456789=====
用OD载入脱完壳的程序,查找字符串,来到这里:
0047EEB4 /. 55 push ebp ; 为什么找到这里,我不说了,基础请看我
前几篇,谢谢!
0047EEB5 |. 8BEC mov ebp, esp
0047EEB7 |. 81C4 C8FEFFFF add esp, -138 ; 分配堆栈空间
0047EEBD |. 53 push ebx
0047EEBE |. 56 push esi
0047EEBF |. 57 push edi
0047EEC0 |. 33C9 xor ecx, ecx
0047EEC2 |. 898D C8FEFFFF mov dword ptr [ebp-138], ecx
0047EEC8 |. 898D CCFEFFFF mov dword ptr [ebp-134], ecx
0047EECE |. 8945 FC mov dword ptr [ebp-4], eax
0047EED1 |. 33C0 xor eax, eax
0047EED3 |. 55 push ebp
0047EED4 |. 68 C9F04700 push 0047F0C9
0047EED9 |. 64:FF30 push dword ptr fs:[eax]
0047EEDC |. 64:8920 mov dword ptr fs:[eax], esp
0047EEDF |. 33F6 xor esi, esi
0047EEE1 |. 8D95 CCFEFFFF lea edx, dword ptr [ebp-134]
0047EEE7 |. 8B45 FC mov eax, dword ptr [ebp-4]
0047EEEA |. 8B80 D8020000 mov eax, dword ptr [eax+2D8]
0047EEF0 |. E8 0331FBFF call 00431FF8
0047EEF5 |. 8B95 CCFEFFFF mov edx, dword ptr [ebp-134] ; 出现我们的用户名
0047EEFB |. 8D85 D0FEFFFF lea eax, dword ptr [ebp-130] ; 用户名长度也出来了
0047EF01 |. B9 FF000000 mov ecx, 0FF
0047EF06 |. E8 714DF8FF call 00403C7C
0047EF0B |. 8D95 D0FEFFFF lea edx, dword ptr [ebp-130]
0047EF11 |. 8D45 D2 lea eax, dword ptr [ebp-2E]
0047EF14 |. B1 14 mov cl, 14
0047EF16 |. E8 F13AF8FF call 00402A0C
0047EF1B |. 8A55 D2 mov dl, byte ptr [ebp-2E]
0047EF1E |. 84D2 test dl, dl ; 用户名是否为空
0047EF20 |. 76 1C jbe short 0047EF3E
0047EF22 |. B1 01 mov cl, 1
0047EF24 |. 8D45 D3 lea eax, dword ptr [ebp-2D]
0047EF27 |> 33DB /xor ebx, ebx
0047EF29 |. 8A18 |mov bl, byte ptr [eax] ; 从头往尾一个一个的取出字符
0047EF2B |. 8BF9 |mov edi, ecx ; 计数器i
0047EF2D |. 81E7 FF000000 |and edi, 0FF ; i=i&&0FF
0047EF33 |. 0FAFDF |imul ebx, edi ; R(i)*i即第i个字符的ASCII乘以i
0047EF36 |. 03F3 |add esi, ebx ; 把最终的结果存放
0047EF38 |. 41 |inc ecx ; ++
0047EF39 |. 40 |inc eax ; ++
0047EF3A |. FECA |dec dl ; --
0047EF3C |.^ 75 E9 \jnz short 0047EF27 ; 是不是每个字符都处理完毕?
0047EF3E |> B8 E0EA0B00 mov eax, 0BEAE0 ; 把常数0BEAEO
0047EF43 |. 2BC6 sub eax, esi ; eax=把这个常数减去上面循环所得到的结
果.肯定有阴谋,接着往下走
0047EF45 |. 8BF0 mov esi, eax
0047EF47 |. 8D45 E7 lea eax, dword ptr [ebp-19]
0047EF4A |. 8D55 D2 lea edx, dword ptr [ebp-2E]
0047EF4D |. B1 14 mov cl, 14
0047EF4F |. E8 B83AF8FF call 00402A0C
0047EF54 |. 8A55 E7 mov dl, byte ptr [ebp-19]
0047EF57 |. 84D2 test dl, dl
0047EF59 |. 76 20 jbe short 0047EF7B
0047EF5B |. B1 01 mov cl, 1
0047EF5D |. 8D45 E8 lea eax, dword ptr [ebp-18]
0047EF60 |> F6C1 01 /test cl, 1 ; 好了,我们来看下面这个循环
0047EF63 |. 74 09 |je short 0047EF6E
0047EF65 |. 8A18 |mov bl, byte ptr [eax] ; 从头往尾一个一个用户名字符串
0047EF67 |. 80F3 52 |xor bl, 52 ; 与52异或
0047EF6A |. 8818 |mov byte ptr [eax], bl ; 存储这个经过运算的字符字符
0047EF6C |. EB 07 |jmp short 0047EF75
0047EF6E |> 8A18 |mov bl, byte ptr [eax] ; 跟上面一样同时存储
0047EF70 |. 80F3 4C |xor bl, 4C
0047EF73 |. 8818 |mov byte ptr [eax], bl
0047EF75 |> 41 |inc ecx
0047EF76 |. 40 |inc eax
0047EF77 |. FECA |dec dl
0047EF79 |.^ 75 E5 \jnz short 0047EF60 ; 处理完每个字符
0047EF7B |> 8D95 C8FEFFFF lea edx, dword ptr [ebp-138] ; 上面经过运算后是:[eax]=11cdc38:接着
往下走发现这个根本就没用处,折磨人而已
0047EF81 |. 8BC6 mov eax, esi
0047EF83 |. E8 C095F8FF call 00408548 ; 由下面判断是个关键CALL1
0047EF88 |. 8B85 C8FEFFFF mov eax, dword ptr [ebp-138] ; 晕,突然出来一串字符,肯定上面那个
CALL做的手脚,跟进上面CALL
0047EF8E |. 50 push eax ;把我们得到字符串"778306"
0047EF8F |. 8D95 CCFEFFFF lea edx, dword ptr [ebp-134]
0047EF95 |. 8B45 FC mov eax, dword ptr [ebp-4]
0047EF98 |. 8B80 E4020000 mov eax, dword ptr [eax+2E4]
0047EF9E |. E8 5530FBFF call 00431FF8
0047EFA3 |. 8B95 CCFEFFFF mov edx, dword ptr [ebp-134] ;假的注册码"123456789"
0047EFA9 |. 58 pop eax
0047EFAA |. E8 014EF8FF call 00403DB0 ; 经典模式关键CALL2
0047EFAF |. 0F85 D8000000 jnz 0047F08D
0047EFB5 |. 8B15 48E14800 mov edx, dword ptr [48E148] ; Scbook.00490184
---------------
分析一下关键CALL1:进来
00408548 /$ 83C4 F8 add esp, -8
0040854B |. 6A 00 push 0 ; /Arg1 = 00000000
0040854D |. 894424 04 mov dword ptr [esp+4], eax ; |eax,就是上面常数减去运算后的结果
00408551 |. C64424 08 00 mov byte ptr [esp+8], 0 ; |
00408556 |. 8D4C24 04 lea ecx, dword ptr [esp+4] ; |
0040855A |. 8BC2 mov eax, edx ; |
0040855C |. BA 74854000 mov edx, 00408574 ; |ASCII "%d"//看到这个没有,转化为十进制
拿出计算器,呵呵,还真的是这样,就是真的注册码
00408561 |. E8 9E0B0000 call 00409104 ; \Scbook.00409104
00408566 |. 59 pop ecx
00408567 |. 5A pop edx
00408568 \. C3 retn
-----------------
分析关键CALL2:
00403DB0 /$ 53 push ebx
00403DB1 |. 56 push esi
00403DB2 |. 57 push edi
00403DB3 |. 89C6 mov esi, eax ;真的注册码
00403DB5 |. 89D7 mov edi, edx ;假的注册码
00403DB7 |. 39D0 cmp eax, edx ;真假较量
00403DB9 |. 0F84 8F000000 je 00403E4E ;不相等就Death
------------------
经验总结:
用户名的ASCII
C C D e a t h
ASCII 43 43 44 65 61 74 68 上面
位置 1 2 3 4 5 6 7 下面
上面与下面对应相乘,在相加ASCII(i)*i=43*1+43*2+ 44*3+65*4+64*5+74*6+68*7=00000A9E
取出一个常数:000BEAE0-00000A9E=000BE042.在把000BE042转化为十进制就是778306.好了778306就是真的注册码
------------------
先来写内存注册机如下---友情提示:真的注册码放在EAX上,不是EDX。
中断地址:0047EFAA
中断次数:1
第一字节:E8
指令长度:5
看图:呀,还真的是778306
------------------
我们来写带有漂亮界面,又有动态光标,又有音乐的注册机。我写的是上次发那篇注册机,这次的注册机就留给想学VC的
思。
来。我看上次的算法:
取得机器码8位为:Y21A5WQC,接着把机器码转化为16进制字符(共16个),接着把这16个字符倒序。
取出此时机器码前四位为N1="3415",接着从第五位取出四个字符为N2="7553".
固定字符出场了C26P-Q618,取出其前四位为N3="C26P",取出其后五位为N4="-Q618"
开始组合为: N3+'-'+N1+N4+'-'+N2 ="C26P-3415-Q618-7553"
来,我看下图,注册机运行的结果是不是这样子的呢?OK就是这样也是"C26P-3415-Q618-7553"
源代码:
void CCCDeathDlg::OnButGen()
{
UpdateData(true);
CString sMac;//存放机器码字符串
CString sMacHex;//存放机器码转化为16进制字符串,Hex代表16
CString sMacRev;//存放机器码倒序后的字符串,Rev代表Reverse
CString sTemp;//格式化中间字符串
this->m_Mac.GetWindowText(sMac);//取得机器码
if(sMac=="")
{
AfxMessageBox("请复制机器码,机器码不能为空");
}
//============把机器码转化十六进制
for(int i=0;i<sMac.GetLength();i++)
{
sTemp.Format("%x",sMac[i]);
sMacHex= sMacHex+sTemp;
}
//============把转化后的机器码进行倒序
char *pstr;
pstr=(LPSTR)(LPCTSTR)sMacHex;
sMacRev=fun(pstr);
//============拆分
//1.对固定值进行拆分
CString staValve="C26P-Q618";//staVale代表:static valve
CString staFirst=staValve.Left(4);//N3
CString staEnd=staValve.Right(5);//N4
//2.对倒序的机器码进行拆分
CString MacFirst=sMacRev.Left(4);//N1
CString MacEnd=sMacRev.Mid(4,4);//N2
//=============开始进行连接
CString sReg;
sReg=staFirst+'-'+MacFirst+staEnd+'-'+MacEnd;
//最终成功生成注册码
this->m_Reg.SetWindowText(sReg);
AfxMessageBox("恭喜注册成功!欢迎使用CCDeath注册机");
UpdateData(false);
}
后记:我也对VC进行编辑框字符串操作,一点了解都没有,一直网找呀,结果找不到资料和一些封装的函数。天呀,我头晕,
只好自己看着MSDN重新写。调试了一天,终于到现在完成了。OK,Let's continue.....
这个软件早在01精华集有,但只给中文算法,什么都没有做,大家可以查查,所以我就重新分析....希望多多批评和建议...CCDeath在此感激不尽...Good-night!...
此文所有贴图: 此文所有图片下载.rar
完美注册机关键代码下载: 关键源代码下载.rar
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年09月29日 1:01:43
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课