Andrénalin.2

拿到程序是找序列号的,查壳没有,vb写的。先运行下,随便输入字符,ok按钮才激活,然后点击后弹出错误的弹窗。

在od中查找字符串,找到了相关信息。

跟进去看了下,找到了跳转的分支。

eax和ecx里面存的什么不知道,往上找。跟了好多次,发现当输入name后,点击ok按钮,会对name的每一位ASSIC码进行一个累加。累加完成后,会和一个0x499602D2的数相乘,计算出的结果转化成十进制后,形成一个字符串,然后在字符串的第四位和第九位替换成‘-’,最后拼接成序列号。

累加部分:我这里输入的123,换成assic后,是31,32,33,三个数累加后,结果为96。

相乘部分:ecx里存放的是累加后的0x96,然后和0x499602D2相乘,计算结果保存在0x0019F114中。因为这里相乘的时候用的是vb的函数,所以找具体相乘的地方,可以在ebp-0xA4的地址下一个硬件访问断点,因为是累加的数乘这个固定的数,然后就能找到相乘的位置。

 可以看到乘完以后eax的值,转化成十进制正好的185185183500

拼接序列号:将乘出来的数十进制转成字符串,然后把第四位和第九位替换成‘-’,最后得到序列号

比较部分:最后就是将输入的和正确的序列号进行比较

测试下,输入123,序列号为185-8518-500,弹出正确的对话框。这个注册机写了一下。


#include <iostream>
#include <stdio.h>
#include<windows.h>

//两数相乘超过32位后,eax存不下整个数字,edx存高位,eax存地位,这里取出高位和低位的数
void mult(long op1, long op2, long *prod_hi, long *prod_lo)
{
	long op1_hi = (op1 >> 16) & 0xffff;
	long op1_lo = op1 & 0xffff;
	long op2_hi = (op2 >> 16) & 0xffff;
	long op2_lo = op2 & 0xffff;
	long cross_prod = op1_lo * op2_hi + op1_hi * op2_lo;
	*prod_hi = op1_hi * op2_hi + ((cross_prod >> 16) & 0xffff);
	*prod_lo = op1_lo * op2_lo + ((cross_prod << 16) & 0xffff0000);
}
//计算序列号,比较low,没考虑输入汉字什么乱七八遭的情况,就单纯的数字,字母应该都可以
void calcSerial(char *str, char *ret, int len)
{
	long Tmp = 0;
	long Num = 0x499602D2;
	long Hcalc = 0;
	long Lcalc = 0;
	long long calc = 0;
	char strTmp[50] = {};
	for (int i = 0; i < len; i++)
	{
		Tmp += str[i];
	}
	mult(Tmp, Num, &Hcalc, &Lcalc);
	
	calc |= Hcalc;
	long long tmp = calc << 32;
	tmp |= (unsigned)Lcalc;
	//直接转化成浮点数,来转字符串,然后截掉小数点
	sprintf(strTmp, "%lf", (double)tmp);    
	char *index = strstr(strTmp, ".");
	strTmp[index - strTmp] = '\0';
	strTmp[3] = '-';
	strTmp[8] = '-';
	memcpy(ret, strTmp, strlen(strTmp));
}
	
int main()
{
	char str[50] = {};
	char aa[50] = {};
	int len = 0;
	printf("输入name: ");
	scanf("%s", str);
	len = strlen(str);
	if (len == 0)
	{
		printf("输入name!\n");
	}
	else
	{
		calcSerial(str, aa, len);
		printf("序列号为%s\n", aa);
	}
	system("pause");
	return 0;
}

 测试结果。

猜你喜欢

转载自blog.csdn.net/weixin_42489582/article/details/85849435
2
>&2
α2
2-2