吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2688|回复: 10
收起左侧

[已解决] IDA Pro 一段伪代码读不明白,望坛友指点一二

[复制链接]
罗婷 发表于 2021-7-23 05:41
本帖最后由 罗婷 于 2021-7-24 07:24 编辑

[C++] 纯文本查看 复制代码
char __stdcall DoEncrypt(void *dataSrc, int lenth, int cookie, int key, int result)
{
  int v6; // [esp+8h] [ebp-18h]
  unsigned __int16 *v7; // [esp+Ch] [ebp-14h]
  int i; // [esp+14h] [ebp-Ch]
  int j; // [esp+14h] [ebp-Ch]
  int k; // [esp+14h] [ebp-Ch]
  char v11; // [esp+18h] [ebp-8h]
  unsigned __int8 v12; // [esp+18h] [ebp-8h]
  unsigned int v13; // [esp+1Ch] [ebp-4h]
  int newLenth; // [esp+38h] [ebp+18h]
  unsigned __int16 *v15; // [esp+38h] [ebp+18h]

  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];
    v12 += 3;
  }
  *(_BYTE *)key = v12;
  v6 = (*(_DWORD *)lenth + 3) / 4;
  v7 = v15;
  v13 = *(_DWORD *)cookie;
  for ( k = 0; k < v6; ++k )
  {
    *(_DWORD *)&v15[2 * k] ^= v13;
    v13 = (((271405 * (unsigned int)v7[1] + 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
[C] 纯文本查看 复制代码
char __stdcall DoEncrypt(void *dataSrc, int lenth, int cookie, int key, int result)
{
  int v6; // [esp+8h] [ebp-18h]
  unsigned __int16 *v7; // [esp+Ch] [ebp-14h]
  int i; // [esp+14h] [ebp-Ch]
  int j; // [esp+14h] [ebp-Ch]
  int k; // [esp+14h] [ebp-Ch]
  char v11; // [esp+18h] [ebp-8h]
  unsigned __int8 v12; // [esp+18h] [ebp-8h]
  unsigned int v13; // [esp+1Ch] [ebp-4h]
  int newLenth; // [esp+38h] [ebp+18h]
  unsigned __int16 *v15; // [esp+38h] [ebp+18h]
 
  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[v12];    //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[2 * k] ^= v13;    //逐字异或,此处的v15为默认的 int16*,&v15[2 *0]指向result[0],&v15[2 *1]指向result[4]
    v13 = (((271405 * (unsigned int)v7[1] + 2951407) >> 16 << 16) | ((271405 * (unsigned int)*v7 + 2951407) >> 16)) ^ 0xD77DD77D;    //更新密钥
    v7 += 2;    //更新密钥的“药引子”,v7为int16*,初始指向result[0],v7+2后指向result[4]
  }
  *(_DWORD *)cookie = v13;    //将更新后的密钥写回cookie,使下一轮函数调用可以得到正确的初始密钥,对应  v13 = *(_DWORD *)cookie;    这行
  return 1;
}

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
罗婷 + 1 + 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 编辑

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

免费评分

参与人数 1吾爱币 -8 收起 理由
涛之雨 -8 请勿灌水,提高回帖质量是每位会员应尽的义务!

查看全部评分

evea 发表于 2021-7-23 09:22
本帖最后由 evea 于 2021-7-23 09:25 编辑

[C++] 纯文本查看 复制代码
bool  DoEncrypt(void *dataSrc, int & lenth, int &cookie, unsigned  char& key, unsigned  char *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[i + 1];
	++lenth;
	result[0] = -check;
	unsigned char  v12 = key;
	for (int j = 0; j < lenth; ++j )
	{
    result[j] ^= byte_100060D0[v12];
    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[1] + 2951407) >> 16 << 16) | ((271405 * pShort[0] + 2951407) >> 16)) ^ 0xD77DD77D;;
		pShort += 2;
	}
	cookie = v13;
	return true;
}


v13 = 这行应该可以再优化一下

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
罗婷 + 1 + 1 谢大神

查看全部评分

Tugou 发表于 2021-7-23 09:27
[C] 纯文本查看 复制代码
char __stdcall DoEncrypt(void *dataSrc, int lenth, int cookie, int key, int result)
{
  int v6; // [esp+8h] [ebp-18h]
  unsigned __int16 *v7; // [esp+Ch] [ebp-14h]
  int i; // [esp+14h] [ebp-Ch]
  int j; // [esp+14h] [ebp-Ch]
  int k; // [esp+14h] [ebp-Ch]
  char v11; // [esp+18h] [ebp-8h]
  unsigned __int8 v12; // [esp+18h] [ebp-8h]
  unsigned int v13; // [esp+1Ch] [ebp-4h]
  int newLenth; // [esp+38h] [ebp+18h]
  unsigned __int16 *v15; // [esp+38h] [ebp+18h]
 
  // 明文数组不能为空且长度不能过大
  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[i];
  // v15 = &dst[0];  密文起始地址
  v15 = (unsigned __int16 *)(newLenth - 1);                
  // 更新参数中的密文长度
  ++*(_DWORD *)lenth;
  // dst[0] = -total; 密文第一个字节,现阶段存放后续明文的校验和
  *(_BYTE *)v15 = -v11;
  
  // 数组每一个元素与查表byte_100060D0数组中的元素进行异或操作, dst[i] ^= byte_100060D0[key]; key += 3;
  v12 = *(_BYTE *)key;
  for ( j = 0; j < *(_DWORD *)lenth; ++j )
  {
    *((_BYTE *)v15 + j) ^= byte_100060D0[v12];
    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[i] ^= cookie;  
    *(_DWORD *)&v15[2 * k] ^= v13;
        // 更新密钥,这个过程不知道咋设计的,数学匮乏~ 伪代码: cookie = ((x * (dst[i+1]+0x2D08EF))&0xFFFF0000 | (0x4242D * dst[i] + 0x2D08EF))0x0000FFFF) ^ 0xD77DD77D; dst++;  这里dst默认int格式数组,过程是数组的两个元素,一通运算之后异或一个值
    v13 = (((271405 * (unsigned int)v7[1] + 2951407) >> 16 << 16) | ((271405 * (unsigned int)*v7 + 2951407) >> 16)) ^ 0xD77DD77D;
    v7 += 2;
  }
  // 把运算过程的密钥值回传给调用者
  *(_DWORD *)cookie = v13;
  return 1;
}




以下是个人理解

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
罗婷 + 1 + 1 谢大神

查看全部评分

飘零星夜 发表于 2021-7-23 09:29
好多热心网友, 学到了,

免费评分

参与人数 1吾爱币 -8 收起 理由
涛之雨 -8 请勿灌水,提高回帖质量是每位会员应尽的义务!

查看全部评分

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

   没丢失,主要能cookie 就能解
一个悲桑的问题 发表于 2021-7-23 10:16
你们一个个是真的牛皮……

免费评分

参与人数 1吾爱币 -4 收起 理由
涛之雨 -4 未能按照本版块发帖要求发帖,请仔细阅读本版块版规再发帖,谢谢理解!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 00:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表