首页
社区
课程
招聘
[原创]编译器 C-Free V3.5.2 注册算法分析(重启验证)
发表于: 2005-1-29 11:35 16282

[原创]编译器 C-Free V3.5.2 注册算法分析(重启验证)

2005-1-29 11:35
16282

编译器 C-Free V3.5.2 注册算法分析(重启验证)
       
        今天在DFCG论坛上闲逛时无意中看到一个国产C/C++编译器,C-Free V3.5.2,随手下载只是想看看注

册算法,没有使用,不知道功能如何。

[Cracker]    : prince

[时间]             : 2005.01.28

[声明]             : 只做技术交流,不做商业用途,如果你手头宽裕并喜欢这个软件的话请支持正版软件。

[E-mail]     : Cracker_prince@163.com

[软件信息]

[软件说明]   :

        C-Free是一款基于Windows的C/C++集成化开发软件(IDE)。利用本软件,使用者可以轻松地编辑、编

译、连接、运行、调试C/C++程序。特别地,这款软件对于C/C++的学习者非常容易使用,是迅速提高C/C++水平

的好帮手。当然,C/C++高手也会在其中找到许多惊喜的功能。
        C-Free包含下列主要特征:

                支持MinGW编译器和C/C++解释器Ch
       
                集成化的调试环境

                工程管理

                可定制的语法加亮编辑器

                智能输入(大大地提高代码输入效率)

                函数列表

                集成化的C/C++库函数帮助

                快速创建控制台、窗口和DLL应用

                借助工程模板创建自己想要的工程类型

                完善的查找替换功能

                可定制的代码模板

                支持Window图形界面应用的开发

                对话框资源编辑器

[保护方式]   : 机器码 + 序列号

[限制方式]   : 次数限制 (10 次试用 )

[外壳保护]   : ASPack 2.12

[编译器/语言]: Borland C++ 1999 / C++

[下载地址]   :http://www.programarts.com/cfree_ch/index.htm

        ASPack 2.12 脱壳很简单,ASPackDie也可以轻松对付。无自校验,脱壳后可直接运行。注册情况:机

器码给出,输入用户名prince和序列号8764321,确定,提示重启验证。
        说到重启验证,最简单最直接的就想到注册表,确认一下,打开注册表搜索用户名prince,果然找到

在\HKEY_LOCAL_MACHINE\SOFTWARE\C-Free\3.5下,同样列在其中的还有我们输入的假码87654321和我机器上的

机器码(MachineCode)2781318776。这下我们就可以确定了软件确实是通过注册表来进行重启验证的。目标如此

明确,载入脱壳后的程序,下断点RegQueryValueA,恩?没有,再下RegQueryValueExA,呵呵,可以了。F9运

行,马上被断下,看堆栈,ValueName = "layout text",不是我们想要的,继续F9,注意断点不能取消,因为

后面的对注册表的读取还是要靠这个函数,再次断下,还不是,再运行...,大约81次,堆栈中显示ValueName

= "MachineCode",这就是要读取机器码了,注意。再次F9,断在读取RegistryCode也就是假码的地方,呵呵,

敏感。再接下来是读取UserName,即用户名。到这里,计算注册码的准备工作就做完了,可是在那里计算的呢

?作者在软件启动的时候将所有的配置信息连同机器码,用户名和注册码一起读出,而且也没有读出后立即计

算注册码继续比较,这就给我们定位注册码计算造成了困难。这个时候我们该怎么办?两个办法,一个就是下

面都进行单步跟踪,直到找到关键函数为止,毕竟软件在启动前肯定会计算注册码的;另外一个办法就是在内

存中搜索假码然后下内存断点,这个方法倒是即快又方便,但是要掌握时机,具体什么时候搜内存要看代码的

动作。我通常都是先搜内存,不行的话只好一步一步的单跟了,做Cracker要有耐心。当你在堆栈中看到

ValueName = "EditorTabWidth"的时候,小心,呵呵,我们到了藏有宝藏的秘密入口了。

----------------------------------------------------------------------------------------
00419654  |.>MOV WORD PTR DS:[EBX+10],4B8
0041965A  |.>MOV EDX,unpacked.005DAA4C        ;  ASCII "EditorTabWidth"
0041965F  |.>LEA EAX,DWORD PTR SS:[EBP-620]
00419665  |.>CALL unpacked.0058D308
0041966A  |.>INC DWORD PTR DS:[EBX+1C]
0041966D  |.>MOV EDX,DWORD PTR DS:[EAX]
0041966F  |.>MOV EAX,ESI
00419671  |.>CALL unpacked.004E936C
00419676  |.>MOV ECX,DWORD PTR DS:[EDI]
00419678  |.>MOV EDX,2
0041967D  |.>MOV DWORD PTR DS:[ECX+A0C],EAX
00419683  |.>LEA EAX,DWORD PTR SS:[EBP-620]
00419689  |.>DEC DWORD PTR DS:[EBX+1C]
0041968C  |.>CALL unpacked.0058D520
00419691  |.>MOV ECX,DWORD PTR DS:[EDI]
00419693  |.>MOV BYTE PTR DS:[ECX+8F4],0
0041969A  |.>MOV EAX,DWORD PTR DS:[EDI]
0041969C  |.>INC DWORD PTR DS:[EAX+8F0]
004196A2  |.>CALL unpacked.00462F18           ;  取机器码送EAX
004196A7  |.>MOV DWORD PTR SS:[EBP-764],EAX
004196AD  |.>MOV WORD PTR DS:[EBX+10],98
004196B3  |.>MOV EDX,DWORD PTR DS:[EDI]
004196B5  |.>MOV ECX,DWORD PTR DS:[EDX+8E4]
004196BB  |.>CMP ECX,DWORD PTR SS:[EBP-764]
004196C1  |.>JNZ unpacked.00419772
004196C7  |.>LEA EAX,DWORD PTR SS:[EBP-884]
004196CD  |.>PUSH EAX                         ; /Arg2
004196CE  |.>MOV EDX,DWORD PTR SS:[EBP-764]   ; |[EBP-764]==机器码
004196D4  |.>PUSH EDX                         ; |Arg1
004196D5  |.>CALL unpacked.00462F70           ; \关键CALL,跟进
004196DA  |.>MOV WORD PTR DS:[EBX+10],4C4     ;  上面的这个CALL计算真码,存放在EAX中(哎!又是明文

)
004196E0  |.>ADD ESP,8
004196E3  |.>LEA EDX,DWORD PTR SS:[EBP-884]   ;  真码地址送入EDX
004196E9  |.>LEA EAX,DWORD PTR SS:[EBP-624]
004196EF  |.>CALL unpacked.0058D308
004196F4  |.>INC DWORD PTR DS:[EBX+1C]
004196F7  |.>MOV EDX,DWORD PTR DS:[EAX]
004196F9  |.>MOV EAX,DWORD PTR DS:[EDI]
004196FB  |.>MOV EAX,DWORD PTR DS:[EAX+8E8]   ;  假码送入EAX,呵呵,准备比较了哦
00419701  |.>CALL unpacked.004ECED4           ;  比较函数,嘿嘿。
00419706  |.>TEST EAX,EAX
00419708  |.>LEA EAX,DWORD PTR SS:[EBP-624]

----------------------------------------------------------------------------------------

我们要找算法的计算过程,所以004196D5 处跟进:

----------------------------------------------------------------------------------------
00462F70  /$>PUSH EBP
00462F71  |.>MOV EBP,ESP
00462F73  |.>ADD ESP,-0C
00462F76  |.>XOR EDX,EDX
00462F78  |.>PUSH EBX
00462F79  |.>PUSH ESI
00462F7A  |.>PUSH EDI
00462F7B  |.>MOV EBX,25                       ;  EBX=0x25
00462F80  |.>MOV ECX,DWORD PTR SS:[EBP+8]     ;  [EBP+8]==机器码
00462F83  |.>XOR ECX,90909090                 ;  机器码异或90909090,ECX==35571EE8
00462F89  |.>MOV EAX,ECX
00462F8B  |.>DIV EBX                          ;  上面异或的结果除以25
00462F8D  |.>MOV EAX,EDX                      ;  余数送EAX
00462F8F  |.>CMP EAX,11                       ;  余数同0x11比较
00462F92  |.>JGE SHORT unpacked.00462F97      ;  大于等于就直接压栈准备函数调用
00462F94  |.>ADD EAX,11                       ;  否则余数+0x11,然后再入栈
00462F97  |>>PUSH EAX                         ; /Arg3 余数入栈
00462F98  |.>LEA EDX,DWORD PTR SS:[EBP-C]     ; |
00462F9B  |.>PUSH EDX                         ; |Arg2
00462F9C  |.>PUSH ECX                         ; |Arg1 上面异或结果入栈
00462F9D  |.>CALL unpacked.005861F0           ; \跟进
00462FA2  |.>MOV ECX,DWORD PTR SS:[EBP+C]
00462FA5  |.>ADD ESP,0C
00462FA8  |.>MOV ESI,ECX
00462FAA  |.>XOR EAX,EAX
00462FAC  |.>LEA EDI,DWORD PTR SS:[EBP-C]

----------------------------------------------------------------------------------------

00462F9D 处继续跟进:

----------------------------------------------------------------------------------------
005861F0  /$>PUSH EBP
005861F1  |.>MOV EBP,ESP
005861F3  |.>MOV EAX,DWORD PTR SS:[EBP+10]
005861F6  |.>MOV EDX,DWORD PTR SS:[EBP+8]
005861F9  |.>CMP EAX,0A                       ;  余数同0A比较
005861FC  |.>PUSH 61
005861FE  |.>SETE CL                          ;  条件为假,所以CL清零
00586201  |.>AND ECX,1
00586204  |.>CMP EAX,0A                       ;  仍然同0A比较
00586207  |.>PUSH ECX
00586208  |.>PUSH EAX
00586209  |.>MOV ECX,DWORD PTR SS:[EBP+C]
0058620C  |.>PUSH ECX
0058620D  |.>JNZ SHORT unpacked.00586213
0058620F  |.>MOV EAX,EDX
00586211  |.>JMP SHORT unpacked.00586215
00586213  |>>MOV EAX,EDX
00586215  |>>PUSH EAX                         ; |Arg1
00586216  |.>CALL unpacked.00586160           ; \跟进
0058621B  |.>ADD ESP,14
0058621E  |.>POP EBP
0058621F  \.>RETN

----------------------------------------------------------------------------------------

没有结果,00586216处继续跟进:

----------------------------------------------------------------------------------------
00586160  /$>PUSH EBP
00586161  |.>MOV EBP,ESP
00586163  |.>ADD ESP,-24
00586166  |.>PUSH EBX
00586167  |.>PUSH ESI
00586168  |.>PUSH EDI
00586169  |.>MOV EDI,DWORD PTR SS:[EBP+10]    ;  [EBP+10]为前面压栈的余数
0058616C  |.>MOV ESI,DWORD PTR SS:[EBP+8]     ;  [EBP+8]为机器码异或90909090的结果
0058616F  |.>MOV EBX,DWORD PTR SS:[EBP+C]
00586172  |.>CMP EDI,2                        ;  余数同0x2比较
00586175  |.>JL SHORT unpacked.005861C4       ;  小于跳
00586177  |.>CMP EDI,24                       ;  同0x24比较
0058617A  |.>JG SHORT unpacked.005861C4       ;  大于则跳
0058617C  |.>TEST ESI,ESI
0058617E  |.>JGE SHORT unpacked.0058618C
00586180  |.>CMP BYTE PTR SS:[EBP+14],0
00586184  |.>JE SHORT unpacked.0058618C
00586186  |.>MOV BYTE PTR DS:[EBX],2D
00586189  |.>INC EBX
0058618A  |.>NEG ESI
0058618C  |>>LEA ECX,DWORD PTR SS:[EBP-24]    ;  下面为关键循环
0058618F  |>>/MOV EAX,ESI                     ;  ESI==机器码异或结果
00586191  |.>|XOR EDX,EDX                     ;  EDX清零
00586193  |.>|DIV EDI                         ;  将上面异或结果除以压栈的余数
00586195  |.>|MOV BYTE PTR DS:[ECX],DL        ;  上面计算的余数的一个字节写入内存
00586197  |.>|INC ECX
00586198  |.>|MOV EAX,ESI
0058619A  |.>|XOR EDX,EDX
0058619C  |.>|DIV EDI
0058619E  |.>|MOV ESI,EAX                     ;  又做了一次相同的计算,商送入ESI
005861A0  |.>|TEST EAX,EAX                    ;  直到EAX==0为止
005861A2  |.>\JNZ SHORT unpacked.0058618F     ;  不为0则继续循环
005861A4  |.>JMP SHORT unpacked.005861BD
005861A6  |>>/DEC ECX
005861A7  |.>|MOV AL,BYTE PTR DS:[ECX]        ;  内存[ECX]的值送入AL
005861A9  |.>|CMP AL,0A                       ;  同0A比较
005861AB  |.>|JGE SHORT unpacked.005861B5     ;  大于等于跳到下面进行另外的计算
005861AD  |.>|ADD EAX,30                      ;  该值加上0x30
005861B0  |.>|MOV BYTE PTR DS:[EBX],AL        ;  这个值就是注册码的第i个值,写入内存保存起来
005861B2  |.>|INC EBX                         ;  继续下一步
005861B3  |.>|JMP SHORT unpacked.005861BD
005861B5  |>>|ADD AL,BYTE PTR SS:[EBP+18]     ;  上面如果大于0A,则加上[EBP+18]==61,
005861B8  |.>|ADD AL,0F6                      ;  再加上0F6
005861BA  |.>|MOV BYTE PTR DS:[EBX],AL        ;  作为注册码的第i个值写入内存
005861BC  |.>|INC EBX
005861BD  |>> LEA EDX,DWORD PTR SS:[EBP-24]   ;  取地址[EBP-24]
005861C0  |.>|CMP ECX,EDX                     ;  比较是否结束循环
005861C2  |.>\JNZ SHORT unpacked.005861A6     ;  没有结束则继续
005861C4  |>>MOV BYTE PTR DS:[EBX],0
005861C7  |.>MOV EAX,DWORD PTR SS:[EBP+C]
005861CA  |.>POP EDI
005861CB  |.>POP ESI
005861CC  |.>POP EBX
005861CD  |.>MOV ESP,EBP
005861CF  |.>POP EBP
005861D0  \.>RETN

----------------------------------------------------------------------------------------

呵呵,过程清晰明了吧?第一次循环:机器码异或0x90909090的结果除以前面求得的压栈的余数,然后这个过

程的余数写入内存保留,商作为下一次循环的变量继续循环。第二次循环:将第一次循环中写入内存的值逆序

读取出来,同0xA比较,小于就直接加上0x30,作为注册码的第i个字符写入内存;大于等于则加上61,再加

0xF6,取低字节作为注册码的第i个字符写入内存。用户名没有参与计算。也不知道我说明白了没有,还是看程

序来得直接,C源码的注册机:

-----------------------------------------------------------------------------------------

#include "stdafx.h"
#include "stdlib.h"
#include "stdio.h"

int main(int argc, char* argv[])
{
        char chKey[128] = {0};
        unsigned int unXORCode, unRemainder, unQuotient, unTmp, unMachineCode;
        printf("Please Key in the Machine Code:\n");
        scanf("%d", &unMachineCode);

        unXORCode   = unMachineCode ^ 0x90909090;
        unRemainder = unXORCode % 0x25;
        unQuotient  = unXORCode;
        if (unRemainder < 0x11)
        {
                unRemainder += 0x11;
        }

        int i;
        i = 0;
        while (unQuotient != 0)
        {
                unTmp          = unQuotient % unRemainder;
                unQuotient /= unRemainder;
                if (unTmp >= 0xa)
                {
                        unTmp = unTmp + 0x61 + 0xf6;
                        unTmp &= 0x0ff;
                        chKey[i] = unTmp;
                }
                else
                {
                        chKey[i] = unTmp + 0x30;
                }
                i++;
        }
        printf("Key is: \n");
        while (i >= 0)
        {
                printf("%c", chKey[i]);
                i--;
        }
        printf("\n");

        return 0;
}

-----------------------------------------------------------------------------------------
文章赶的比较紧,有失误的地方请来信告知。

        菜鸟写菜文,请高手指教。

                                                        prince 2005.01.28


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (21)
雪    币: 117
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不错。。
很详细,呵呵。。。
可以受精了。。
2005-1-29 11:41
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
3
呵呵,我在流行时代也发了贴,继续支持我啊,无赖版主。
2005-1-29 11:49
0
雪    币: 519
活跃值: (1223)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
4
崇拜能写编译器的人,知识和精力
2005-1-29 11:56
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
5
我也崇拜,希望作者下个版本加强保护措施。
2005-1-29 12:12
0
雪    币: 212
活跃值: (70)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
被抢先了~~~~我玩的是3.0的版本……
2005-1-29 14:26
0
雪    币: 211
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
思路,结构和分析都很清晰,
这才算实实在在的精华贴嘛。
2005-1-29 14:28
0
雪    币: 239
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这个注册机的C代码在C-FREE中不能编译成功,请楼主再测试一下。
2005-1-29 14:57
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
好人啊  我等了好久啊
2005-1-29 15:24
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
10
最初由 dssz 发布
这个注册机的C代码在C-FREE中不能编译成功,请楼主再测试一下。


哦,忘了说了,我是在VC++6.0下写的,WIN2000,SP3和XP SP2下都测试通过,这个C-Free我没用过,不知道具体情况。你在VC下新建一个控制台程序,然后把代码全部考到你新建的程序中运行。如果还有问题,可以写信给我。
2005-1-29 20:13
0
雪    币: 97697
活跃值: (200824)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
11
原创我支持...
2005-1-29 21:47
0
雪    币: 239
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最初由 prince 发布


哦,忘了说了,我是在VC++6.0下写的,WIN2000,SP3和XP SP2下都测试通过,这个C-Free我没用过,不知道具体情况。你在VC下新建一个控制台程序,然后把代码全部考到你新建的程序中运行。如果还有问题,可以写信给我。


C-FREE中不成功,主要是找不到
#include "stdafx.h"
#include "stdlib.h"

我去掉这两行后就能编译了。

请问这两行头文件我看不到有什么作用,请楼主指点一下。
2005-1-29 22:24
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
13
最初由 dssz 发布


C-FREE中不成功,主要是找不到
#include "stdafx.h"
#include "stdlib.h"
........


stdafx.h头文件是用来引入那些标准的系统包含的文件,或者是工程指定引入的那些被经常用到而且经常改变的文件。比如在stdafx.h文件中include这样一些头文件:

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#include <afxcmn.h>         // MFC common controls  
#include <objbase.h>        // Common Object Model  
#include <strmif.h>         // Quartz #include <control.h>
#include <evcode.h>
#include <uuids.h>

#include <stdlib.h>是引用标准函数库,这样才能使用该函数库中的函数。就好象要使用printf()函数就要#include <stdio.h>一样。

stdlib.h这里我并没有用到,可以去掉,而stdafx.h头文件正如上面解释的,是VC编译器预编译必须用到的文件,如果去掉会发生错误,编译不通过,提示查找预编译(precompiled)指引(directive)文件失败。C-Free显然采用的编译方式同VC不一样,所以这个文件在C-Free下也不需要。

以上是我的个人理解,如有失误请楼下指正。
2005-1-29 23:00
0
雪    币: 239
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
最初由 prince 发布


stdafx.h头文件是用来引入那些标准的系统包含的文件,或者是工程指定引入的那些被经常用到而且经常改变的文件。比如在stdafx.h文件中include这样一些头文件:

#include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions
........


#include "stdlib.h"
这个头文件好象不一定需要的,我去掉以后在VC中一样OK
2005-1-29 23:06
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
15
对,我没有用到里面的函数,所以可以去掉。
2005-1-29 23:09
0
雪    币: 300
活跃值: (521)
能力值: ( LV9,RANK:410 )
在线值:
发帖
回帖
粉丝
16
写的好,对我帮助很大!谢谢楼主的无私奉献精神!
2005-1-29 23:54
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
请问楼主是通过F8单步跟踪还是通过搜索内存到达这里的:00419654  |.>MOV WORD PTR DS:[EBX+10],4B8
0041965A  |.>MOV EDX,unpacked.005DAA4C        ;  ASCII "EditorTabWidth"
0041965F  |.>LEA EAX,DWORD PTR SS:[EBP-620] ?
另外,EditorTabWidth 是什么东东?为什么在堆栈中看到它就到了关键的地方?盼指教,谢谢!
2005-1-30 00:39
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
18
最初由 ljy3282393 发布
请问楼主是通过F8单步跟踪还是通过搜索内存到达这里的:00419654 |.>MOV WORD PTR DS:[EBX+10],4B8
0041965A |.>MOV EDX,unpacked.005DAA4C ; ASCII "EditorTabWidth"
0041965F |.>LEA EAX,DWORD PTR SS:[EBP-620] ?
另外,EditorTabWidth 是什么东东?为什么在堆栈中看到它就到了关键的地方?盼指教,谢谢!


呵呵,真是不好意思,这里我写得确实比较模糊。原因是这样,我在分析他算法的时候是在读取完MachineCode等关键值后单步跟了好多步,具体多少我忘了,然后看到注册表中还有好多的键值程序还没有读完,就为了方便,直接打开内存镜像搜索我输入的假码,然后下内存访问中断,直接就找到了。可是在写这篇文章的时候忘了在什么地方开始下内存断点了   ,就用了笨方法,直接单步跟踪来到了计算注册码的地方。呵呵,菜啊!

那个EditorTabWidth是C-Free要用到的一个值,看名字应该是在编辑代码的时候按Tab键跳跃的列数。问为什么看到它就知道来到了关键地方?呵呵,跟踪喽,跟到关键地方后,记下地址或在上面下个断点,再重新调试分析,因为读完EditorTabWidth这个值后就快到计算注册码的地方了,所以这里我就拿它做标志讲解了。
2005-1-30 09:02
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
19
注意:错误更正。

有个小错误,原程序有一处的条件是大于等于,我马虎了,少写个等于,现在更正。

if (unTmp >= 0xa),就是这里,我原来写的是 if (unTmp > 0xa),文章中已经更正。

抱歉!
2005-1-30 09:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
我碰巧也研究了一下。
写了个注册机自己用,gcc,vc6.0下编译通过:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *strrev(char *s, char *t); /* 倒序输出*/

int main(int argc, char *argv[])
{

    unsigned long Machinecode, x, y;
    char RegistryCode[20], MiddleCode[20];
    int i;

    /*Machinecode = 3505625557; */
    printf("Please input your Machinecode:");
    scanf("%u", &Machinecode);
    Machinecode ^= 0x90909090;
    x = Machinecode / 0x25;
    y = Machinecode % 0x25;
    y += (y<0x11)?0x11:0;

    i = 1;
    while (Machinecode)
    {
        unsigned long code;
        code = Machinecode % y;
        Machinecode = Machinecode / y;
        
        code += (code<=0xA)?0x30:0x157;

        printf("%d:x is %X, y is %c \n", i, Machinecode, code);
        MiddleCode[i-1] = code;
        i++;
    }
   
    MiddleCode[i-1] = '\0';
    printf("Your RegistryCode is %s \n", strrev(RegistryCode, MiddleCode));
    return 0;
}

char *strrev(char *s, char *t)
{
    char *r = s;
    t += strlen(t);
    while (*s++ = *--t)
    {
        ;
    }
    return r;
}
2005-1-30 11:11
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
最初由 prince 发布


呵呵,真是不好意思,这里我写得确实比较模糊。原因是这样,我在分析他算法的时候是在读取完MachineCode等关键值后单步跟了好多步,具体多少我忘了,然后看到注册表中还有好多的键值程序还没有读完,就为了方便,直接打开内存镜像搜索我输入的假码,然后下内存访问中断,直接就找到了。可是在写这篇文章的时候忘了在什么地方开始下内存断点了 ,就用了笨方法,直接单步跟踪来到了计算注册码的地方。呵呵,菜啊!

那个EditorTabWidth是C-Free要用到的一个值,看名字应该是在编辑代码的时候按Tab键跳跃的列数。问为什么看到它就知道来到了关键地方?呵呵,跟踪喽,跟到关键地方后,记下地址或在上面下个断点,再重新调试分析,因为读完EditorTabWidth这个值后就快到计算注册码的地方了,所以这里我就拿它做标志讲解了。

多谢指教!
2005-1-30 11:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
我觉得 dev-c++不错啊
2005-4-24 20:38
0
游客
登录 | 注册 方可回帖
返回
//