首页
论坛
课程
招聘
[原创]超级电话通算法分析及ESP定律操作详解,附内存注册机及如何一步步编写VC完美注册机功能篇(上)
2007-9-29 01:26 9662

[原创]超级电话通算法分析及ESP定律操作详解,附内存注册机及如何一步步编写VC完美注册机功能篇(上)

2007-9-29 01:26
9662
【文章标题】: 超级电话通算法分析及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

【看雪培训】《Adroid高级研修班》2022年夏季班招生中!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (11)
雪    币: 49
活跃值: 活跃值 (16)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
壹只老虎 活跃值 7 2007-9-29 07:28
2
0
辛苦了!
不错不错!~`
雪    币: 324
活跃值: 活跃值 (17)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
likunkun 活跃值 1 2007-9-29 11:08
3
0
顶一下
不错
雪    币: 276
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
大菜一号 活跃值 21 2007-9-30 07:59
4
0
喂`楼主,我说那个界面怎么做嘿嘿嘿`
雪    币: 252
活跃值: 活跃值 (47)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wyqzm 活跃值 1 2007-10-2 18:18
5
0
前提是你要有一个皮肤文件,一个.h头文件和一个.lib库文件.
先在StdAfx.h中加入
#include "Skin*.h"  //隐藏的具体的名字,呵呵
#pragma comment(lib, "Skin*.lib")

貌似像这样的,在VC的InitInstance()函数中加载皮肤,像
VERIFY( 1 == InitSkinMagicLib(AfxGetInstanceHandle(), NULL, NULL, NULL));
VERIFY( 1 == LoadSkinFile("corona.smf"));

在退出的过程中加入
ExitSkinMagicLib();就可以了

下载附件: skin_demo.rar
上传的附件:
雪    币: 193
活跃值: 活跃值 (17)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
CCDeath 活跃值 9 2007-10-2 19:20
6
0
skin++她针对每种语言 都有自己的语言的皮肤库,也就是说本来在VC使用的皮肤库,就不可以在delphi语言使用,必须去找支持delphi的皮肤库...在勇进公司的主页有下载,它也使用说明...好象delphi有破解版的皮肤库...不然他在你程序启动时,会先出现一个你未注册版本皮肤...其实也可以自己写皮肤了....比较丑而已了...源代码就从楼上那个好心人下吧....
雪    币: 245
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
Winter-Night 活跃值 5 2007-10-2 22:39
7
0
delphi好像能用E的皮肤库,E的皮肤库从ppstream网站上下就可以了:)
雪    币: 252
活跃值: 活跃值 (47)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wyqzm 活跃值 1 2007-10-2 23:39
8
0
试过,VC也能用易的skin,楼主提供一下皮肤吧.我这有个相当的,但稍有不同.

另指出一句问题

      if(sMac=="")
      {
              AfxMessageBox("请复制机器码,机器码不能为空");
              return; //加上这一句,否则你的程序并不会退出这个过程的.
      }

随贴附上demo源程序,为避免有传播真实注册机之嫌疑,本demo程序仅演示皮肤的加载,xm音乐的加入,并对注册机产生的结果作了修改,并不能对应楼主的真实结果,如需要看到成果,请重新编译!

平台: winxp+sp2
环境: VC++6.0(sp6)

效果:

demo附件下载: Key.rar
上传的附件:
雪    币: 193
活跃值: 活跃值 (17)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
CCDeath 活跃值 9 2007-10-3 00:39
9
0
谢谢楼上了,我在国庆那天晚上已经修正了这个问题.把音乐嵌入到程序中去了,并使它循环播放...
还添加多种皮肤切换...
皮肤一效果图:
皮肤二效果图:
皮肤三效果图:

关键代码: 针对楼上提出的问题,我在国庆无聊的时候也发现这个问题,谢谢你
void CCCDeathDlg::OnButGen()
{
       
        UpdateData(true);
     CString  sMac;//存放机器码字符串
        CString  sMacHex;//存放机器码转化为16进制字符串,Hex代表16
        CString  sMacRev;//存放机器码倒序后的字符串,Rev代表Reverse
        CString  sTemp;//格式化中间字符串       

        this->m_Mac.GetWindowText(sMac);//取得机器码

//============把机器码转化十六进制
          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);
//====修正的地方
        if(sMac=="")
        {
                this->m_Reg.SetWindowText("");
                AfxMessageBox("请复制机器码,机器码不能为空");               
        }
        else
        {
                AfxMessageBox("恭喜注册成功!欢迎使用CCDeath注册机");
        }
        UpdateData(false);       

}
------------------------------皮肤变换关键代码,我只是用了三种皮肤而已,可以再加

void CCCDeathDlg::OnChange()
{
   ecx++;                      //计数器
   if(ecx==4)
   {
           ecx=1;
   }
   switch(ecx)
   {
   case 1: {theApp.SetSkin(_T("AquaOS.ssk"));   break;}  //加载皮肤一
   case 2: {theApp.SetSkin(_T("bOzen.ssk")) ;   break;}  //加载皮肤二
   case 3: {theApp.SetSkin(_T("xp_corona.ssk"));break;}//加载皮肤三
   }

   InvalidateRect(false);//重绘窗体
}
上传的附件:
雪    币: 219
活跃值: 活跃值 (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
daxuebin 活跃值 2007-10-3 15:46
10
0
前提是你要有一个皮肤文件,一个.h头文件和一个.lib库文件.wyqzm能提供你的.h头文件和.lib库文件吗?
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
钟浩田 活跃值 2007-10-3 17:01
11
0
无语,全是牛人~
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大大连连 活跃值 2007-10-23 10:59
12
0
辛苦拉,很有成绩的~~
游客
登录 | 注册 方可回帖
返回