首页
社区
课程
招聘
[原创]Mac OS X下一软件Voila注册算法分析
发表于: 2010-1-7 19:28 10249

[原创]Mac OS X下一软件Voila注册算法分析

2010-1-7 19:28
10249

Voila keygen

工具: IDA v5.2, gdb
IDA可以用Wine在mac os x上跑起来,或者有两台电脑,一台windows,跑IDA,另一台Mac。

在windows平台中打开ida,加载Voila(Mac OS X binary)
找到的关键地方为:
000A9B8F                         __VLRegister_registerContinue__





下面再跟进下面的函数:

000AA67A                         __VLRegister_validateKeyWithInfo_Fortype__

在000AA681执行后,查看ecx:


下面,判断使用什么key



参数nType_C是从下面传进来的.
__text:000A9C0B C7 44 24 0C 00 00 00 00                 mov     [esp+0B8h+var_AC], 0

看看key:



继续:


注意到上图最上面两行, 两个常数, 为方便起见,就当作是一个int64整数.

跟进_GetSystemInfo

实例化一个SystemState类



进入构造函数 SystemState::SystemState(unsigned char  const*, char  const*, long long, EValidationType):



如果没有传入上面提到的int64常数,则调用GetSeed函数来生成一个int64.

继续:



SystemState::GetFirstState 用来校验注册码的长度(0x20)和注册码的字符(数字和字母).

再跟进 SystemState::GetState



首先调用SystemState::GetDecryptText,然后对解出来的信息进行校验.

跟进SystemState::GetDecryptText:


取出序列号的最后一个字符,然后找到这个字符在” NIWHSALRMPJ5EKTUYX3012QV67ZGF984”中的位置(第一个字符位置为0),设为LastCharIndex。

下面再从注册码中的LastCharIndex开始,取5个字符,设为Part_5,将剩余的26个字符,合并为Part_26



再来看看SystemState::GenerateEncryptedPart
这个函数先将注册码分割为两部分,再将注册码用其在两个字符串中的位置所代替。
偶数字符从 SystemState::m_acSet2 db 'BCDORSJAMP5LEKTUYX3012QV67ZGF984',0 中取
奇数字符从 SystemState::m_acSet1 db 'NIWHSALRMPJ5EKTUYX3012QV67ZGF984',0 中取
注册码的第一个字符为0,偶数字符

再往下看



函数SystemState::ConvertNToHexa,将part_5转换为密钥(aes128),当成一个int64来看。

来看看函数SystemState::ConvertNToHexa的关键代码:


将part_5紧凑起来。因为两个字符级是32,index最大31,占5个bit,因此将这些5bit合并,使得每个字节的每个bit都利用。
同时将这个int64变成一个字符串。
  jmp     SystemState::GenerateNinHexa(uchar *,ulong long) ; 将int64变成字符串

再看看part_26的转换:



将26个index,也紧凑起来。

继续
调用CAESDecryptor::DecryptText,将part_26用part_5作密钥来解密


解密之后,回到函数SystemState::GetState
校验解出来的16个字节,以及part_5

解密出来的16个字节必须是 ds:__ZL13KeyForGeneric



part_5得到的int64,必须比上面提到的int64 0x00000000 001e8480 要小

Over。
剩下的活,就是写注册机。
该公司的另一款产品web2delight,算法一样。
关键代码为:

- (NSString*) doKeygen:(int)indexofproduct atusername:(NSString*)username atEmail:(NSString*)email
{
	NSString *szkey;
	unsigned char indata_web2delight[17] = {0x75,0x18,0x10,0x25,0x86,0x37,0x8B,0xDE,
											0x19,0xA7,0x21,0x90,0xD3,0x12,0xB4,0x86,0x00};
	unsigned char indata[17] = {0x86,0x97,0xB3,0xF1,0x6C,0xD2,0x22,0xE8,
								0x9B,0xCE,0xA7,0xC6,0xAE,0x65,0xB1,0xBB,0x00};
	unsigned char outdata[17] = {0};
	unsigned char aeskeydata[17] = {0};
	
	const char* set1 = "NIWHSALRMPJ5EKTUYX3012QV67ZGF984";
	const char* set2 = "BCDORSJAMP5LEKTUYX3012QV67ZGF984";
	
	const unsigned long long ullKeyLowLimit = 0x0;
	const unsigned long long ullKeyHighLimit = 0x001E8480;//1,1D,1,4,0
	const unsigned long long ullKeyLowLimitWeb2 = 0x0;
	const unsigned long long ullKeyHighLimitWeb2 = 0x00004E20;//
	unsigned long long ullKeyRandom = 0;
	unsigned char key5[5] = {0};
	unsigned char otherkey26[26] = {0};
	unsigned char c = 0;
	char szckey[33] = {0};
	int i = 0;
	unsigned char halfbyte = 0;
	int j = 0;
	
	
	
	srand(time(NULL));
	
	if(indexofproduct == 0)
	{
		ullKeyRandom = rand() % (ullKeyHighLimit - ullKeyLowLimit) + ullKeyLowLimit;
	}
	else if(indexofproduct == 1)
	{
		ullKeyRandom = rand() % (ullKeyHighLimitWeb2 - ullKeyLowLimitWeb2) + ullKeyLowLimitWeb2;
	}
	else
	{
		return nil;
	}
		
	for(i = 0; i < 5;i++)
	{
		c = ullKeyRandom >> (i) * 5;
		key5[i] = c & 0x1F;
	}
	
	
	c = rand() % (31 - 5); //the last char of registration code
	
	for(i = 0; i < 16;i++)
	{
		halfbyte = Gethalfbytefromint64(ullKeyRandom,i);
		aeskeydata[15 - i] = halfbyte2hexchar(halfbyte);
	}
	
	
	
	if(indexofproduct == 0)
	{
		aes_encrypt(indata,
				outdata,
				aeskeydata);
	}
	else if(indexofproduct == 1)
	{
		aes_encrypt(indata_web2delight,
					outdata,
					aeskeydata);
	}
	else
	{
		return nil;
	}
	
	
	//5 * 8 = 40, 40 / 5 = 8
	otherkey26[0] = outdata[0] & 0x1F;
	otherkey26[1] = ((outdata[1] & 0x3) << 3) | (outdata[0] >> 5);
	otherkey26[2] = (outdata[1] >> 0x2) & 0x1F;
	otherkey26[3] = ((outdata[2] & 0xF) << 1) | (outdata[1] >> 7);
	otherkey26[4] = ((outdata[3] & 0x1) << 4) | (outdata[2] >> 4);
	otherkey26[5] = (outdata[3] >> 1) & 0x1F;
	otherkey26[6] = ((outdata[4] & 0x7) << 2) | (outdata[3] >> 6);
	otherkey26[7] = (outdata[4] >> 3) & 0x1F;
	
	otherkey26[8] = (outdata[5]) & 0x1F;
	otherkey26[9] = ((outdata[6] & 0x3) << 3) | (outdata[5] >> 5);
	otherkey26[10] = (outdata[6] >> 2) & 0x1F;
	otherkey26[11] = ((outdata[7] & 0xF) << 1) | (outdata[6] >> 7);
	otherkey26[12] = ((outdata[8] & 0x1) << 4) | (outdata[7] >> 4);
	otherkey26[13] = (outdata[8] >> 1) & 0x1F;
	otherkey26[14] = ((outdata[9] & 0x7) << 2) | (outdata[8] >> 6);
	otherkey26[15] = (outdata[9] >> 3) & 0x1F;
	
	otherkey26[16] = (outdata[10]) & 0x1F;
	otherkey26[17] = ((outdata[11] & 0x3) << 3) | (outdata[10] >> 5);
	otherkey26[18] = (outdata[11] >> 2) & 0x1F;
	otherkey26[19] = ((outdata[12] & 0xF) << 1) | (outdata[11] >> 7);
	otherkey26[20] = ((outdata[13] & 0x1) << 4) | (outdata[12] >> 4);
	otherkey26[21] = (outdata[13] >> 1) & 0x1F;
	otherkey26[22] = ((outdata[14] & 0x7) << 2) | (outdata[13] >> 6);
	otherkey26[23] = (outdata[14] >> 3) & 0x1F;
	
	otherkey26[24] = (outdata[15]) & 0x1F;
	otherkey26[25] = ((outdata[16] & 0x3) << 3) | (outdata[15] >> 5);	
	
	for(i = 0; i < c;i++)
	{
		szckey[i] = otherkey26[i];
		
		j = szckey[i];
		if((i % 2) == 0)
		{
			szckey[i] = set2[j];
		}
		else
		{
			szckey[i] = set1[j];
		}
	}
	
	for(i = c; i < c + 5;i++)
	{
		szckey[i] = key5[i - c];
		
		j = szckey[i];
		if(((i - c) % 2) == 0)
		{
			szckey[i] = set2[j];
		}
		else
		{
			szckey[i] = set1[j];
		}
	}
	
	for(i = c + 5; i < 31;i++)
	{
		szckey[i] = otherkey26[i - 5];
		
		j = szckey[i];
		if(((i - 5) % 2) == 0)
		{
			szckey[i] = set2[j];
		}
		else
		{
			szckey[i] = set1[j];
		}
	}
	
	szckey[31] = set1[c];
	
	NSLog(@" key is %s",szckey);
	
	szkey = [[NSString stringWithCString:(const char*)szckey] retain];
	
	return szkey;
}


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
怎么听不到啊?这到底是为什么呢?
2010-1-7 19:30
0
雪    币: 47147
活跃值: (20420)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
winndy的知识面真广
2010-1-7 19:44
0
雪    币: 191
活跃值: (41)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
4
牛 X,牛 X
2010-1-7 20:27
0
雪    币: 440
活跃值: (717)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
5
还是师傅牛啊
2010-1-7 20:45
0
雪    币: 80
活跃值: (45)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
好强大啊。。。
2010-1-8 10:49
0
雪    币: 440
活跃值: (717)
能力值: ( LV9,RANK:690 )
在线值:
发帖
回帖
粉丝
7
关于OS X逆向的一个站点:

http://kellogsosx.blogspot.com/2007/04/links.html

里面链接不少
2010-1-8 16:38
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
8
厉害,收藏+学习
2010-1-10 22:41
0
游客
登录 | 注册 方可回帖
返回
//