吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 684|回复: 6
收起左侧

[原创] 对HYP的配置文件的一些研究

  [复制链接]
VisionTravel 发表于 2025-3-18 05:13

获取HYP(XX游启动器)的基本信息

第一次发帖,如果有问题欢迎指出!


最近闲来无事,浅浅研究了下XX游的启动器
在程序安装目录发现一个app.conf.dat,数据被混淆了,用 010 Editor没看出有什么可读的信息,所以尝试分析启动器目录下的其他文件。

简单研究

直接将动态链接库拖入Binary Ninja发现似乎没有混淆,所以查看了几个动态链接库的函数后在HYBase.dll中找到AppConfigManager类,并在initialize函数看到了疑似对app.conf.dat操作的实现。


查看反汇编进行初步猜测

初始化:

sub_1800346d0(&var_728, HoYo::Common::FileSystem::GetAppDir())
sub_18002d2d0(&var_728, &data_1803c5040)

使用GetAppDir()获取应用目录路径,并存储在var_728中。

加载app.conf.dat

if (sub_180051760(&s, &var_728) != 0)

初步推测这个函数实现了解析数据到s中,查看sub_180051760后发现sub_180051760是一个配置文件加载器,并且在sub_180051760中发现对app.conf.dat的一些验证相关的实现,所以转至sub_180051760继续研究。


对sub_180051760函数进行详细研究

有关的sub_180051760函数会在文末给出,因为太长了,影响阅读;为了方便理解,我在文中会将一部分伪代码简化。


1. 配置文件存在性检查

int32_t* rax_2 = sub_180052970(&var_308, arg2, 3)
uint32_t var_320 = (*rax_2).d
if (var_320 == 0 && rcx_1 == 0)
    goto label_180051831
else
    sub_180052dc0("exists", &var_2f8, arg2) // 记录错误并终止?
  • 猜测:
    • sub_180052970 可能是检查文件是否存在或获取文件属性的函数。
    • var_320 表示文件状态。
    • 若文件不存在,跳转到日志记录分支:
      HoYo::Common::LogStream::operator<<("File not exists:") 

      2. 配置文件大小检查

      sub_1802cd4a0(rcx_13, &var_2d8, 9, 0xffffffff) // 获取文件大小
      if (var_2d0 <= 0x110)    // 文件过小
      LogStream << "File too small:"
      elif (var_2d0 > 0x80000) // 文件过大
      LogStream << "File too large:"
  • 猜测:
    • var_2d0 存储文件大小。
    • 文件大小范围限制为 0x110 (272B) <= size <= 0x80000 (524KB),可能是配置文件的合法范围,我还没有验证。

3.文件读取

if (var_2d0 < 0x1000)
...
    rax_46 = operator new(var_2d0) // 小内存分配
...
else
    rax_44 = operator new(var_2d0 + 0x27) // 对齐分配(似乎加密需求,这里还看不出来什么)
std::basic_istream::read(s.q, var_2d0)    // 读取文件内容 180052373
  • 猜测:
    • 根据文件大小动态分配内存,可能是要适应某种加密?
      -读取配置文件内容,解密也在这之后进行。

4. 数据解密函数猜测

初步推测
sub_180050c80(&var_2b8, arg2, 0x21, 0x40) // 解密或解析操作
int64_t* s_1 = sub_180083340(&var_2f8, &s, ...) // 处理配置数据
  • 猜测:
    • 初步推测sub_180050c80 可能是解密函数(参数 0x210x40 似乎为解密模式或密钥标识)。
    • sub_180083340 将解密后的数据封装到 arg1 指向的结构中。
    • 在查看sub_180050c80后发现并不是解密操作,似乎是文件流初始化函数,但也与解密有关联性所以继续向下找。
关键代码段定位

在函数后半部分(地址1800523ec处)发现核心解密调用:

int64_t* s_1 = sub_180083340(&var_2f8, &s, &data_1803c51c0, &data_1803c51a0)

这里将读取的加密数据(s)与两个全局数据结构传递给sub_180083340,返回结果存储到arg1中。这里基本上可以确认sub_180083340时进行解密操作的函数了。


解密操作分步骤解析

  1. 文件读取与内存分配

    • 在地址180051f58处分配内存:rax_46 = operator new(var_2d0)
    • 通过std::basic_istream::read将文件内容读入缓冲区s.q(地址180052373
  2. 解密函数调用

    sub_180083340(
       &var_2f8,         // 输出缓冲区
       &s,               // 输入数据(加密内容)
       &data_1803c51c0,  // 疑似密钥/算法参数1
       &data_1803c51a0   // 疑似密钥/算法参数2
    )
  3. 结果处理

    • 将解密结果s_1arg1比较
    • 若不同,则将解密数据移动到arg1并清空临时缓冲区(地址18005243c处)
  4. 寻找秘钥
    使用binary ninja的code references找这两个数据被谁赋值了,找到关键函数sub_180001390,在这里找到了疑似秘钥的字符串1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8T,以及这个秘钥的结构:

偏移量 内容 长度 编码分析
0x00 1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8T 32字节 Base64特征字符串
0x20 0x4e44496941372f53 8字节 解码为ASCII "NDIiA7/S"
0x28 yTA= 4字节 base64结束标记

最后得出秘钥的Base64编码为1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8TS/7AiIDNyTA=
使用nodejs简单解码后输出长度,发现秘钥的长度为32字节,结合之前的猜测,这个秘钥大概率是AES-256-CBC算法的秘钥,但这个秘钥只是传入sub_180001390函数的第一个数据,第二个数据查看后发现是一个RSA公钥,所以可能是一个混合加密。

想了一下,这个混合加密可能使用AES加密数据主体,然后用RSA公钥加密AES秘钥,在解密时先用RSA私钥解密AES秘钥,再用AES解密数据。这里突然发现如果真是按我想的思路实现,那我完全不需要管这个RSA加密,因为我已经获取到了AES秘钥,所以决定直接测试解密app.conf.dat的数据。


解密配置文件

AES-256-CBC的初始化向量只影响第一个块,会使用第一个块的加密数据作为下一个块的iv,以此迭代,所以在不知道初始化向量时只有第一个块数据会出错,不影响后续数据。

使用nodejs编写一个简单的解密脚本:

const crypto = require('crypto');
const fs = require('fs');
const path = require('path');

const keyBase64 = '1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8TS/7AiIDNyTA=';
const key = Buffer.from(keyBase64, 'base64');
const iv = Buffer.alloc(16); //暂不知道iv的值,先填充0,后续再研究

class EncryptionHelper {
  static aesDecrypt(buffer) {
    const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
    decipher.setAutoPadding(true);
    let decrypted = decipher.update(buffer);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
  }
}

async function main() {
  const destFileName = 'app.conf.dat';
  let appDir = 'C:\\XXX Launcher';
  const versionDir = findVersionDirectory(appDir);
  if (!versionDir) {
    console.error('未找到有效版本目录');
    return;
  }
  const filePath = path.join(versionDir, destFileName);
  try {
    const buffer = fs.readFileSync(filePath);
    const decryptedContent = EncryptionHelper.aesDecrypt(buffer);
    console.log("解密内容:", decryptedContent);
  } catch (err) {
    console.error('解密失败:', err.message);
  }
}

//这个启动器版本目录是当前版本号,如1.4.5.222,会变,所以需要动态查找
function findVersionDirectory(baseDir) {
  const dirs = fs.readdirSync(baseDir, { withFileTypes: true })
    .filter(d => d.isDirectory())
    .map(d => path.join(baseDir, d.name))
    .find(dir => /^\d+(\.\d+)+$/.test(path.basename(dir)));
  return dirs;
}

main().catch(console.error);

运行后,得到app.conf.dat的解密后数据,但不完美,不过关键信息基本都在可读的数据内。

解密后数据

解密后数据

后续我可能会找出初始化向量,不过研究这个启动器也是一时兴起,随缘咯~

趣事

  • HYBase.dll中直接搜索这个秘钥的第一部分,发现还有一个秘钥1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8TS/7AiIDNyTA=这个也可以解密配置文件。在图表模式下查看sub_180001390的反汇编后发现这个可能是版本迭代时秘钥变更但没有完全清理?也可能是开发调试的残留。最后发现是我想多了,只是编码转换的问题。
  • 那个RSA公钥可能用于其他的功能实现,我发现在这个公钥附近有一些api获取相关的字符串,可能用于一些敏感信息的加解密?我有了一些猜测,如果有时间继续研究,我会写另一个帖子,因为我猜测的似乎和这个帖子的主题不太相关。

相关反汇编伪代码片段

没有完整给出,太长了,大家可以自己逆向去看

18003cdc0  int64_t HoYo::Base::AppConfigManager::initialize()()

18003cdc0  {
18003cdd9      void var_7f8;
18003cdd9      int64_t rax_1 = (__security_cookie ^ &var_7f8);
18003cde6      int32_t var_7c8 = 0;
18003cdfb      void var_728;
18003cdfb      sub_1800346d0(&var_728, HoYo::Common::FileSystem::GetAppDir());
18003ce10      sub_18002d2d0(&var_728, &data_1803c5040);
18003ce18      int128_t s;
18003ce18      __builtin_memset(&s, 0, 0x18);
18003ce37      int64_t result;
18003ce37      int64_t var_7b0;
18003ce37      void var_618;
18003ce37      
18003ce37      if (sub_180051760(&s, &var_728) != 0)
18003ce37      {
180051760  int64_t sub_180051760(int64_t* arg1, int64_t* arg2)

180051760  {
180051781      void var_378;
180051781      int64_t rax_1 = (__security_cookie ^ &var_378);
180051792      int64_t* var_328 = arg2;
18005179a      int32_t var_348 = 0;
1800517a8      void var_308;
1800517a8      int32_t* rax_2 = sub_180052970(&var_308, arg2, 3);
1800517b1      uint32_t var_320 = ((int32_t)*(uint64_t*)rax_2);
1800517b7      int32_t rcx_1 = rax_2[2];
1800517ba      int32_t var_2f8 = rcx_1;
1800517c8      void** var_2f0 = &data_1803c50b0;
1800517d8      var_2f8 = var_2f8;
1800517d8      
1800517e7      if (var_320 == 0)
1800517e7      {
1800517eb          if (rcx_1 == 0)
1800517eb              goto label_180051831;
1800517eb          
1800527cc          sub_180052dc0("exists", &var_2f8, arg2);
1800527cc          /* no return */
1800517e7      }
1800517e7      
1800517f6      void* const var_2b8;
1800517f6      
1800517f6      if (var_320 == 1)
1800517f6      {
180051831      label_180051831:
180051831          class HoYo::Common::LogStream* rax_5 = HoYo::Common::LogStream::operator<<(HoYo::Common::Logger::Logger(&var_2b8, "D:\jenkins_home\workspace\plat-l…", 0x21, "HoYo::Base::Details::ConfigFileL…", 4), "File not exists:");
18005183a          wchar16* r15_1 = arg2;
18005183a          
180051842          if (arg2[3] > 7)
180051844              r15_1 = *(uint64_t*)arg2;
180051844          
180051847          int64_t r14_1 = arg2[2];
18005184e          var_2f8 = {0};
180051856          int64_t r8_1 = 0;
180051859          int64_t var_2e8_1 = 0;
180051861          int64_t rax_6 = 0xf;
180051866          int64_t var_2e0_1 = 0xf;
18005186e          var_2f8 = 0;
180051876          int32_t var_348_1 = 2;
180051876          
180051881          if (r14_1 != 0)
180051881          {
18005188e              if (r14_1 > 0x7fffffff)
18005188e              {
1800527d5                  sub_180037230(0x16);
1800527d5                  /* no return */
18005188e              }
18005188e              
1800518a7              int64_t rax_7 = __std_fs_convert_wide_to_narrow(0xfde9, r15_1, r14_1, nullptr, 0);
1800518a7              
1800518b5              if (((int32_t)(rax_7 >> 0x20)) != 0)
1800518b5              {
1800527e1                  sub_180037270(((int32_t)(rax_7 >> 0x20)));
1800527e1                  /* no return */
1800518b5              }
1800518b5              
1800518bb              int64_t rcx_4 = ((int64_t)rax_7);
1800518be              int64_t rdx_1 = var_2e8_1;
1800518be              
1800518c9              if (rcx_4 > rdx_1)
1800518c9              {
1800518f6                  int64_t count = (rcx_4 - rdx_1);
1800518f6                  
18005190a                  if (count > (var_2e0_1 - rdx_1))
18005190a                  {
18005193f                      int32_t var_358_2;
18005193f                      var_358_2 = 0;
180051955                      sub_180016780(&var_2f8, count, 0, count, var_358_2);
18005190a                  }
18005190a                  else
18005190a                  {
18005190c                      var_2e8_1 = rcx_4;
180051914                      int32_t* rbx_1 = &var_2f8;
180051914                      
180051920                      if (var_2e0_1 > 0xf)
180051920                          rbx_1 = var_2f8;
180051920                      
180051929                      char* rbx_2 = ((char*)rbx_1 + rdx_1);
180051934                      memset(rbx_2, 0, count);
180051939                      rbx_2[count] = 0;
18005190a                  }
1800518c9              }
1800518c9              else
1800518c9              {
1800518cb                  char* rax_9 = &var_2f8;
1800518cb                  
1800518dc                  if (var_2e0_1 > 0xf)
1800518dc                      rax_9 = var_2f8;
1800518dc                  
1800518e5                  var_2e8_1 = rcx_4;
1800518ed                  rax_9[rcx_4] = 0;
1800518c9              }
1800518c9              
18005195a              int32_t* r9_2 = &var_2f8;
18005195a              
18005196b              if (var_2e0_1 > 0xf)
18005196b                  r9_2 = var_2f8;
18005196b              
180051983              int64_t rax_12 = __std_fs_convert_wide_to_narrow(0xfde9, r15_1, r14_1, r9_2, rax_7);
180051983              
180051991              if (((int32_t)(rax_12 >> 0x20)) != 0)
180051991              {
1800527eb                  sub_180037270(((int32_t)(rax_12 >> 0x20)));
1800527eb                  /* no return */
180051991              }
180051991              
180051997              rax_6 = var_2e0_1;
18005199f              r8_1 = var_2e8_1;
180051881          }
180051881          
1800519a7          wchar16* rdx_4 = &var_2f8;
1800519a7          
1800519b3          if (rax_6 > 0xf)
1800519b3              rdx_4 = var_2f8;
1800519b3          
1800519bf          sub_180015f00(rax_5, rdx_4, r8_1);
1800519bf          
1800519d1          if (var_2e0_1 > 0xf)
1800519d1          {
1800519d6              void* rcx_9 = var_2f8;
1800519de              void* rax_14 = rcx_9;
1800519de              
1800519e8              if ((var_2e0_1 + 1) >= 0x1000)
1800519e8              {
1800519ee                  rcx_9 = *(uint64_t*)((char*)rcx_9 - 8);
1800519ee                  
1800519fd                  if ((((char*)rax_14 - rcx_9) - 8) > 0x1f)
1800519fd                  {
1800519ff                      _invalid_parameter_noinfo_noreturn();
1800519ff                      /* no return */
1800519fd                  }
1800519e8              }
1800519e8              
180051a06              sub_1802d3e7c(rcx_9);
1800519d1          }
1800519d1          
180051a0b          int64_t var_2e8_2 = 0;
180051a13          int64_t var_2e0_2 = 0xf;
180051a1f          var_2f8 = 0;
180051881          goto label_180051a2f;
1800517f6      }
1800517f6      
180051a64      int64_t* rcx_13 = arg2;
180051a64      
180051a6c      if (arg2[3] > 7)
180051a6e          rcx_13 = *(uint64_t*)arg2;
180051a6e      
180051a85      void var_2d8;
180051a85      enum WIN32_ERROR rax_17 = sub_1802cd4a0(rcx_13, &var_2d8, 9, 0xffffffff);
180051a85      
180051a8c      if (rax_17 != NO_ERROR)
180051a8c      {
1800527b4          sub_180052e20("file_size", rax_17, arg2);
1800527b4          /* no return */
180051a8c      }
180051a8c      
180051aa1      uint64_t var_2d0;
180051aa1      int64_t result;
180051aa1      
180051aa1      if (var_2d0 <= 0x110)
180051aa1      {
180051ada          class HoYo::Common::LogStream* rax_19 = HoYo::Common::LogStream::operator<<(HoYo::Common::Logger::Logger(&var_2b8, "D:\jenkins_home\workspace\plat-l…", (rax_17 + 0x28), "HoYo::Base::Details::ConfigFileL…", 4), "File too small:");
180051ae3          int64_t* r15_2 = arg2;
180051ae3          
180051aeb          if (arg2[3] > 7)
180051aed              r15_2 = *(uint64_t*)arg2;
180051aed          
180051af0          int64_t r14_2 = arg2[2];
180051af7          var_2f8 = {0};
180051aff          int64_t r8_7 = 0;
180051b02          int64_t var_2e8_3 = 0;
180051b0a          int64_t rax_20 = 0xf;
180051b0f          int64_t var_2e0_3 = 0xf;
180051b17          var_2f8 = 0;
180051b1f          int32_t var_348_2 = 8;
180051b1f          
180051b2a          if (r14_2 != 0)
180051b2a          {
180051b37              if (r14_2 > 0x7fffffff)
180051b37              {
1800527f4                  sub_180037230(0x16);
1800527f4                  /* no return */
180051b37              }
180051b37              
180051b50              int64_t rax_21 = __std_fs_convert_wide_to_narrow(0xfde9, r15_2, r14_2, nullptr, 0);
180051b50              
180051b5e              if (((int32_t)(rax_21 >> 0x20)) != 0)
180051b5e              {
180052800                  sub_180037270(((int32_t)(rax_21 >> 0x20)));
180052800                  /* no return */
180051b5e              }
180051b5e              
180051b64              int64_t rcx_16 = ((int64_t)rax_21);
180051b67              int64_t rdx_9 = var_2e8_3;
180051b67              
180051b72              if (rcx_16 > rdx_9)
180051b72              {
180051b9f                  uint64_t count_1 = (rcx_16 - rdx_9);
180051b9f                  
180051bb3                  if (count_1 > (var_2e0_3 - rdx_9))
180051bb3                  {
180051be8                      int32_t var_358_5;
180051be8                      var_358_5 = 0;
180051bfe                      sub_180016780(&var_2f8, count_1, 0, count_1, var_358_5);
180051bb3                  }
180051bb3                  else
180051bb3                  {
180051bb5                      var_2e8_3 = rcx_16;
180051bbd                      int32_t* rbx_3 = &var_2f8;
180051bbd                      
180051bc9                      if (var_2e0_3 > 0xf)
180051bc9                          rbx_3 = var_2f8;
180051bc9                      
180051bd2                      void* rbx_4 = ((char*)rbx_3 + rdx_9);
180051bdd                      memset(rbx_4, 0, count_1);
180051be2                      *(uint8_t*)(count_1 + rbx_4) = 0;
180051bb3                  }
180051b72              }
180051b72              else
180051b72              {
180051b74                  char* rax_23 = &var_2f8;
180051b74                  
180051b85                  if (var_2e0_3 > 0xf)
180051b85                      rax_23 = var_2f8;
180051b85                  
180051b8e                  var_2e8_3 = rcx_16;
180051b96                  rax_23[rcx_16] = 0;
180051b72              }
180051b72              
180051c03              PSTR r9_4 = &var_2f8;
180051c03              
180051c14              if (var_2e0_3 > 0xf)
180051c14                  r9_4 = var_2f8;
180051c14              
180051c2c              int64_t rax_26 = __std_fs_convert_wide_to_narrow(0xfde9, r15_2, r14_2, r9_4, rax_21);
180051c2c              
180051c3a              if (((int32_t)(rax_26 >> 0x20)) != 0)
180051c3a              {
18005280a                  sub_180037270(((int32_t)(rax_26 >> 0x20)));
18005280a                  /* no return */
180051c3a              }
180051c3a              
180051c40              rax_20 = var_2e0_3;
180051c48              r8_7 = var_2e8_3;
180051b2a          }
180051b2a          
180051c50          wchar16* rdx_12 = &var_2f8;
180051c50          
180051c5c          if (rax_20 > 0xf)
180051c5c              rdx_12 = var_2f8;
180051c5c          
180051c68          sub_180015f00(rax_19, rdx_12, r8_7);
180051c68          
180051c7a          if (var_2e0_3 > 0xf)
180051c7a          {
180051c7f              void* rcx_21 = var_2f8;
180051c87              void* rax_28 = rcx_21;
180051c87              
180051c91              if ((var_2e0_3 + 1) >= 0x1000)
180051c91              {
180051c97                  rcx_21 = *(uint64_t*)((char*)rcx_21 - 8);
180051c97                  
180051ca6                  if ((((char*)rax_28 - rcx_21) - 8) > 0x1f)
180051ca6                  {
180051ca8                      _invalid_parameter_noinfo_noreturn();
180051ca8                      /* no return */
180051ca6                  }
180051c91              }
180051c91              
180051caf              sub_1802d3e7c(rcx_21);
180051c7a          }
180051c7a          
180051cb4          int64_t var_2e8_4 = 0;
180051cbc          int64_t var_2e0_4 = 0xf;
180051cc8          var_2f8 = 0;
180051a2f      label_180051a2f:
180051a2f          HoYo::Common::Logger::~Logger(&var_2b8);
180051a35      label_180051a35:
180051a35          result = 0;
180051a42          __security_check_cookie((rax_1 ^ &var_378));
180051a63          return result;
180051aa1      }
180051aa1      
180051cdc      if (var_2d0 > 0x80000)
180051cdc      {
180051d17          class HoYo::Common::LogStream* rax_32 = HoYo::Common::LogStream::operator<<(HoYo::Common::Logger::Logger(&var_2b8, "D:\jenkins_home\workspace\plat-l…", 0x2e, "HoYo::Base::Details::ConfigFileL…", 4), "File too large:");
180051d20          int64_t* r15_3 = arg2;
180051d20          
180051d28          if (arg2[3] > 7)
180051d2a              r15_3 = *(uint64_t*)arg2;
180051d2a          
180051d2d          int64_t r14_3 = arg2[2];
180051d34          var_2f8 = {0};
180051d3c          wchar16* r8_12 = nullptr;
180051d3f          wchar16* var_2e8_5 = nullptr;
180051d47          int64_t rax_33 = 0xf;
180051d4c          int64_t var_2e0_5 = 0xf;
180051d54          var_2f8 = 0;
180051d5c          int32_t var_348_3 = 0x20;
180051d5c          
180051d67          if (r14_3 != 0)
180051d67          {
180051d74              if (r14_3 > 0x7fffffff)
180051d74              {
180052813                  sub_180037230(0x16);
180052813                  /* no return */
180051d74              }
180051d74              
180051d8d              int64_t rax_34 = __std_fs_convert_wide_to_narrow(0xfde9, r15_3, r14_3, nullptr, 0);
180051d8d              
180051d9b              if (((int32_t)(rax_34 >> 0x20)) != 0)
180051d9b              {
18005281f                  sub_180037270(((int32_t)(rax_34 >> 0x20)));
18005281f                  /* no return */
180051d9b              }
180051d9b              
180051da1              int64_t rcx_24 = ((int64_t)rax_34);
180051da4              wchar16* rdx_16 = var_2e8_5;
180051da4              
180051daf              if (rcx_24 > rdx_16)
180051daf              {
180051ddc                  uint64_t count_2 = (rcx_24 - rdx_16);
180051ddc                  
180051df0                  if (count_2 > (var_2e0_5 - rdx_16))
180051df0                  {
180051e25                      int32_t var_358_8;
180051e25                      var_358_8 = 0;
180051e3b                      sub_180016780(&var_2f8, count_2, 0, count_2, var_358_8);
180051df0                  }
180051df0                  else
180051df0                  {
180051df2                      var_2e8_5 = rcx_24;
180051dfa                      int32_t* rbx_5 = &var_2f8;
180051dfa                      
180051e06                      if (var_2e0_5 > 0xf)
180051e06                          rbx_5 = var_2f8;
180051e06                      
180051e0f                      void* rbx_6 = ((char*)rbx_5 + rdx_16);
180051e1a                      memset(rbx_6, 0, count_2);
180051e1f                      *(uint8_t*)(count_2 + rbx_6) = 0;
180051df0                  }
180051daf              }
180051daf              else
180051daf              {
180051db1                  char* rax_36 = &var_2f8;
180051db1                  
180051dc2                  if (var_2e0_5 > 0xf)
180051dc2                      rax_36 = var_2f8;
180051dc2                  
180051dcb                  var_2e8_5 = rcx_24;
180051dd3                  rax_36[rcx_24] = 0;
180051daf              }
180051daf              
180051e40              PSTR r9_6 = &var_2f8;
180051e40              
180051e51              if (var_2e0_5 > 0xf)
180051e51                  r9_6 = var_2f8;
180051e51              
180051e69              int64_t rax_39 = __std_fs_convert_wide_to_narrow(0xfde9, r15_3, r14_3, r9_6, rax_34);
180051e69              
180051e77              if (((int32_t)(rax_39 >> 0x20)) != 0)
180051e77              {
180052829                  sub_180037270(((int32_t)(rax_39 >> 0x20)));
180052829                  /* no return */
180051e77              }
180051e77              
180051e7d              rax_33 = var_2e0_5;
180051e85              r8_12 = var_2e8_5;
180051d67          }
180051d67          
180051e8d          wchar16* rdx_19 = &var_2f8;
180051e8d          
180051e99          if (rax_33 > 0xf)
180051e99              rdx_19 = var_2f8;
180051e99          
180051ea5          sub_180015f00(rax_32, rdx_19, r8_12);
180051ea5          
180051eb7          if (var_2e0_5 > 0xf)
180051eb7          {
180051ebc              void* rcx_29 = var_2f8;
180051ec4              void* rax_41 = rcx_29;
180051ec4              
180051ece              if ((var_2e0_5 + 1) >= 0x1000)
180051ece              {
180051ed4                  rcx_29 = *(uint64_t*)((char*)rcx_29 - 8);
180051ed4                  
180051ee3                  if ((((char*)rax_41 - rcx_29) - 8) > 0x1f)
180051ee3                  {
180051ee5                      _invalid_parameter_noinfo_noreturn();
180051ee5                      /* no return */
180051ee3                  }
180051ece              }
180051ece              
180051eec              sub_1802d3e7c(rcx_29);
180051eb7          }
180051eb7          
180051ef1          int64_t var_2e8_6 = 0;
180051ef9          int64_t var_2e0_6 = 0xf;
180051f05          var_2f8 = 0;
180051d67          goto label_180051a2f;
180051cdc      }
180051cdc      
180051f15      int128_t s;
180051f15      __builtin_memset(&s, 0, 0x18);
180051f27      void* rax_46;
180051f27      
180051f27      if (var_2d0 < 0x1000)
180051f27      {
180051f58          rax_46 = operator new(var_2d0);
180051f5d      label_180051f5d:
180051f5d          s = rax_46;
180051f62          void* rbx_7 = ((char*)rax_46 + var_2d0);
180051f73          memset(rax_46, 0, var_2d0);
180051f78          *(uint64_t*)((char*)s)[8] = rbx_7;
180051f84          var_2b8 = &data_1803146d0;
180051f94          void var_208;
180051f94          std::basic_ios<char,struct std::char_traits<char> >::basic_ios<char,struct std::char_traits<char> >(&var_208);
180051f9b          int32_t var_348_4 = 0x40;
180051fb9          void** const _Strbuf;
180051fb9          std::basic_istream<char,struct std::char_traits<char> >::basic_istream<char,struct std::char_traits<char> >(&var_2b8, &_Strbuf, 0);
180051fd3          *(uint64_t*)(&var_2b8 + ((int64_t)*(uint32_t*)((char*)var_2b8 + 4))) = &data_1803146c8;
180051fe3          int64_t rcx_37 = ((int64_t)*(uint32_t*)((char*)var_2b8 + 4));
180051fed          void var_2bc;
180051fed          *(uint32_t*)(&var_2bc + rcx_37) = ((int32_t)(rcx_37 - 0xb0));
180051ffc          std::basic_streambuf<char,struct std::char_traits<char> >::basic_streambuf<char,struct std::char_traits<char> >();
180052009          _Strbuf = &data_180314648;
180052011          char var_22c_1 = 0;
180052019          char var_237_1 = 0;
180052029          std::basic_streambuf<char,struct std::char_traits<char> >::_Init();
18005202f          int64_t var_228_1 = 0;
18005203e          int64_t var_234_1 = data_1803d1ce0;
180052046          int64_t var_240_1 = 0;
180052063          sub_180050c80(&var_2b8, arg2, 0x21, 0x40);
180052071          void var_178;
180052071          
180052071          if (var_228_1 == 0)
180052071          {
1800520ac              class HoYo::Common::LogStream* rax_51 = HoYo::Common::LogStream::operator<<(HoYo::Common::Logger::Logger(&var_178, "D:\jenkins_home\workspace\plat-l…", 0x3a, "HoYo::Base::Details::ConfigFileL…", 4), "Failed to open file:");
1800520b5              int64_t* r15_4 = arg2;
1800520b5              
1800520bd              if (arg2[3] > 7)
1800520bf                  r15_4 = *(uint64_t*)arg2;
1800520bf              
1800520c2              int64_t r14_4 = arg2[2];
1800520c9              var_2f8 = {0};
1800520d1              wchar16* r8_18 = nullptr;
1800520d4              wchar16* var_2e8_7 = nullptr;
1800520dc              int64_t rax_52 = 0xf;
1800520e1              int64_t var_2e0_7 = 0xf;
1800520e9              var_2f8 = 0;
1800520f1              int32_t var_348_5 = 0x140;
1800520f1              
1800520fc              if (r14_4 != 0)
1800520fc              {
180052109                  if (r14_4 > 0x7fffffff)
180052109                  {
180052838                      sub_180037230(0x16);
180052838                      /* no return */
180052109                  }
180052109                  
180052122                  int64_t rax_53 = __std_fs_convert_wide_to_narrow(0xfde9, r15_4, r14_4, nullptr, 0);
180052122                  
180052130                  if (((int32_t)(rax_53 >> 0x20)) != 0)
180052130                  {
180052843                      sub_180037270(((int32_t)(rax_53 >> 0x20)));
180052843                      /* no return */
180052130                  }
180052130                  
180052136                  int64_t rcx_41 = ((int64_t)rax_53);
180052139                  wchar16* rdx_26 = var_2e8_7;
180052139                  
180052144                  if (rcx_41 > rdx_26)
180052144                  {
180052171                      uint64_t count_3 = (rcx_41 - rdx_26);
180052171                      
180052185                      if (count_3 > (var_2e0_7 - rdx_26))
180052185                      {
1800521c1                          int32_t var_358_11;
1800521c1                          var_358_11 = 0;
1800521d7                          sub_180016780(&var_2f8, count_3, 0, count_3, var_358_11);
180052185                      }
180052185                      else
180052185                      {
180052187                          var_2e8_7 = rcx_41;
18005218f                          int32_t* rbx_8 = &var_2f8;
18005218f                          
18005219b                          if (var_2e0_7 > 0xf)
18005219b                              rbx_8 = var_2f8;
18005219b                          
1800521a4                          void* rbx_9 = ((char*)rbx_8 + rdx_26);
1800521af                          memset(rbx_9, 0, count_3);
1800521b4                          *(uint8_t*)((char*)rbx_9 + count_3) = 0;
180052185                      }
180052144                  }
180052144                  else
180052144                  {
180052146                      int32_t* rax_55 = &var_2f8;
180052146                      
180052157                      if (var_2e0_7 > 0xf)
180052157                          rax_55 = var_2f8;
180052157                      
180052160                      var_2e8_7 = rcx_41;
180052168                      *(uint8_t*)(rcx_41 + rax_55) = 0;
180052144                  }
180052144                  
1800521dc                  PSTR r9_8 = &var_2f8;
1800521dc                  
1800521ed                  if (var_2e0_7 > 0xf)
1800521ed                      r9_8 = var_2f8;
1800521ed                  
180052205                  int64_t rax_58 = __std_fs_convert_wide_to_narrow(0xfde9, r15_4, r14_4, r9_8, rax_53);
180052205                  
180052213                  if (((int32_t)(rax_58 >> 0x20)) != 0)
180052213                  {
18005284c                      sub_180037270(((int32_t)(rax_58 >> 0x20)));
18005284c                      /* no return */
180052213                  }
180052213                  
180052219                  rax_52 = var_2e0_7;
180052221                  r8_18 = var_2e8_7;
1800520fc              }
1800520fc              
180052229              wchar16* rdx_29 = &var_2f8;
180052229              
180052235              if (rax_52 > 0xf)
180052235                  rdx_29 = var_2f8;
180052235              
180052241              sub_180015f00(rax_51, rdx_29, r8_18);
180052241              
180052253              if (var_2e0_7 > 0xf)
180052253              {
180052258                  void* rcx_46 = var_2f8;
180052260                  void* rax_60 = rcx_46;
180052260                  
18005226a                  if ((var_2e0_7 + 1) >= 0x1000)
18005226a                  {
180052270                      rcx_46 = *(uint64_t*)((char*)rcx_46 - 8);
180052270                      
18005227f                      if ((((char*)rax_60 - rcx_46) - 8) > 0x1f)
18005227f                      {
180052281                          _invalid_parameter_noinfo_noreturn();
180052281                          /* no return */
18005227f                      }
18005226a                  }
18005226a                  
180052288                  sub_1802d3e7c(rcx_46);
180052253              }
180052253              
18005228d              int64_t var_2e8_8 = 0;
180052295              int64_t var_2e0_8 = 0xf;
1800522a1              var_2f8 = 0;
1800522b1              HoYo::Common::Logger::~Logger(&var_178);
1800522c4              *(uint64_t*)(&var_2b8 + ((int64_t)*(uint32_t*)((char*)var_2b8 + 4))) = &data_1803146c8;
1800522d4              int64_t rcx_49 = ((int64_t)*(uint32_t*)((char*)var_2b8 + 4));
1800522de              *(uint32_t*)(&var_2bc + rcx_49) = ((int32_t)(rcx_49 - 0xb0));
1800522ed              sub_180051340(&_Strbuf);
1800522fa              std::basic_istream<char,struct std::char_traits<char> >::~basic_istream<char,struct std::char_traits<char> >();
180052308              std::basic_ios<char,struct std::char_traits<char> >::~basic_ios<char,struct std::char_traits<char> >(&var_208);
18005230f              void* rcx_52 = s;
18005230f              
180052317              if (rcx_52 != 0)
180052317              {
180052321                  void* rax_65 = rcx_52;
180052321                  
18005232b                  if (((char*)rbx_7 - rcx_52) >= 0x1000)
18005232b                  {
180052331                      rcx_52 = *(uint64_t*)((char*)rcx_52 - 8);
180052331                      
180052340                      if ((((char*)rax_65 - rcx_52) - 8) > 0x1f)
180052340                      {
180052342                          _invalid_parameter_noinfo_noreturn();
180052342                          /* no return */
180052340                      }
18005232b                  }
18005232b                  
180052349                  sub_1802d3e7c(rcx_52);
180052351                  __builtin_memset(&s, 0, 0x18);
180052317              }
180052317              
18005235c              result = 0;
180051a42              __security_check_cookie((rax_1 ^ &var_378));
180051a63              return result;
180052071          }
180052071          
180052373          std::basic_istream<char,struct std::char_traits<char> >::read(&var_2b8, s, var_2d0);
180052386          *(uint64_t*)(&var_2b8 + ((int64_t)*(uint32_t*)((char*)var_2b8 + 4))) = &data_1803146c8;
180052396          int64_t rcx_55 = ((int64_t)*(uint32_t*)((char*)var_2b8 + 4));
1800523a0          *(uint32_t*)(&var_2bc + rcx_55) = ((int32_t)(rcx_55 - 0xb0));
1800523af          sub_180051340(&_Strbuf);
1800523bc          std::basic_istream<char,struct std::char_traits<char> >::~basic_istream<char,struct std::char_traits<char> >();
1800523ca          std::basic_ios<char,struct std::char_traits<char> >::~basic_ios<char,struct std::char_traits<char> >(&var_208);
1800523ec          int64_t* s_1 = sub_180083340(&var_2f8, &s, &data_1803c51c0, &data_1803c51a0);
180001390  int64_t sub_180001390()

180001390  {
180001399      void* rax = operator new(0x30);
1800013a5      data_1803c51c0 = rax;
1800013ac      data_1803c51d0 = 0x2c;
1800013b7      data_1803c51d8 = 0x2f;
1800013c2      __builtin_strncpy(rax, "1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8T", 0x20);
1800013d8      *(uint64_t*)((char*)rax + 0x20) = 0x4e44496941372f53;
1800013e3      __builtin_strncpy(((char*)rax + 0x28), "yTA=", 5);
1800013f5      /* tailcall */
1800013f5      return atexit(sub_18030d7c0);
180001390  }

免费评分

参与人数 3威望 +1 吾爱币 +22 热心值 +3 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
beihai1314 + 1 + 1 我很赞同!
janlili + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

janlili 发表于 2025-3-18 09:43
感谢分享
jcgycl 发表于 2025-3-18 11:01
cattie 发表于 2025-3-18 16:34
楼主你好,关于最后的反汇编代码部分,建议你直接使用三点进行包裹,md插件会自动确定语言的;
不要指定PseudoC之类无法解析的语言,这样可能导致代码块高亮异常。
 楼主| VisionTravel 发表于 2025-3-18 17:11
cattie 发表于 2025-3-18 16:34
楼主你好,关于最后的反汇编代码部分,建议你直接使用三点进行包裹,md插件会自动确定语言的;
不要指定Ps ...

好的,感谢指导!
bolin8 发表于 2025-3-20 22:18
厉害啊,感谢分享,学到了
 楼主| VisionTravel 发表于 2025-3-26 01:08
本帖最后由 VisionTravel 于 2025-3-29 00:26 编辑

完善了一下解密代码:
[JavaScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
 
const keyBase64 = '1qck4mmSyJ+YQ10PKzdZ6+J6AuvUAR8TS/7AiIDNyTA=';
const key = Buffer.from(keyBase64, 'base64');
 
class EncryptionHelper {
  static aesDecrypt(encryptedData, iv) {
    const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
    decipher.setAutoPadding(true);
    let decrypted = decipher.update(encryptedData);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted;
  }
}
 
async function main() {
  const destFileName = 'app.conf.dat';
  let appDir = 'D:\\Game\\XXX Launcher';
   
  const versionDir = findVersionDirectory(appDir);
  if (!versionDir) {
    console.error('未找到有效版本目录');
    return;
  }
   
  const filePath = path.join(versionDir, destFileName);
 
  try {
 
    // 读取原始文件
    const buffer = fs.readFileSync(filePath);
    const originalIv = buffer.subarray(256, 272);  // 提取原始IV
    const encryptedData = buffer.subarray(272);    // 加密数据部分
 
    // 解密数据
    const decryptedBuffer = EncryptionHelper.aesDecrypt(encryptedData, originalIv);
    const decryptedStr = decryptedBuffer.toString('utf8');
    console.log(`解密数据: ${decryptedStr}`);
 
  } catch (err) {
    console.error('操作失败:', err.message);
  }
}
 
function findVersionDirectory(baseDir) {
  const dirs = fs.readdirSync(baseDir, { withFileTypes: true })
    .filter(d => d.isDirectory())
    .map(d => path.join(baseDir, d.name))
    .find(dir => /^\d+(\.\d+)+$/.test(path.basename(dir)));
  return dirs;
}
 
main().catch(console.error);

如果需要知道逆向的过程,请回复这个帖子告诉我,谢谢!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-3-29 05:22

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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