现在的位置: 首页 > 综合 > 正文

编译器C-Free V3.52注册算法分析 【附注册机】

2013年08月20日 ⁄ 综合 ⁄ 共 8585字 ⁄ 字号 评论关闭

本来邪恶八进制有一个注册机的 可是这几天进不去 我在网上找了这篇文章 顺便把注册机编译出来

要是编译的时候 提示缺少文件 你可以尝试去掉 #include "stdafx.h"

=====================================

stdafx.h的作用 你注意到了吗?

1.关于stdafx.h的作用:
Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程序也要花费相当长的时间来完成工作。由于每个.CPP文件都包含相同的include文件,为每个.CPP文件都重复处理这些文件就显得很傻了。
为避免这种浪费,AppWizard和Visual C++编译程序一起进行工作,如下所示:
AppWizard建立了文件stdafx.h,该文件包含了所有当前工程文件需要的MFC include文件。且这一文件可以随被选择的选项而变化。
AppWizard然后就建立stdafx.cpp。这个文件通常都是一样的。
然后AppWizard就建立起工程文件,这样第一个被编译的文件就是stdafx.cpp。
当Visual C++编译stdafx.cpp文件时,它将结果保存在一个名为stdafx.pch的文件里。 (扩展名pch表示预编译头文件。)
当Visual C++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。 Visual C++不再分析Windows include文件,除非你又编缉了stdafx.cpp或stdafx.h。

2.编译程序中老出现“fatal error C1010: unexpected end of file while looking for precompiled header directive”这是怎么一回事?

(1)肯定是一个新添加的类的.cpp文件开头没包含stdafx.h,在该文件最前面加上即可。

(2)可以使用右键点击项目工程中的该cpp文件,选择setting,在c/c++栏,选择PreCompiled headers,然后设置第一选项,选择不使用预编译头,解决这个问题。

====================================

编译器C-Free V3.52注册算法分析

作者:prince
Email:
cracker_prince@163.com
QQ: 812937

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源码的注册机:

-----------------------------------------------------------------------------------------
Codz:


#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;
}

附件: cfree.exe [需 0 社区元下载]
该文件已经被下载 1 次.

抱歉!评论已关闭.