飘云 发表于 2006-8-31 22:26:02

AlarmMaster V4.13 算法分析(疲劳指数:★★★^_^,想消磨时间的朋友进)

【破文标题】AlarmMaster V4.13 算法分析(疲劳指数:★★★^_^,想消磨时间的朋友进)
【破文作者】飘云
【作者邮箱】[email protected]
【作者主页】WwW.ChiNaPYG.CoM
【破解工具】Peid0.94,OllyDbg,VC++
【破解平台】Win9x/NT/2000/XP
【软件名称】AlarmMaster V4.13
【软件大小】644kb
【原版下载】http://www.brigsoft.com/alarm-clock/download/AlarmMasterInst.exe
【保护方式】Nag+Name+Code
【软件简介】    这是一个简单的闹钟、时程表、计时器、PC 对时器程序。只需按一下鼠标就可以设定闹铃的时间,同时也可以在日程表上设定闹铃,你可以设在任一个时间,并可以对每一个闹铃设定文字讯息。闹铃几乎没有限制,而且每组都可以设定个自的声音。这程序还附有对时功能,再你每次上线时它就会自动连接原子钟帮你对时。
【破解声明】我是一只菜菜鸟,偶得一点心得,愿与大家分享 !^_^
------------------------------------------------------------------------
【破解过程】先运行程序,打开注册窗口,发现有4组注册码框~~

OD载入程序后,搜索字符串,没有找到~~~

欲下断 bp GetDlgItem

Nag窗口出来之后,选择 “Enter Registration Code” 马上断住了~~~

0012F8D0   1000210C/CALL 到 GetDlgItem 来自 BSSuppor.1000210A
0012F8D4   002603DE|hWnd = 002603DE ('Alarm Master',class='#32770')
0012F8D8   000003E9\ControlID = 3E9 (1001.)

我晕,原来在DLL文件中效验注册码,难怪刚刚找不到有用信息咯~~

ALT+F9返回

1000210C   push    3EA//返回到这里~~
10002111   push    ebx
10002112   mov   , eax
10002115   call    edi
10002117   push    3EB

用插件搜索字符串吧:

找到个有用的~~
%d%d%d%d(c++的格式字符串)这不正式我们四个输入框的格式字符串吗?

双击后来到:

1000285E   push    ebp                        //代码开始处,F2下断
1000285F   mov   ebp, esp
10002861   sub   esp, 118
10002867   push    ebx
.
.
.
1000292F   dword ptr
10002932   dword ptr
10002935   dword ptr
10002938   1000D2D8                  ; %d%d%d%d//★来到这里,向上看!★


将以前的断点取消,在 1000285E 下断,输入注册信息:
piaoyun
1111-2222-3333-4444
立刻中断~:
1000285E   push    ebp
1000285F   mov   ebp, esp
10002861   sub   esp, 118
10002867   push    ebx
10002868   mov   ebx,
1000286B   push    esi
1000286C   push    edi
1000286D   xor   edi, edi
1000286F   mov   , ecx
10002872   xor   esi, esi
10002874   cmp   edi,                ; 变量和用户名长度比较(意即用户名算法部分的循环开关)
10002877   jge   short 100028A8
10002879   mov   dword ptr , 1
10002880   push    edi
10002881   mov   ecx, ebx
10002883   call    10002847
10002888   cmp   byte ptr , 20            ; 逐个字符与空格比较
1000288B   jnz   short 10002897
1000288D   inc   edi
1000288E   inc   dword ptr
10002891   cmp   dword ptr , 64
10002895   jl      short 10002880
10002897   push    edi
10002898   mov   ecx, ebx
1000289A   call    10002847
1000289F   mov   al,                      ; 逐位当前指针处字符ASCII到al
100028A1   mov   , al            ; 转存
100028A5   inc   edi                           ; 指向用户名下一位
100028A6   jmp   short 100028AD
100028A8   mov   byte ptr , 40   ; 追加“@”字符   40=“@”   追加的个数为 16-用户名长度
100028AD   inc   esi                           ; 指向注册码下一位
100028AE   cmp   esi, 10                     ; 是否取完16(10进制)位?
100028B1   jl      short 10002874                ; 循环    变换后的用户名("piaoyun@@@@@@@@@")
100028B3   mov   byte ptr , 0
100028B8   xor   esi, esi
100028BA   xor   ebx, ebx
100028BC   lea   edi,
100028C0   mov   dword ptr , 4
100028C7   mov   ecx,
100028CA   call    10002827                      ; 算法CALL 跟进!   EAX中返回的是关键值
100028CF   movsx   ecx, byte ptr          ; 取变换后的用户名ASCII送ecx(共4轮循环 第一轮:1、5、9、13位,第二轮:2、6、
10、14位,第三轮:3、7、11、15位,第四轮:4、8、12、16位)
100028D2   xor   edx, edx                      ; edx 清零
100028D4   lea   eax,             ; eax=eax+ecx-0xa
100028D8   push    0A                            ; 0x0A(10)
100028DA   pop   ecx
100028DB   div   ecx                           ; eax%0xA (余数放edx)
100028DD   add   edi, 4                        ; 指向变换后用户名的随后第4位
100028E0   add   dl, 30                        ; 余数+0x30
100028E3   mov   , dl             ; 保存结果
100028EA   inc   esi
100028EB   dec   dword ptr
100028EE   jnz   short 100028C7                ; 小循环
100028F0   mov   byte ptr , 20    ; 每4位(即每1轮大循环)用空格隔开
100028F8   inc   esi
100028F9   inc   ebx
100028FA   cmp   ebx, 4                        ; 大循环共4轮
100028FD   jl      short 100028BC
100028FF   mov   byte ptr , 0
10002907   xor   esi, esi
10002909   lea   eax,
1000290F   mov   bl,
10002911   lea   ecx,
10002918   movsx   edx, byte ptr
1000291B   mov   , bl
1000291D   inc   esi
1000291E   mov   , dl
10002920   dec   eax
10002921   cmp   esi, 9
10002924   jl      short 1000290F                ; 此循环为:倒置字符串
10002926   push    dword ptr
10002929   lea   eax,
1000292F   push    dword ptr
10002932   push    dword ptr
10002935   push    dword ptr
10002938   push    1000D2D8                      ; %d%d%d%d
1000293D   push    eax
1000293E   call    10004CC7
10002943   add   esp, 18
10002946   pop   edi
10002947   pop   esi
10002948   pop   ebx
10002949   leave
1000294A   retn    14                            ; 返回到 1000297D   

*****************************call    10002827*****************************
10002827   mov   eax,                   ; 初始值为0
10002829   imul    eax, eax, 343FD               ; eax=eax×0x343FD
1000282F   add   eax, 269EC3                   ; eax=eax+0x269EC3
10002834   mov   , eax                  ; 结果保存到
10002836   sar   eax, 10                     ; EAX右移0x10位
10002839   and   eax, 7FFF                     ; EAX and 0x7FFF
1000283E   cdq                                 ; edx符号扩展
1000283F   push    0A                            ; 0xA入栈
10002841   pop   ecx
10002842   idiv    ecx                           ; eax%ecx   余数放edx
10002844   mov   eax, edx
10002846   retn
***********************************************************************

下面开始验证注册码:
1000297D   mov   eax,              ; 假码第1部分送eax
10002980   cmp   eax,              ; 和真码第1部分比较
10002983   mov   ebx,             ; 假码第4部分送ebx
10002986   mov   edi,             ; 假码第3部分送edi
10002989   mov   edx,             ; 假码第2部分送edx
1000298C   jnz   short 1000299D         ; 不相等就跳
1000298E   cmp   edx,              ; 和真码第2部分比较
10002991   jnz   short 1000299D
10002993   cmp   edi,              ; 和真码第3部分比较
10002996   jnz   short 1000299D
10002998   cmp   ebx,             ; 和真码第4部分比较
1000299B   je      short 100029B7         ; 上面都通过就跳到 成功~~
1000299D   mov   ecx, 4D2               ; ecx=0x4D2(1234)
100029A2   cmp   eax, ecx               ; 假码第1部分=1234?
100029A4   jnz   short 100029BC
100029A6   mov   eax, 162E                ; eax=0x162E(5678)
100029AB   cmp   edx, eax               ; 假码第2部分=5678?
100029AD   jnz   short 100029BC
100029AF   cmp   edi, ecx               ; 假码第3部分=1234?
100029B1   jnz   short 100029BC
100029B3   cmp   ebx, eax               ; 假码第4部分=5678?
100029B5   jnz   short 100029BC         ; 满足上面条件就不跳,也就注册成功了~~ 因此,通用注册码为 1234-5678-1234-5678
100029B7   xor   eax, eax
100029B9   inc   eax
100029BA   jmp   short 100029BE
100029BC   xor   eax, eax
100029BE   pop   edi
100029BF   pop   ebx
100029C0   leave
100029C1   retn    14
------------------------------------------------------------------------
【破解总结】
1.对用户名进行变换,规则如下:
变换后的用户名=用户名+(16-用户名长度)个字符"@"   piaoyun==>>piaoyun@@@@@@@@@
2.call    10002827中的内容,请自行查看,返回值到eax
3.分4轮大循环取变换后的用户名待下一步运算(第一轮:1、5、9、13位,第二轮:2、6、10、14位,第三轮:3、7、11、15位,第四轮:4、8、12、16位),取得的ASCII均放到ecx中
4.eax=eax+ecx-0xA (eax的初始值由第2步决定)
5.第4步的结果除以0xA的余数+0x30保存起来
6.每4位(即每1轮大循环)用空格隔开 (用空格隔开在还原注册码时不是必须的!只是代表4组而以)
7.倒置第6步的结果即为注册码

通用注册码:1234-5678-1234-5678   ~~ 哈哈,作者在玩你!

注册信息保存在:HKEY_LOCAL_MACHINE\SOFTWARE\BrigSoft\AlarmMaster\Options   删除即可重玩~~------------------------------------------------------------------------
【算法注册机】
//说明:
//注册机是按照算法流程写下来的,没做任何优化处理,仅仅为了方便初学者对照反汇编代码参考

#include "iostream.h"
#include "string.h"
#include "windows.h"
#include "stdio.h"
void main()
{
        char Name={0},Code={0},Sn={0};
        long Sum0=0,Sum=0;
        cout<<"\t\t------------------------------------\n";
        cout<<"\t\t|------------------------------|\n";
        cout<<"\t\t||KeyGen For AlarmMaster V4.13||\n";
        cout<<"\t\t||    Code By PiaoYun    ||\n";
        cout<<"\t\t||      WwW.ChiNaPYG.CoM      ||\n";
        cout<<"\t\t||E-mail:[email protected]||\n";
        cout<<"\t\t||   WinXP SP2&VC++ 6.0   ||\n";
        cout<<"\t\t|------------------------------|\n";
        cout<<"\t\t------------------------------------\n";
        cout<<"Please Input Your RegName:\n";
        cin>>Name;
        int i,j,k=0;
        int LenName;
        byte n;//支持中文
        LenName=strlen(Name);
        //对用户名进行变换
        if(LenName<16)
                for(;LenName<16;LenName++)
                        Name='@';
                for(i=0;i<4;i++) //大循环
                {
                        for(j=i;j<16;j+=4,k++)//小循环
                                //call    10002827里面的算法
                        {
                                Sum0*=0x343FD;
                                Sum0+=0x269EC3;
                                Sum=Sum0;
                                __asm
                                {
                                        mov eax,Sum
                                        sar eax,010H
                                        and eax,07FFFH
                                        cdq
                                        mov ecx,0AH
                                        idiv ecx
                                        mov Sum,edx
                                }
                                        n=Name;
                                        Sum=Sum+n-0xA;
                                        Sum=Sum%0xA+0x30;
                                        Code=Sum;
                                       
                        }
                }
                                        for(i=0;i<16;i++)//倒置字符串作为注册码
                                        {
                                                Sn=Code;
                                        }
                                        cout<<"Your RegCode:\n"<<Sn<<endl;
                                        system("pause");
}
------------------------------------------------------------------------
【版权声明】本文纯属技术交流,转载请注明作者信息并保持文章的完整,谢谢!

wzwgp 发表于 2006-8-31 23:13:04

坐在沙发上好好学习!

bfqyygy 发表于 2006-9-1 15:10:34

老大强呀。学习!

WAKU 发表于 2006-9-1 15:28:39

学习了

eopenfang 发表于 2006-9-1 16:30:57

论坛再次开通

好像以前没见过的人好多多哦。都是成员啊,版主之类了。:L一个!

Mysoft 发表于 2006-9-1 16:46:33

坐下听讲。。。。。。。

haiyun 发表于 2006-9-2 00:16:46

看不懂~~呵呵,支持老大!

网游难民 发表于 2006-9-2 09:12:39

咱来慢慢研究啊~~/:D

黑夜彩虹 发表于 2006-9-2 09:33:30

学习了~~

wxh9833 发表于 2006-9-2 09:51:56

页: [1] 2
查看完整版本: AlarmMaster V4.13 算法分析(疲劳指数:★★★^_^,想消磨时间的朋友进)