:o:下了加密里面的一本书的光盘里面有个TraceMe.exe,也没去看书上怎么弄的,就因为刚看完了《C++逆向与反汇编技术解密》这本书,感觉想拿个东西练下手,就它了。很菜的,第一次分析算法,高手不笑,菜鸟学习不容易啊。
软件没加壳,OD载入后直接,查找字串。
附件 81410
在CPU窗口查看
在头部下断。
运行程序,发现无法运行,程序会不断调用此函数。
去掉断点,重新来过。运行程序发现输入用户名的框框。
于是用BP GetDlgitemtextA试下。
程序断在这里。单步走,查看堆栈,发现此处为取用户名和密码。
附件 81415
附件 81414
分析结果如下。以下用户名和注册码入栈后进入一个Call初步怀疑是算法Call,Call后一个跳转,测试跳转后,发现修改跳转结果,程序提示注册成功。
此时可确定些Call为算法Call。
重点分析这个Call的实现。
代码如下:
附件 81411
附件 81412
通过分析得出如下结论。
函数通过取用户输入的用户名,从第四个字符开始取,用取出字符的ASC码与依次取出的一个全局定义的整型数组项相乘,将依次的结果累加到一个局部变量中,将些作为注册码。
逆向的C代码如下。
int g_szBuffer[8]={0C,0A,13,09,0C,0B,0A,08};
int reav(char *userName,char *pass,int len)
{
int userNameLen=len,intFlag=0,intA=0,intB=0,intC=0;
char outBuffer[20]={0};
if(userNameLen>=3)
{
for(int i=3;i<userNameLen;i++)
{
if(intFlag>7)
{
intFlag=0;
}
intA=0;
intB=0;
intA=userName[i];
intB=g_szBuffer[intFlag];
intA*=intB;
intC+=intA;
intFlag++;
}
}
wsprintf(outBuffer,"%ld",intC);
if(lstrcmp(outBuffer,pass)==0);
{
return 1;
}
else
{
return 0;
}
}
顺手写出注册机
void reav(char *userName)
{
int userNameLen=strlen(userName),intFlag=0,intA=0,intB=0,intC=0;
char outBuffer[20]={0};
if(userNameLen>=3||userNameLen<20)
{
for(int i=3;i<userNameLen;i++)
{
if(intFlag>7)
{
intFlag=0;
}
intA=0;
intB=0;
intA=userName[i];
intB=g_szBuffer[intFlag];
intA*=intB;
intC+=intA;
intFlag++;
}
}
else
{
printf("用户名不能长长度不能小于3或大于20,请重新输入");
return;
}
wsprintf(outBuffer,"%ld",intC);
printf("正确注册码为:%d\n",intC);
}
分析完毕,第一次分析,加油!!
软件没加壳,OD载入后直接,查找字串。
附件 81410
在CPU窗口查看
在头部下断。
运行程序,发现无法运行,程序会不断调用此函数。
去掉断点,重新来过。运行程序发现输入用户名的框框。
于是用BP GetDlgitemtextA试下。
程序断在这里。单步走,查看堆栈,发现此处为取用户名和密码。
附件 81415
附件 81414
分析结果如下。以下用户名和注册码入栈后进入一个Call初步怀疑是算法Call,Call后一个跳转,测试跳转后,发现修改跳转结果,程序提示注册成功。
此时可确定些Call为算法Call。
重点分析这个Call的实现。
代码如下:
附件 81411
附件 81412
通过分析得出如下结论。
函数通过取用户输入的用户名,从第四个字符开始取,用取出字符的ASC码与依次取出的一个全局定义的整型数组项相乘,将依次的结果累加到一个局部变量中,将些作为注册码。
逆向的C代码如下。
int g_szBuffer[8]={0C,0A,13,09,0C,0B,0A,08};
int reav(char *userName,char *pass,int len)
{
int userNameLen=len,intFlag=0,intA=0,intB=0,intC=0;
char outBuffer[20]={0};
if(userNameLen>=3)
{
for(int i=3;i<userNameLen;i++)
{
if(intFlag>7)
{
intFlag=0;
}
intA=0;
intB=0;
intA=userName[i];
intB=g_szBuffer[intFlag];
intA*=intB;
intC+=intA;
intFlag++;
}
}
wsprintf(outBuffer,"%ld",intC);
if(lstrcmp(outBuffer,pass)==0);
{
return 1;
}
else
{
return 0;
}
}
顺手写出注册机
void reav(char *userName)
{
int userNameLen=strlen(userName),intFlag=0,intA=0,intB=0,intC=0;
char outBuffer[20]={0};
if(userNameLen>=3||userNameLen<20)
{
for(int i=3;i<userNameLen;i++)
{
if(intFlag>7)
{
intFlag=0;
}
intA=0;
intB=0;
intA=userName[i];
intB=g_szBuffer[intFlag];
intA*=intB;
intC+=intA;
intFlag++;
}
}
else
{
printf("用户名不能长长度不能小于3或大于20,请重新输入");
return;
}
wsprintf(outBuffer,"%ld",intC);
printf("正确注册码为:%d\n",intC);
}
分析完毕,第一次分析,加油!!