【文章标题】:三国kill字符串加密算法 【文章作者】: Ericky 【作者博客】: http://blog.csdn.net/hk9259
【下载地址】: 百度下载 【保护方式】: 字符串加密
【作者声明】: 本人水平有限,若有不足错误之处请各位大侠指正 0x1 前言 据说这款游戏的老版本是可以直接修改其中相应的字符串来进行狸猫换太子,从而绕过检验并且达到内购 破解的效果,如今时隔一年,该游戏为了防止被篡改或者其他,加强了对自身的加密,尤其把一些关键字符串所保护,强度是否值得起时间的考验,我们来一探究竟。 0x2 定位 打开libgame.so,按照以前的思路,在浩瀚的字符串中找到加密的字符串如下: 定位到红色框框中的类如下:
0x3 分析 分析如图: 继续向下分析: 跟进后如下: Base64为标准的解密方式。 而下面的函数为Xor编码函数,不用管我们继续往下跟进: 这里是一个循环解密,关键函数为70004C。 跟进去再继续跟来到SUB_7BE950这个函数: 然后进行解密,解密出来的字符串用于so里面的调用。 0x4 写解密加密程序 还原加密代码如下: [Asm] 纯文本查看 复制代码 //加密字符串
BYTE arry[] = "classes.dea";
//加密KEY
const uint32_t Key = 0x9f;
//初始化
unsigned char XorOut[100] ="";
char Base64Out[100]="";
const size_t lens = sizeof(arry);
for (size_t i = 0 ; i < lens - 1; i++) {
XorOut[i] = arry[i] ^ (Key+i);
}
base64_encode( XorOut, Base64Out, lens-1 );
printf("%s\n", Base64Out);
char * base64_encode( const unsigned char * bindata, char * base64, int binlength )
{
int i, j;
unsigned char current;
for ( i = 0, j = 0 ; i < binlength ; i += 3 )
{
current = (bindata[i] >> 2) ;
current &= (unsigned char)0x3F;
base64[j++] = base64char[(int)current];
current = ( (unsigned char)(bindata[i] << 4 ) ) & ( (unsigned char)0x30 ) ;
if ( i + 1 >= binlength )
{
base64[j++] = base64char[(int)current];
base64[j++] = '=';
base64[j++] = '=';
break;
}
current |= ( (unsigned char)(bindata[i+1] >> 4) ) & ( (unsigned char) 0x0F );
base64[j++] = base64char[(int)current];
current = ( (unsigned char)(bindata[i+1] << 2) ) & ( (unsigned char)0x3C ) ;
if ( i + 2 >= binlength )
{
base64[j++] = base64char[(int)current];
base64[j++] = '=';
break;
}
current |= ( (unsigned char)(bindata[i+2] >> 6) ) & ( (unsigned char) 0x03 );
base64[j++] = base64char[(int)current];
current = ( (unsigned char)bindata[i+2] ) & ( (unsigned char)0x3F ) ;
base64[j++] = base64char[(int)current];
}
base64[j] = '\0';
return base64;
} 还原解密代码如下: [Asm] 纯文本查看 复制代码 //*******************解密
//KEY
const uint32_t Key2 = 0X9f;
//解密字符串
const char Base64In[]="7cXSzdbWxsPUhsbf3w==";
const size_t lens2 = (sizeof(Base64In)- 1)*3/4 -2;
//Base64解密后存放
unsigned char XorIn[] ="";
//Base64解密
base64_decode( Base64In, XorIn);
//Xor解密后存放
char Base64Outd[100] = "";
//Xor解密
for (size_t i = 0 ; i < lens2; i++) {
Base64Outd[i] = XorIn[i] ^ (Key2+i);
}
printf("%s\n", Base64Outd);
int base64_decode( const char * base64, unsigned char * bindata )
{
int i, j;
unsigned char k;
unsigned char temp[4];
for ( i = 0, j = 0; base64[i] != '\0' ; i += 4 )
{
memset( temp, 0xFF, sizeof(temp) );
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i] )
temp[0]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i+1] )
temp[1]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i+2] )
temp[2]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i+3] )
temp[3]= k;
}
bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2))&0xFC)) |
((unsigned char)((unsigned char)(temp[1]>>4)&0x03));
if ( base64[i+2] == '=' )
break;
bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4))&0xF0)) |
((unsigned char)((unsigned char)(temp[2]>>2)&0x0F));
if ( base64[i+3] == '=' )
break;
bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6))&0xF0)) |
((unsigned char)(temp[3]&0x3F));
}
return j;
} 0x5 测试结果 7cXSzdbWxsPUhsbf3w== --------> resources.out 88nDjcLWyMPGysCFx8XPyc7d1JzA2w== --------> lib/armeabi/libgame.so 88nDjcLWyMPGysCH3ZvMgcPZ09XS2dCYxNc= --------> lib/armeabi-v7a/libgame.so /MzA0dDB1ojDzdE= --------> classes.dex 0x6总结 需要十足的耐心来分析算法,很锻炼人,睡觉。 2015.7.26 By Ericky
|