您的位置:首页 > 其它

一个含有crc32算法的CrackMe分析

2017-07-17 22:26 316 查看
exe文件的下载地址为: http://pan.baidu.com/s/1gfw0XKf

启动界面:



大概意思是输入用户名和序列号,检查是否匹配,现在用ida打开分析一下:



msg==0x111位处理传过来的WM_COMMAND消息








下面对关键的地方进行分析,F5大法:

size = GetDlgItemTextA(hWnd, 1004, name, 255);
// 取Name放到name数组里面
if ( size >= 4 )      // 名字必须大于等于4
{
nameSize = size;
codeSize[0] = GetDlgItemTextA(hWnd, 1005, code, 255);
crc32Init();
//对codeSize进行CRC32加密,且必须为0x2f6016f7
//用python写个爆破脚本可得到codeSize为26
if ( Funcrc32(codeSize) == 0x2F6016F7 )
{
RtlZeroMemory(byte_40347F, 8);//初始化0x40347f的8个字节
byte_40347F[0] = code[8];           //取第9位
byte_40347F[1] = code[17];//取第18位
crc32Init();
//将第9位和第18组成的字节数组进行CRC32加密,且必须为0x242C1465
if ( Funcrc32(byte_40347F) == 0x242C1465 )
{
//用python写个爆破脚本可得到9位和18位都为'-'
//可得到Serial的格式为12345678-12345678-12345678
RtlZeroMemory(&buffer1, 10);
RtlZeroMemory(&buffer2, 10);
cnt = 0;
while ( 1 )
{
t = code[cnt];
if ( t > '9' && t < 'A' )
break;
if ( t < '0' || t > 'F' )       // 16进制检查
break;
if ( ++cnt == 8 )
{
count = 0;
v10 = 0;
buffer1_1 = &buffer1;
do
{
v10 *= 16;
v12 = code[count];
*buffer1_1 = v12;
if ( v12 < 'A' || v12 > 'F' )
v13 = v12 - '0';          // 不正常
else
v13 = v12 - '7';          // 正常
LOBYTE(v10) = v13 & 0xF | v10;
++buffer1_1;
++count;
step1 = v10;
}
while ( count != 8 );
// 这个while循环将相应的16进制字符串转化为int类型
crc32Init();
crcName = Funcrc32(name);
//对name数组进行crc32加密,且必须等于Serial的第一部分
if ( step1 == crcName )       // 名字必须满足这个条件
{
v15 = 0;
v16 = &code[9];//Serial的第二部分的首地址
while ( 1 )
{
v17 = v16[v15];
if ( v17 > '9' && v17 < 'A' )
break;
if ( v17 < '0' || v17 > 'F' )
break;
if ( ++v15 == 8 )
{
cnt_1 = 0;
v19 = 0;
v20 = &buffer2;
do
{
v19 *= 16;
v21 = v16[cnt_1];
*v20 = v21;
*v16 = v21;
if ( v21 < 'A' || v21 > 'F' )
v22 = v21 - 48;
else
v22 = v21 - 55;
LOBYTE(v19) = v22 & 0xF | v19;
++v20;
++cnt_1;
step2 = v19;
}
while ( cnt_1 != 8 );
// 这个while循环将Serial第二部分的16进制字符串转化为int类型,并保存在step2变量里
crc32Init();
crcBuffer1 = Funcrc32(&buffer1);
if ( step2 == crcBuffer1 )
{
//Serial第二部分的值必须等于Serial第一部分CRC32加密后的值
crc32Init();
step2 = Funcrc32(&buffer2);
//对第二部分进行crc32加密,并且保存到step2变量里
v24 = 0;
v25 = &code[18];
while ( 1 )
{
v26 = v25[v24];
if ( (unsigned __i
b4cd
nt8)v26 > 0x39u && (unsigned __int8)v26 < 0x41u )
break;
if ( (unsigned __int8)v26 < 0x30u || (unsigned __int8)v26 > 0x46u )
break;
if ( ++v24 == 8 )
{
cnt_2 = 0;
v28 = 0;
do
{
v28 *= 16;
v29 = v25[cnt_2];
*v25 = v29;
if ( (unsigned __int8)v29 < 0x41u || (unsigned __int8)v29 > 0x46u )
v30 = v29 - 48;
else
v30 = v29 - 55;
LOBYTE(v28) = v30 & 0xF | v28;
++cnt_2;
step3 = v28;
}
while ( cnt_2 != 8 );这个while循环将Serial的第三部分16进制字符串转换为int类型
//
if ( (step2 ^ step1) == step3 )//最后一个条件step2和step1进行异或的值必须为step3
{
SetWindowTextA(hWnd, "GOOD JOB, MAN!");//成功
hCheck = GetDlgItem(hWnd, 0x3EE);
EnableWindow(hCheck, 0);// 禁用单击按钮


#求codeSize的脚本:
def     crc32(v):
'''
Generates the crc32 hash of the v.
@return: str, the str value for the crc32 of the v
'''
return "%08X"%(binascii.crc32(v)&0xffffffff)
for i in range(60):
crc = crc32(binascii.a2b_hex('%02X'%i))
#print crc
if crc=='2F6016F7':
print i
break

#求第9位和第18位的脚本:
for i,j in itertools.product(string.printable,string.printable):
crc =crc32(binascii.a2b_hex('%02X%02x'%(ord(i),ord(j))))
if crc=='242C1465':
print i,j
break

#上面是确定Serial的长度和格式:12345678-12345678-12345678
#最后注册机为:
import crypt,binascii,itertools
name = raw_input('输入你的注册名(大于4):')
c1 = crc32(name)
print 'c1',c1,hex(int(c1,16))
c2 = crypt.crc32(c1)
print 'c2',c2,hex(int(c2,16))
t = crypt.crc32(c2)
c3 = '%08X'%(int(t,16)^int(c1,16))
print 'Serial:',c1+'-'+c2+'-'+c3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: