as3852711 发表于 2009-5-6 19:55:40

XX电话通 算法分析+Delphi注册机

标 题: 【原创】 XX电话通 算法分析+Delphi注册机
作 者: as3852711
时 间: 2009-05-06,20:20
链 接: https://www.chinapyg.com/viewthread.php?tid=45977&extra=page%3D1&frombbs=1

―――――――――――――――――――――――――――――――――――――
【文章标题】: XX电话通 算法分析+Delphi注册机
【文章作者】: 莱莉
【程序名称】: XX电话通.exe
【程序大小】: 1.01 MB
【下载地址】: http://www.rayfile.com/zh-cn/files/508980bd-3a31-11de-a7f4-0014221b798a/
【保护方式】: 注册码
【编写语言】: Borland Delphi 6.0 - 7.0
【使用工具】: PEID,OD
【操作平台】: D-Windows XP3
【程序介绍】: 一个供给菜鸟学习的练手程序.
【作者声明】: 我只是一只小菜鸟,失误之处难免,敬望诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这是一个过期的软件,是N年的前估计已经没什么用了,不过算法就比较简单较为适合我们这种菜鸟学习算法时来练手!


一、用PEID对程序进行查壳 → UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo ,用ESP定律秒脱,脱完后修复一下便可.

二、用OD载入程序进行分析。

载入OD后运行程序,试注册一下,有错误提示。用F12暂停法来到下面的地方(0048DA63)。然后我们到段首(0048D628)设置断点.
------------------------------(第一部分)----------------------------------------------------------
0048D628    55            push    ebp
0048D629    8BEC            mov   ebp, esp
0048D62B    B9 6E000000   mov   ecx, 6E
0048D630    6A 00         push    0
0048D632    6A 00         push    0
0048D634    49            dec   ecx
0048D635^ 75 F9         jnz   short 0048D630
0048D637    51            push    ecx
0048D638    53            push    ebx
0048D639    56            push    esi
0048D63A    57            push    edi
0048D63B    8945 FC         mov   dword ptr , eax
0048D63E    33C0            xor   eax, eax
0048D640    55            push    ebp
0048D641    68 BEDC4800   push    0048DCBE
0048D646    64:FF30         push    dword ptr fs:
0048D649    64:8920         mov   dword ptr fs:, esp
0048D64C    E8 D7EEFFFF   call    0048C528                         ; 到我们C盘的这个目录获取一些数值:"C:\Documents and Settings\All Users"
0048D651    E8 2254F7FF   call    00402A78                         ; 对数值作运算;
0048D656    52            push    edx
0048D657    50            push    eax
0048D658    8D85 F0FCFFFF   lea   eax, dword ptr
0048D65E    E8 F1ABF7FF   call    00408254                         ; 同上;
0048D663    8B85 F0FCFFFF   mov   eax, dword ptr
0048D669    E8 CE6CF7FF   call    0040433C
0048D66E    48            dec   eax
0048D66F    50            push    eax
0048D670    E8 B3EEFFFF   call    0048C528                         ; 也是到C盘获取数值;
0048D675    E8 FE53F7FF   call    00402A78                         ; 同样是运算得到的数值;
0048D67A    52            push    edx
0048D67B    50            push    eax
0048D67C    8D85 ECFCFFFF   lea   eax, dword ptr
0048D682    E8 CDABF7FF   call    00408254
0048D687    8B85 ECFCFFFF   mov   eax, dword ptr          ; 计算后得到一个字符串,我的是(ASCII "2953");
0048D68D    8D8D F4FCFFFF   lea   ecx, dword ptr
0048D693    5A            pop   edx
0048D694    E8 4F1DFAFF   call    0042F3E8                         ; 把字符串截取到前三位;
0048D699    8B85 F4FCFFFF   mov   eax, dword ptr          ; 变成了(ASCII "295");
0048D69F    E8 00ACF7FF   call    004082A4                         ; 字符转化成数字;
0048D6A4    05 F9030000   add   eax, 3F9                         ; EAX装的是我们转化后的数值(127),加上3F9;
0048D6A9    69C0 D3020000   imul    eax, eax, 2D3                  ; EAX(520)再乘于2D3;
0048D6AF    8945 F8         mov   dword ptr , eax         ; 把最后得到的数字(E7960)传递给这个地址;
0048D6B2    8D95 E4FCFFFF   lea   edx, dword ptr
0048D6B8    33C0            xor   eax, eax
以上基本就是本程序的关键算法了,往下走就都是一些读取.INI文件的操作.我就不多说了就提一点,如果你的程序出现了自校验的话,就可到C盘WINDOWS的根目录下把WINDOWS.INI删掉就好了.下面再来说说注册验证的过程.

------------------------------(第二部分)-----------------------------------------------------------
0048D977    8B45 FC         mov   eax, dword ptr
0048D97A    8B80 F8020000   mov   eax, dword ptr
0048D980    8B80 08020000   mov   eax, dword ptr
0048D986    BA 01000000   mov   edx, 1
0048D98B    E8 FCA3FAFF   call    00437D8C
0048D990    50            push    eax
0048D991    8D85 B4FCFFFF   lea   eax, dword ptr
0048D997    8B55 FC         mov   edx, dword ptr
0048D99A    81C2 58050000   add   edx, 558
0048D9A0    E8 3B69F7FF   call    004042E0                     ; 获取用户名:hanyu;
0048D9A5    8B8D B4FCFFFF   mov   ecx, dword ptr
0048D9AB    8D85 B8FCFFFF   lea   eax, dword ptr
0048D9B1    BA 10DE4800   mov   edx, 0048DE10                ; 授权使用:
0048D9B6    E8 CD69F7FF   call    00404388
0048D9BB    8B95 B8FCFFFF   mov   edx, dword ptr    ; //在这里用户名不参与注册码的计算,只作标识罢了;
0048D9C1    58            pop   eax
0048D9C2    E8 21A3FAFF   call    00437CE8
0048D9C7    8D85 ACFCFFFF   lea   eax, dword ptr
0048D9CD    8B55 FC         mov   edx, dword ptr
0048D9D0    81C2 58050000   add   edx, 558
0048D9D6    E8 0569F7FF   call    004042E0
0048D9DB    8B8D ACFCFFFF   mov   ecx, dword ptr
0048D9E1    8D85 B0FCFFFF   lea   eax, dword ptr
0048D9E7    BA 24DE4800   mov   edx, 0048DE24                ; 本软件授权于:
0048D9EC    E8 9769F7FF   call    00404388
0048D9F1    8B95 B0FCFFFF   mov   edx, dword ptr
0048D9F7    8B45 FC         mov   eax, dword ptr
0048D9FA    8B80 34030000   mov   eax, dword ptr
0048DA00    E8 BB94FCFF   call    00456EC0
0048DA05    8D85 A4FCFFFF   lea   eax, dword ptr
0048DA0B    8B55 FC         mov   edx, dword ptr
0048DA0E    81C2 58060000   add   edx, 658
0048DA14    E8 C768F7FF   call    004042E0                     ; 获取假码;
0048DA19    8B85 A4FCFFFF   mov   eax, dword ptr    ; 把假码(ASCII "123456"),传递给EAX;
0048DA1F    8D95 A8FCFFFF   lea   edx, dword ptr
0048DA25    E8 B2EBFFFF   call    0048C5DC                     ; 关键算法CALL;
0048DA2A    8B85 A8FCFFFF   mov   eax, dword ptr    ; 计算后得到假码字符串:(ASCII "2296281783")
0048DA30    50            push    eax
0048DA31    8D95 9CFCFFFF   lea   edx, dword ptr
0048DA37    8B45 F8         mov   eax, dword ptr
0048DA3A    E8 29A7F7FF   call    00408168                     ; 把第一部分算法得到的(E7960)数值转化成字符串;
0048DA3F    8B85 9CFCFFFF   mov   eax, dword ptr    ; 得到(ASCII "948576");
0048DA45    8D95 A0FCFFFF   lea   edx, dword ptr
0048DA4B    E8 8CEBFFFF   call    0048C5DC                     ; 也是关键算法CALL它和假码的运算CALL是一样的都是(0048C5DC);
0048DA50    8B95 A0FCFFFF   mov   edx, dword ptr    ; 最后得到正确注册码:(ASCII "17643513783");
0048DA56    58            pop   eax                        ; 假码运算后得到的字符串:ASCII "2296281783"
0048DA57    E8 2C6AF7FF   call    00404488                     ; 经典字符串比较CALL;
0048DA5C    74 05         je      short 0048DA63               ; 关键跳转;(可作内存补丁);
0048DA5E    E8 3DF9FFFF   call    0048D3A0
0048DA63    8D85 F8FDFFFF   lea   eax, dword ptr
好了看完注册验证机制之后,我们再来看看关键算法CALL吧!


------------------------------(第三部分)-----------------------------------------------------------
0048C5DC    55            push    ebp
0048C5DD    8BEC            mov   ebp, esp
0048C5DF    83C4 F8         add   esp, -8
0048C5E2    53            push    ebx
0048C5E3    33C9            xor   ecx, ecx
0048C5E5    894D F8         mov   dword ptr , ecx
0048C5E8    8BDA            mov   ebx, edx
0048C5EA    8945 FC         mov   dword ptr , eax
0048C5ED    8B45 FC         mov   eax, dword ptr
0048C5F0    E8 377FF7FF   call    0040452C
0048C5F5    33C0            xor   eax, eax
0048C5F7    55            push    ebp
0048C5F8    68 44C64800   push    0048C644
0048C5FD    64:FF30         push    dword ptr fs:
0048C600    64:8920         mov   dword ptr fs:, esp
0048C603    8B45 FC         mov   eax, dword ptr
0048C606    E8 99BCF7FF   call    004082A4                         ; 把字符串(ASCII "948576"),转化成数值;
0048C60B    69C0 BA000000   imul    eax, eax, 0BA                  ; 得到数值(E7960)乘于OBA;
0048C611    40            inc   eax                              ; 积(A842FC0)加1;
0048C612    8D55 F8         lea   edx, dword ptr          ; 把地址中的数值传递到EDX中;
0048C615    E8 4EBBF7FF   call    00408168                         ; 把数值转化成ASCII码;
0048C61A    8B55 F8         mov   edx, dword ptr          ; 得到字符串:(ASCII "176435137")
0048C61D    8BC3            mov   eax, ebx
0048C61F    B9 58C64800   mov   ecx, 0048C658                  ; 83
0048C624    E8 5F7DF7FF   call    00404388                         ; 连接"83"和"176435137"两段字符串;
0048C629    33C0            xor   eax, eax
0048C62B    5A            pop   edx
那个算法CALL也就只是简单的对数值做一下加,乘运算罢了.好了,当我们了解了整个注册机制以后,那么软件的作者又是如何发放注册码的了,只要我们细心看看提示就知道了.它是通过机器码来提供注册信息的,好现在我们就来看它的机器码是如何获取的,运用DELPHI获取按钮入口的方法,来到如下代码段:


------------------------------(第四部分)-----------------------------------------------------------
0048DECC    55            push    ebp
0048DECD    8BEC            mov   ebp, esp
0048DECF    33C9            xor   ecx, ecx
0048DED1    51            push    ecx
0048DED2    51            push    ecx
0048DED3    51            push    ecx
0048DED4    51            push    ecx
0048DED5    53            push    ebx
0048DED6    8BD8            mov   ebx, eax
0048DED8    33C0            xor   eax, eax
0048DEDA    55            push    ebp
0048DEDB    68 68DF4800   push    0048DF68
0048DEE0    64:FF30         push    dword ptr fs:
0048DEE3    64:8920         mov   dword ptr fs:, esp
0048DEE6    E8 3DE6FFFF   call    0048C528
0048DEEB    E8 884BF7FF   call    00402A78
0048DEF0    52            push    edx
0048DEF1    50            push    eax
0048DEF2    8D45 F4         lea   eax, dword ptr
0048DEF5    E8 5AA3F7FF   call    00408254
0048DEFA    8B45 F4         mov   eax, dword ptr
0048DEFD    E8 3A64F7FF   call    0040433C
0048DF02    48            dec   eax
0048DF03    50            push    eax
0048DF04    E8 1FE6FFFF   call    0048C528
0048DF09    E8 6A4BF7FF   call    00402A78
0048DF0E    52            push    edx
0048DF0F    50            push    eax
0048DF10    8D45 F0         lea   eax, dword ptr
0048DF13    E8 3CA3F7FF   call    00408254
0048DF18    8B45 F0         mov   eax, dword ptr
0048DF1B    8D4D F8         lea   ecx, dword ptr
0048DF1E    5A            pop   edx
0048DF1F    E8 C414FAFF   call    0042F3E8                     ; //以上的代码是不是很面熟啊!其实它和我们在开始看到的代码基本一样的都是用来获取 C盘的数据的;
0048DF24    8B45 F8         mov   eax, dword ptr          ; 也是截取了头三位(ASCII "295");
0048DF27    E8 78A3F7FF   call    004082A4                     ; 同样是把字符转化成数字;
0048DF2C    69C0 D3020000   imul    eax, eax, 2D3                  ; 数值EAX(127)乘与2D3
0048DF32    05 F9030000   add   eax, 3F9                     ; eax=00034125再加上3F9;
0048DF37    8D55 FC         lea   edx, dword ptr
0048DF3A    E8 29A2F7FF   call    00408168
0048DF3F    8B55 FC         mov   edx, dword ptr          ; 数值转换成字符了:(ASCII "214302");
0048DF42    8B83 44050000   mov   eax, dword ptr        ; //其实机器码和开始认证时的算法只是颠倒了一下循序而已,一个先加
0048DF48    E8 738FFCFF   call    00456EC0                     ; //后乘,另一个先乘后加;
0048DF4D    33C0            xor   eax, eax
0048DF4F    5A            pop   edx
0048DF50    59            pop   ecx
0048DF51    59            pop   ecx
---------------------------------------------------------------------------------------------
【经验总结】
1.我们要大概了解重启验证的程序它们的都有一个启动认证的注册部分,平时我们搞自校或是ANTI基本上都能在这里能搞定;

2.要看懂基本的汇编指令,不懂也没问题.但是人手要有一个汇编指令查询器,我个人一直以来都是用"黑夜"兄汇编查询器.如果你连指令都看不懂,那么程序对数值做了什么操作你又怎么能知道呢!

3.写算法注册机:放三个EXIT控件,以及一个BUTTON控件把源代码复制进去便可;

---------------------------------------------------------------------------------------------
【破解感悟】
本人认为这个算法机制相当的不切合实际,先不说它的注册码计算的难易程度.就取C盘数据而言,如果人家使用的是GHOST版本的XP的话,那么就只有一个超级用户.此时C盘的All Users文件里的数据就会不时的变动.我叫人帮我调试注册机时,就发生过这种情况机器码不停的发生改变.也不懂作者是如何解决这个问题的,难道连他本人都是用内存补丁么?再来就是注册码验证部分,做的实在是有点画蛇添足了.他在0048DA3F处把注册码呈现出来了,然后又让此数值给运算了一遍.我真的搞不懂他的用意何在,要是你说要屏蔽掉人家的内存注册机的话,那么你就不要在0048DA3F处把注册码给字符化,这样就可避免人家编写内存的可能性.你现在把它字符化了然后又再数值化,都在做"无用工"耗内存.最后提醒一下大家,我们设计注册机制时千万不要使用一些不稳定的数值,如本题的C盘数据你可用电脑用户名,网卡号等等不易改变的数值皆可!

【版权声明】: 转载请注明作者并保持文章的完整, 谢谢! 软件久远,如有雷同,敬请理解.

[ 本帖最后由 as3852711 于 2009-5-6 20:00 编辑 ]

as3852711 发表于 2009-5-6 19:57:44

Delphi 注册机源码:

--------------------------------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
code:Double;//定义注册码数值的变量;
i:integer;    //定义记数变量;
begin
val(edit1.Text,code,i);//把字符格式化成数字函数;
if i = 0 then   //如果I等于0说明是一个整型数值;
begin
   if edit2.text <> '' then    //判断用户为不为空;
   begin
    code := (code - $3F9) / $2D3;   //把机器码进行运算得出C盘数据;
    edit3.Text :=floattostr((code + $3F9) * $2D3 );    //再用得到的数据运算,最后转化成字符串;
   end
   else
   showmessage('Please input your Name !');
end
else
showmessage('Please input Number to Machine !');
end;


[ 本帖最后由 as3852711 于 2009-5-6 20:01 编辑 ]

cjteam 发表于 2010-8-6 11:40:07

谢谢,/:018

hahuhu190 发表于 2010-8-6 12:02:19

09的帖子/ch,支持一个
页: [1]
查看完整版本: XX电话通 算法分析+Delphi注册机