IDA Pro 一段伪代码读不明白,望坛友指点一二
本帖最后由 罗婷 于 2021-7-24 07:24 编辑char __stdcall DoEncrypt(void *dataSrc, int lenth, int cookie, int key, int result)
{
int v6; //
unsigned __int16 *v7; //
int i; //
int j; //
int k; //
char v11; //
unsigned __int8 v12; //
unsigned int v13; //
int newLenth; //
unsigned __int16 *v15; //
if ( *(int *)lenth < 0 || *(int *)lenth >= 4098 )
return 0;
memcpy((void *)(result + 1), dataSrc, *(_DWORD *)lenth);
newLenth = result + 1;
v11 = 0;
for ( i = 0; i < *(_DWORD *)lenth; ++i )
v11 += *(_BYTE *)(i + newLenth);
v15 = (unsigned __int16 *)(newLenth - 1);
++*(_DWORD *)lenth;
*(_BYTE *)v15 = -v11;
v12 = *(_BYTE *)key;
for ( j = 0; j < *(_DWORD *)lenth; ++j )
{
*((_BYTE *)v15 + j) ^= byte_100060D0;
v12 += 3;
}
*(_BYTE *)key = v12;
v6 = (*(_DWORD *)lenth + 3) / 4;
v7 = v15;
v13 = *(_DWORD *)cookie;
for ( k = 0; k < v6; ++k )
{
*(_DWORD *)&v15 ^= v13;
v13 = (((271405 * (unsigned int)v7 + 2951407) >> 16 << 16) | ((271405 * (unsigned int)*v7 + 2951407) >> 16)) ^ 0xD77DD77D;
v7 += 2;
}
*(_DWORD *)cookie = v13;
return 1;
}
参数皆为传址,没读懂整个函数,望坛友可以帮忙翻译一下 可以为汇编外任意语言,再一个 byte_100060D0应该是个常量 IDA Pro怎么快捷打印它的内容?
**************************割一下**************************************
各位大神属实惊艳,感谢 char __stdcall DoEncrypt(void *dataSrc, int lenth, int cookie, int key, int result)
{
int v6; //
unsigned __int16 *v7; //
int i; //
int j; //
int k; //
char v11; //
unsigned __int8 v12; //
unsigned int v13; //
int newLenth; //
unsigned __int16 *v15; //
if ( *(int *)lenth < 0 || *(int *)lenth >= 4098 )
return 0;
memcpy((void *)(result + 1), dataSrc, *(_DWORD *)lenth); //拷贝dataSrc至result + 1
newLenth = result + 1; //记录拷贝后数据的起始地址,赋值符左边写成newDataStart好理解些
v11 = 0; //累加和初始化,char类型,占1字节
for ( i = 0; i < *(_DWORD *)lenth; ++i ) //从数据新地址处逐字节计算累加和
v11 += *(_BYTE *)(i + newLenth);
v15 = (unsigned __int16 *)(newLenth - 1); //v15指向result
++*(_DWORD *)lenth; //总数据的字节数加1,用于后文加密
*(_BYTE *)v15 = -v11; //v15类型转换为int8*,仍指向result,累加和的相反数存入result
v12 = *(_BYTE *)key; //取key的起始偏移
for ( j = 0; j < *(_DWORD *)lenth; ++j )
{
*((_BYTE *)v15 + j) ^= byte_100060D0; //v15转换为int8*,指向result,开始逐字节异或
v12 += 3; //更新偏移
}
*(_BYTE *)key = v12; //第一轮异或结束,将更新后的偏移写回key,使下一轮函数调用可以得到正确的起始偏移,对应v12 = *(_BYTE *)key;这行
v6 = (*(_DWORD *)lenth + 3) / 4; //4字节对齐,获取lenth个byte占用的int数,如:lenth为3时,3个byte占用1个int,4个byte占用1个int,5个byte占用2个int
v7 = v15; //v7指向result
v13 = *(_DWORD *)cookie; //获取初始密钥
for ( k = 0; k < v6; ++k )
{
*(_DWORD *)&v15 ^= v13; //逐字异或,此处的v15为默认的 int16*,&v15指向result,&v15指向result
v13 = (((271405 * (unsigned int)v7 + 2951407) >> 16 << 16) | ((271405 * (unsigned int)*v7 + 2951407) >> 16)) ^ 0xD77DD77D; //更新密钥
v7 += 2; //更新密钥的“药引子”,v7为int16*,初始指向result,v7+2后指向result
}
*(_DWORD *)cookie = v13; //将更新后的密钥写回cookie,使下一轮函数调用可以得到正确的初始密钥,对应v13 = *(_DWORD *)cookie; 这行
return 1;
} 贴整个函数反汇编 byte_100060D0应该是个一维数组,起始地址就是100060D0 本帖最后由 zlbcl88 于 2021-7-23 08:52 编辑
来学习得,我也看得不太明白,静等高手。。。 本帖最后由 evea 于 2021-7-23 09:25 编辑
boolDoEncrypt(void *dataSrc, int & lenth, int &cookie, unsignedchar& key, unsignedchar *result)
{
if(lenth < 0 || lenth > 2048)
return false;
memcpy(result + 1,dataSrc,lenth);
char check = 0;
for(int i = 0; i < lenth; ++i)
check += result;
++lenth;
result = -check;
unsigned charv12 = key;
for (int j = 0; j < lenth; ++j )
{
result ^= byte_100060D0;
v12 += 3;
}
key = v12;
int loop = (lenth + 3) / 4;
unsigned int v13 =cookie;
unsigned int *pInt = (unsigned int *)result;
unsigned short *pShort = (unsigned short *)result;
for(int j = 0; j < loop; ++j)
{
*pInt++ ^= v13;
v13 = (((271405 * pShort + 2951407) >> 16 << 16) | ((271405 * pShort + 2951407) >> 16)) ^ 0xD77DD77D;;
pShort += 2;
}
cookie = v13;
return true;
}
v13 = 这行应该可以再优化一下 char __stdcall DoEncrypt(void *dataSrc, int lenth, int cookie, int key, int result)
{
int v6; //
unsigned __int16 *v7; //
int i; //
int j; //
int k; //
char v11; //
unsigned __int8 v12; //
unsigned int v13; //
int newLenth; //
unsigned __int16 *v15; //
// 明文数组不能为空且长度不能过大
if ( *(int *)lenth < 0 || *(int *)lenth >= 4098 )
return 0;
// 密文数组第一个字节保留用途,从下标1位置开始存储明文数组,密文长度就是 len(明文)+1
memcpy((void *)(result + 1), dataSrc, *(_DWORD *)lenth);
newLenth = result + 1;
v11 = 0;
// 计算明文数组元素的和
for ( i = 0; i < *(_DWORD *)lenth; ++i )
v11 += *(_BYTE *)(i + newLenth); // total += src;
// v15 = &dst;密文起始地址
v15 = (unsigned __int16 *)(newLenth - 1);
// 更新参数中的密文长度
++*(_DWORD *)lenth;
// dst = -total; 密文第一个字节,现阶段存放后续明文的校验和
*(_BYTE *)v15 = -v11;
// 数组每一个元素与查表byte_100060D0数组中的元素进行异或操作, dst ^= byte_100060D0; key += 3;
v12 = *(_BYTE *)key;
for ( j = 0; j < *(_DWORD *)lenth; ++j )
{
*((_BYTE *)v15 + j) ^= byte_100060D0;
v12 += 3;
}
// 更新查表的下标,应该是用于下一次加密或解密
*(_BYTE *)key = v12;
v6 = (*(_DWORD *)lenth + 3) / 4; // 计算 模4的值,用于最后四字节加密的循环次数
v7 = v15;
v13 = *(_DWORD *)cookie;
// 4字节为单位,进行最后一步加密
for ( k = 0; k < v6; ++k )
{
// 因为v15是short指针, 所以*2 每次对齐4字节, 相当于 dst ^= cookie;
*(_DWORD *)&v15 ^= v13;
// 更新密钥,这个过程不知道咋设计的,数学匮乏~ 伪代码: cookie = ((x * (dst+0x2D08EF))&0xFFFF0000 | (0x4242D * dst + 0x2D08EF))0x0000FFFF) ^ 0xD77DD77D; dst++;这里dst默认int格式数组,过程是数组的两个元素,一通运算之后异或一个值
v13 = (((271405 * (unsigned int)v7 + 2951407) >> 16 << 16) | ((271405 * (unsigned int)*v7 + 2951407) >> 16)) ^ 0xD77DD77D;
v7 += 2;
}
// 把运算过程的密钥值回传给调用者
*(_DWORD *)cookie = v13;
return 1;
}
以下是个人理解
好多热心网友, 学到了, 本帖最后由 evea 于 2021-7-23 09:46 编辑
:lol 没丢失,主要能cookie 就能解 你们一个个是真的牛皮……
页:
[1]
2