罗婷 发表于 2021-7-23 05:41

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怎么快捷打印它的内容?

**************************割一下**************************************

各位大神属实惊艳,感谢

agd 发表于 2021-7-23 09:17

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;
}

天上飞来一只 发表于 2021-7-23 07:51

贴整个函数反汇编

lies2014 发表于 2021-7-23 08:43

byte_100060D0应该是个一维数组,起始地址就是100060D0

zlbcl88 发表于 2021-7-23 08:49

本帖最后由 zlbcl88 于 2021-7-23 08:52 编辑

来学习得,我也看得不太明白,静等高手。。。

evea 发表于 2021-7-23 09:22

本帖最后由 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 = 这行应该可以再优化一下

Tugou 发表于 2021-7-23 09:27

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;
}



以下是个人理解

飘零星夜 发表于 2021-7-23 09:29

好多热心网友, 学到了,

evea 发表于 2021-7-23 09:41

本帖最后由 evea 于 2021-7-23 09:46 编辑

:lol   没丢失,主要能cookie 就能解

一个悲桑的问题 发表于 2021-7-23 10:16

你们一个个是真的牛皮……
页: [1] 2
查看完整版本: IDA Pro 一段伪代码读不明白,望坛友指点一二