首页
社区
课程
招聘
[原创]纯静态解决遇到的各类global-metadata加密问题
发表于: 2025-12-10 23:35 12690

[原创]纯静态解决遇到的各类global-metadata加密问题

2025-12-10 23:35
12690

在通过Il2cppdumper工具尝试dump unity游戏的sdk时,经常会碰到一些加密的global-metadata.dat,导致无法成功dump。

搜索网上的文章或工具个人感觉最好用两种分别是。

1.动态dump解密后的metadata。

2.利用il2cpp_api(未混淆)动态dump CS文件。

本文总共4个例子,有能用以上办法解决的,也有不能用以上方法解决的,全都是纯静态解决,按照从易到难的顺序。

既然要解密,肯定要先了解加密的位置在哪里。

通过github能下载到2020年的unity源码,找到MetadataCache.cpp中的il2cpp::vm::MetadataCache::Initialize函数,而这里也是大多数metadata解密的位置。

因考虑篇幅问题,一部分的代码都只会截取一部分。

观看源码可以知道,我们可以利用global-metadata.dat或Metadata字符串去索引到具体的函数实现。而大多数的加密操作一般都在这两个函数。

让我们正式开始第一个案例吧!

先通过Metadata字符串索引到LoadMetadataFile函数。

如果是十分熟悉这两个函数的师傅,一眼就可以知道这个函数里没有进行解密操作,接着索引到Initialize函数

if ( v4 )后的伪代码已经是将metadata的结构头和一些值填入到内存中了,按理说应该在sub_35FC404读取metadata后进行解密操作。

既然没找到,那就查看一下metadata的数据。

如果有观察了解过metadata结构头,或是对数字比较敏感的师傅,一眼就能看出来,这个metadata的加密十分规律。

拿一个正常的结构头,会更加直观,因为metadata存储的多是各个参数的偏移和数量,因此很少有数据大于0xffffff(小端序)

因此通过观察03 07 0b 0f等偏移,可以观察出一定的加减规律。

再细致可以观察出这个规律是呈16一轮,这是我们在观察0x100这个偏移,这里存储的是关于windows相关的数据,apk是用不到的,因此多是不变的。

因此我们只需要提取0x100的十六个字节,并且对偏移0x8的数据异或0x1,即可得到一个异或表。

随便找一个ai写一个脚本即可

可以看到我们得到了一个很干净的metadata,只需要把头部修复一下即可。

第二个案例,我在so中无法搜索到metadata相关的字符串,查看assets资源文件,发现文件路径名和文件名都被修改成无意义命名。

但好在LoadMetadataFile函数中还有一个ERROR: Could not open %s 字符串

找到函数后,发现路径名字被改为gloxinia,再向上索引,发现解密函数操作

我们再向上索引,成功找到我们的Initialize函数,我的metadata名字叫做feast_plaint_knight

拉进010查看,这个metadata初看大概也是一个循环异或的规律。

但老是写解密脚本显然不是我这种懒狗的思路。这里当然要使用出我们的顶级解密工具Unidbg!

动态dump的原理除了识别metadata特征就是hook读取metadata返回的指针。

通过把unidbg模拟执行,不用传入任何参数,只需要配置一下globla-metadata.dat的路径读取问题即可。

来到第三个案例,查看metadata

加快节奏,直接来到so中观察加密函数

可以看到函数把global-metadata.dat字符串解密后,读取再解密的过程。

其实就是加密了结构头和两个metadata的区段,stringLiteralDataOffset和stringOffset。

通过unidbg,这次我们断在v24 = *(v10 + 100);解密完后将两个区段dump出来,这里就不详细讲诉了,一样的操作

我们来观察dump下来的结构头。

惊奇的发现,不仅顺序被打乱,还被塞入很多无用数据。

读过源码可以知道,这里填入的有s_GlobalMetadataHeader的一些结构头数据,但是观察偏移0xf8 0xc0明显是不对的,它映照的是打乱顺序后的结构头。

因此我们无法通过解密后的metadata进行sdkdump,还需要修复s_GlobalMetadataHeader。

哪如何快速的修复我们的s_GlobalMetadataHeader呢,我想到的第一个方法是通过拿一份同版本的未魔改的so文件,再索引进行比较。

我们通过010模板拿到我们的结构头

在ida中对s_GlobalMetadataHeader进行填入

这里我未详细修改,将后面的字符串删除即可。

但是我们身为一个懒狗,将近60个数据,一个个去寻找,并且可能还有遗漏,显然不是我们的风格。

我们拿案例1解密后的metadata来观看,可以发现除了头部特征字节和末尾没用的字节,其余字节都是紧凑相连的。

例如

stringLiteralOffset+stringLiteralCount==stringLiteralDataOffset

0x100+0x39458==0x39558

我们只需要开头stringLiteralOffset和stringLiteralCount的数据就可以推算出全部的数据。

因为我们拥有所有正确的结构头,通过遍历stringLiteralDataOffset+打乱结构头数组[i]==打乱结构头数组[j]以此类推。

最后这个例子还有一个小坑

在读取后还需要加0x1e4才是真正的数值

修复后:

直接查看so

最后一个例子就是加强版的3号例子,加密了7个区块,且观察这两行代码,dest指向的就是metadata指针。

3号例子是统一的0x1e4,而这个例子,是不同的加减数,让我们无法利用上面那个方法计算。

但是通过观察发现,这个加减数大多都在0x50以内。

因此我们可以添加一个区间值

stringLiteralOffset+stringLiteralCount ±0x50 ≈≈stringLiteralDataOffset

但这样有一个隐患,可能出现两个或多个值,这里我使用的方法是了解每个结构体中各个值的意义,这样把每个值都添加一边跳转过去查看。

修复后:

如果写得不好,请轻喷,代码基本让ai都能编写出来,就没贴出来了。如果师傅们有更好的方法请多多分享让我学习一下!!!

bool il2cpp::vm::MetadataCache::Initialize()
{
    s_GlobalMetadata = vm::MetadataLoader::LoadMetadataFile("global-metadata.dat");
    if (!s_GlobalMetadata)
        return false;
 
    s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)s_GlobalMetadata;
    IL2CPP_ASSERT(s_GlobalMetadataHeader->sanity == 0xFAB11BAF);
    IL2CPP_ASSERT(s_GlobalMetadataHeader->version == 24);
bool il2cpp::vm::MetadataCache::Initialize()
{
    s_GlobalMetadata = vm::MetadataLoader::LoadMetadataFile("global-metadata.dat");
    if (!s_GlobalMetadata)
        return false;
 
    s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)s_GlobalMetadata;
    IL2CPP_ASSERT(s_GlobalMetadataHeader->sanity == 0xFAB11BAF);
    IL2CPP_ASSERT(s_GlobalMetadataHeader->version == 24);
void* il2cpp::vm::MetadataLoader::LoadMetadataFile(const char* fileName)
{
    std::string resourcesDirectory = utils::PathUtils::Combine(utils::Runtime::GetDataDir(), utils::StringView<char>("Metadata"));
 
    std::string resourceFilePath = utils::PathUtils::Combine(resourcesDirectory, utils::StringView<char>(fileName, strlen(fileName)));
void* il2cpp::vm::MetadataLoader::LoadMetadataFile(const char* fileName)
{
    std::string resourcesDirectory = utils::PathUtils::Combine(utils::Runtime::GetDataDir(), utils::StringView<char>("Metadata"));
 
    std::string resourceFilePath = utils::PathUtils::Combine(resourcesDirectory, utils::StringView<char>(fileName, strlen(fileName)));
__int64 __fastcall sub_35FC404(
  sub_361107C(&a11);
  a9 = "Metadata";
  a10 = 8;
  v19 = a11 >> 1;
  if ( (a11 & 1) != 0 )
    v20 = a13;
  else
    v20 = &a11 + 1;
  if ( (a11 & 1) != 0 )
    v19 = a12;
  a17 = v20;
  a18 = v19;
  sub_35A26B0(&a14, &a17, &a9);
  if ( (a11 & 1) != 0 )
    operator delete(a13);
  v21 = strlen(a1);
  if ( (a14 & 1) != 0 )
    v22 = a16;
  else
    v22 = &a14 + 1;
  if ( (a14 & 1) != 0 )
    v23 = a15;
  else
    v23 = a14 >> 1;
  a9 = a1;
  a10 = v21;
  a17 = v22;
  a18 = v23;
  sub_35A26B0(&a11, &a17, &a9);
  LODWORD(a17) = 0;
  v24 = sub_35B18B0(&a11, 3, 1, 1, 0, &a17);
  if ( a17 )
  {
    if ( (a11 & 1) != 0 )
      v25 = a13;
    else
      v25 = &a11 + 1;
    sub_35B31F4("ERROR: Could not open %s", v25);
  }
  else
  {
    v26 = v24;
    v27 = sub_35B3380();
    sub_35B1AF0(v26, &a17);
    if ( !a17 )
      goto LABEL_22;
    sub_35B3390(v27);
  }
  v27 = 0;
LABEL_22:
  if ( (a11 & 1) != 0 )
    operator delete(a13);
  if ( (a14 & 1) != 0 )
    operator delete(a16);
  return v27;
}
__int64 __fastcall sub_35FC404(
  sub_361107C(&a11);
  a9 = "Metadata";
  a10 = 8;
  v19 = a11 >> 1;
  if ( (a11 & 1) != 0 )
    v20 = a13;
  else
    v20 = &a11 + 1;
  if ( (a11 & 1) != 0 )
    v19 = a12;
  a17 = v20;
  a18 = v19;
  sub_35A26B0(&a14, &a17, &a9);
  if ( (a11 & 1) != 0 )
    operator delete(a13);
  v21 = strlen(a1);
  if ( (a14 & 1) != 0 )
    v22 = a16;
  else
    v22 = &a14 + 1;
  if ( (a14 & 1) != 0 )
    v23 = a15;
  else
    v23 = a14 >> 1;
  a9 = a1;
  a10 = v21;
  a17 = v22;
  a18 = v23;
  sub_35A26B0(&a11, &a17, &a9);
  LODWORD(a17) = 0;
  v24 = sub_35B18B0(&a11, 3, 1, 1, 0, &a17);
  if ( a17 )
  {
    if ( (a11 & 1) != 0 )
      v25 = a13;
    else
      v25 = &a11 + 1;
    sub_35B31F4("ERROR: Could not open %s", v25);
  }
  else
  {
    v26 = v24;
    v27 = sub_35B3380();
    sub_35B1AF0(v26, &a17);
    if ( !a17 )
      goto LABEL_22;
    sub_35B3390(v27);
  }
  v27 = 0;
LABEL_22:
  if ( (a11 & 1) != 0 )
    operator delete(a13);
  if ( (a14 & 1) != 0 )
    operator delete(a16);
  return v27;
}
bool __fastcall sub_35D25D8(_DWORD *a1, int *a2)
  v4 = (sub_35FC404)("global-metadata.dat");
  v5 = v4;
  unk_873B968 = v4;
  if ( v4 )
  {
    unk_873B970 = v4;
    v6 = *(v4 + 172);
    *a1 = v6 / 0x28;
    unk_873B978 = v6 / 0x28;
    *a2 = *(v4 + 180) >> 6;
    unk_873B980 = (sub_35B3354)((v6 / 0x28), 24);
    unk_873B988 = (sub_35B3354)(*(unk_873B960 + 48LL), 8);
    unk_873B990 = (sub_35B3354)(*(unk_873B970 + 164LL) / 0x58uLL, 8);
    unk_873B950 = (sub_35B3354)(*(unk_873B970 + 52LL) / 0x24uLL, 8);
}
bool __fastcall sub_35D25D8(_DWORD *a1, int *a2)
  v4 = (sub_35FC404)("global-metadata.dat");
  v5 = v4;
  unk_873B968 = v4;
  if ( v4 )
  {
    unk_873B970 = v4;
    v6 = *(v4 + 172);
    *a1 = v6 / 0x28;
    unk_873B978 = v6 / 0x28;
    *a2 = *(v4 + 180) >> 6;
    unk_873B980 = (sub_35B3354)((v6 / 0x28), 24);
    unk_873B988 = (sub_35B3354)(*(unk_873B960 + 48LL), 8);
    unk_873B990 = (sub_35B3354)(*(unk_873B970 + 164LL) / 0x58uLL, 8);
    unk_873B950 = (sub_35B3354)(*(unk_873B970 + 52LL) / 0x24uLL, 8);
}
def decrypt_metadata(encrypted_file_path, output_file_path):
    with open(encrypted_file_path, 'rb') as f:
        encrypted_data = f.read()
 
    # 初始化密钥表
    key_table = [0x70,0x2c,0xe8,0xa4,0x60,0x1c,0xd8,0x94,0x51,0x0c,0xc8,0x84,0x40,0xfc,0xb8,0x74]
    key_table[8] ^=0x1
    decrypted_data = bytearray()
 
    for i in range(len(encrypted_data)):
        # 使用当前密钥表位置进行异或
        key_index = i % 16
        temp = encrypted_data[i] ^ key_table[key_index]
 
        # 重要:将解密后的数据写回密钥表
        key_table[key_index] = (key_table[key_index] - 0x40) & 0xFF
 
        decrypted_data.append(temp)
 
    with open(output_file_path, 'wb') as f:
        f.write(decrypted_data)
 
 
# 使用示例
decrypt_metadata('global-metadata.dat', 'global-metadata-decrypted.dat')
def decrypt_metadata(encrypted_file_path, output_file_path):
    with open(encrypted_file_path, 'rb') as f:
        encrypted_data = f.read()
 
    # 初始化密钥表
    key_table = [0x70,0x2c,0xe8,0xa4,0x60,0x1c,0xd8,0x94,0x51,0x0c,0xc8,0x84,0x40,0xfc,0xb8,0x74]
    key_table[8] ^=0x1
    decrypted_data = bytearray()
 
    for i in range(len(encrypted_data)):
        # 使用当前密钥表位置进行异或
        key_index = i % 16
        temp = encrypted_data[i] ^ key_table[key_index]
 
        # 重要:将解密后的数据写回密钥表
        key_table[key_index] = (key_table[key_index] - 0x40) & 0xFF
 
        decrypted_data.append(temp)
 
    with open(output_file_path, 'wb') as f:
        f.write(decrypted_data)
 
 
# 使用示例
decrypt_metadata('global-metadata.dat', 'global-metadata-decrypted.dat')
__int64 __fastcall sub_12C6E34(const char *a1)
{
  sub_12E2F9C(v14);
  v12 = "gloxinia";
  v13 = 8;
  v2 = LOBYTE(v14[0]) >> 1;
  if ( (v14[0] & 1) != 0 )
    v3 = v15;
  else
    v3 = v14 + 1;
  if ( (v14[0] & 1) != 0 )
    v2 = v14[1];
  v18 = v3;
  v19 = v2;
  sub_122C950(v16, &v18, &v12);
  if ( (v14[0] & 1) != 0 )
    operator delete(v15);
  v4 = strlen(a1);
  if ( (v16[0] & 1) != 0 )
    v5 = v17;
  else
    v5 = v16 + 1;
  if ( (v16[0] & 1) != 0 )
    v6 = v16[1];
  else
    v6 = LOBYTE(v16[0]) >> 1;
  v12 = a1;
  v13 = v4;
  v18 = v5;
  v19 = v6;
  sub_122C950(v14, &v18, &v12);
  LODWORD(v18) = 0;
  v7 = sub_12E1F00(v14, 3, 1, 1, 0, &v18);
  if ( v18 )
  {
    if ( (v14[0] & 1) != 0 )
      v8 = v15;
    else
      v8 = v14 + 1;
    sub_12F631C("ERROR: Could not open %s", v8);
  }
  else
  {
    v9 = v7;
    v10 = sub_12F64F4();
    sub_12E2140(v9, &v18);
    if ( !v18 )
      goto LABEL_22;
    sub_12F6504(v10);
  }
  v10 = 0;
LABEL_22:
  if ( (v14[0] & 1) != 0 )
    operator delete(v15);
  if ( (v16[0] & 1) != 0 )
    operator delete(v17);
  return v10;
}
__int64 __fastcall sub_12C6E34(const char *a1)
{
  sub_12E2F9C(v14);
  v12 = "gloxinia";
  v13 = 8;
  v2 = LOBYTE(v14[0]) >> 1;
  if ( (v14[0] & 1) != 0 )
    v3 = v15;
  else
    v3 = v14 + 1;
  if ( (v14[0] & 1) != 0 )
    v2 = v14[1];
  v18 = v3;
  v19 = v2;
  sub_122C950(v16, &v18, &v12);
  if ( (v14[0] & 1) != 0 )
    operator delete(v15);
  v4 = strlen(a1);
  if ( (v16[0] & 1) != 0 )
    v5 = v17;
  else
    v5 = v16 + 1;
  if ( (v16[0] & 1) != 0 )
    v6 = v16[1];
  else
    v6 = LOBYTE(v16[0]) >> 1;
  v12 = a1;
  v13 = v4;
  v18 = v5;
  v19 = v6;
  sub_122C950(v14, &v18, &v12);
  LODWORD(v18) = 0;
  v7 = sub_12E1F00(v14, 3, 1, 1, 0, &v18);
  if ( v18 )
  {
    if ( (v14[0] & 1) != 0 )
      v8 = v15;
    else
      v8 = v14 + 1;
    sub_12F631C("ERROR: Could not open %s", v8);
  }
  else
  {
    v9 = v7;
    v10 = sub_12F64F4();
    sub_12E2140(v9, &v18);
    if ( !v18 )
      goto LABEL_22;
    sub_12F6504(v10);
  }
  v10 = 0;
LABEL_22:
  if ( (v14[0] & 1) != 0 )
    operator delete(v15);
  if ( (v16[0] & 1) != 0 )
    operator delete(v17);
  return v10;
}
__int64 __fastcall sub_12C6D60(const char *a1)
{
  result = sub_12C6E34(a1);
  if ( result )
  {
    v2 = result;
    v3 = sub_12F64A0();
    v4 = sub_12F647C(1, v3);
    v7 = v4;
    if ( v4 )
    {
      memcpy(v4, v2, v3);
      v8 = &v7;
      *(sub_1277C3C(&qword_2CE6568, &v7, &unk_A414F3, &v8, &v6) + 40) = v2;
      LODWORD(v8) = 0;
      v5 = 0;
      v6 = 0;
      sub_12C6FDC(v7, 256, &v8, &v6, &v5);
      sub_12C6FDC(v7, (v7[63] + v7[62]), &v8, &v6, &v5);
      return v7;
    }
    else
    {
      sub_12F631C("ERROR: Could not malloc %ld", v3);
      return 0;
    }
  }
  return result;
}
__int64 __fastcall sub_12C6D60(const char *a1)
{
  result = sub_12C6E34(a1);
  if ( result )
  {
    v2 = result;
    v3 = sub_12F64A0();
    v4 = sub_12F647C(1, v3);
    v7 = v4;
    if ( v4 )
    {
      memcpy(v4, v2, v3);
      v8 = &v7;
      *(sub_1277C3C(&qword_2CE6568, &v7, &unk_A414F3, &v8, &v6) + 40) = v2;
      LODWORD(v8) = 0;
      v5 = 0;
      v6 = 0;
      sub_12C6FDC(v7, 256, &v8, &v6, &v5);
      sub_12C6FDC(v7, (v7[63] + v7[62]), &v8, &v6, &v5);
      return v7;
    }
    else
    {
      sub_12F631C("ERROR: Could not malloc %ld", v3);
      return 0;
    }
  }
  return result;
}
bool __fastcall sub_12645CC(_DWORD *a1, int *a2)
{
  v4 = sub_12C6D60("feast_plaint_knight");
  v5 = v4;
  qword_2CE58C0 = v4;
  if ( v4 )
  {
    qword_2CE58C8 = v4;
    v6 = *(v4 + 172);
    *a1 = v6 / 0x28;
    dword_2CE58D0 = v6 / 0x28;
    *a2 = *(v4 + 180) >> 6;
    qword_2CE58D8 = sub_12F647C((v6 / 0x28), 24);
    qword_2CE58E0 = sub_12F647C(*(qword_2CE58B8 + 48), 8);
    qword_2CE58E8 = sub_12F647C(*(qword_2CE58C8 + 164) / 0x58uLL, 8);
    qword_2CE58A8 = sub_12F647C(*(qword_2CE58C8 + 52) / 0x24uLL, 8);
    v7 = sub_12F647C(*(qword_2CE58B8 + 64), 8);
}
bool __fastcall sub_12645CC(_DWORD *a1, int *a2)
{
  v4 = sub_12C6D60("feast_plaint_knight");
  v5 = v4;
  qword_2CE58C0 = v4;
  if ( v4 )
  {
    qword_2CE58C8 = v4;
    v6 = *(v4 + 172);
    *a1 = v6 / 0x28;
    dword_2CE58D0 = v6 / 0x28;
    *a2 = *(v4 + 180) >> 6;
    qword_2CE58D8 = sub_12F647C((v6 / 0x28), 24);
    qword_2CE58E0 = sub_12F647C(*(qword_2CE58B8 + 48), 8);
    qword_2CE58E8 = sub_12F647C(*(qword_2CE58C8 + 164) / 0x58uLL, 8);
    qword_2CE58A8 = sub_12F647C(*(qword_2CE58C8 + 52) / 0x24uLL, 8);
    v7 = sub_12F647C(*(qword_2CE58B8 + 64), 8);
}
public class Decryptor extends AbstractJni {
 
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;
 
    public Decryptor() {
        // 创建模拟器
        emulator = AndroidEmulatorBuilder.for64Bit().build();
        Memory memory = emulator.getMemory();
 
        memory.setLibraryResolver(new AndroidResolver(23)); // Android 8.0
 
        // 创建虚拟机
        vm = emulator.createDalvikVM();
        vm.setJni(this);
        vm.setVerbose(true);
 
        // 加载目标so文件
        File lib = new File("unidbg-android/src/test/resources/libil2cpp.so"); // 替换为实际路径
        module = vm.loadLibrary(lib, false).getModule();
    }
 
    public void decryptGlobalMetadata() {
        try {
            // 获取目标函数地址
            long funcAddr = 0x12645CC;
            System.out.println("目标函数地址: 0x" + Long.toHexString(funcAddr));
 
            emulator.attach().addBreakPoint(module, 0x, new BreakPointCallback() {
                @Override
               public boolean onHit(Emulator<?> emulator, long address) {
                    try {
                    // 读取后的地址添加一个断点,dump出来即可,可让ai直接写
                    return true;
                }
          });
            Number result = module.callFunction(emulator, funcAddr);
            System.out.println("函数执行结果: " + result);
 
        } catch (Exception e) {
            e.printStackTrace();
 
        }
    }
public class Decryptor extends AbstractJni {
 
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;
 
    public Decryptor() {
        // 创建模拟器
        emulator = AndroidEmulatorBuilder.for64Bit().build();
        Memory memory = emulator.getMemory();
 
        memory.setLibraryResolver(new AndroidResolver(23)); // Android 8.0
 
        // 创建虚拟机
        vm = emulator.createDalvikVM();
        vm.setJni(this);
        vm.setVerbose(true);
 
        // 加载目标so文件
        File lib = new File("unidbg-android/src/test/resources/libil2cpp.so"); // 替换为实际路径
        module = vm.loadLibrary(lib, false).getModule();
    }
 
    public void decryptGlobalMetadata() {
        try {
            // 获取目标函数地址

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 52
支持
分享
最新回复 (24)
雪    币: 7
活跃值: (100)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不错
2025-12-11 02:28
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2025-12-11 10:51
0
雪    币: 132
活跃值: (6447)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
案例3像以前解决的一款海外游戏,对峙2
2025-12-11 11:18
0
雪    币: 379
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
学习
2025-12-11 11:29
0
雪    币: 104
活跃值: (7270)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
tql
2025-12-11 14:51
0
雪    币: 865
活跃值: (3143)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
tql
2025-12-11 23:33
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
tql
2025-12-13 21:27
0
雪    币: 8273
活跃值: (4833)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2025-12-15 14:41
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
哥 四个样本分别是啥 我想动手试试
2025-12-15 19:04
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11

哥 我真的好想学 你看到了能发下样本的名字吗

2025-12-15 19:24
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12

大佬们 这个游戏是bao ke meng da ji jie是tprt加固

然后

我去hook这俩地址 用的是大佬的unidbg代码

下方是我的代码


打印结果是



然后我查看了这个地址的值

为啥会这样

我很蒙 看不懂


求帮助 我想知道具体是怎么打印这个

大佬的0x我是改过的 发现0x它报错 希望大佬能讲讲


球球大佬了



2025-12-15 22:09
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
   public boolean onHit(Emulator<?> emulator, long address) {
                    try {
                    // 读取后的地址添加一个断点,dump出来即可,可让ai直接写
                    return true;
                }
          });哥 这里的代码能发过来吗
2025-12-15 23:03
0
雪    币: 67
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
感谢分享
2025-12-19 00:16
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
哥 你还在吗球球了
2025-12-23 14:49
0
雪    币: 223
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
学习
2025-12-23 22:05
0
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
mb_vhwdzyqo 大佬们 这个游戏是bao ke meng da ji jie是tprt加固然后我去hook这俩地址 用的是大佬的unidbg代码下方是我的代码打印结果是然后我查看了这个地址的值为啥会这样我很蒙 看不懂 ...
用frida + 物理机去dump,直接就是解密后的文件
2025-12-25 10:25
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
感谢大佬分享
2025-12-25 16:32
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
666
2025-12-26 07:12
0
雪    币: 234
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
666
2025-12-26 10:12
0
雪    币: 2579
活跃值: (3876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
感谢大佬分享
2025-12-29 13:47
0
雪    币: 115
活跃值: (1203)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
666
2025-12-30 14:44
0
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
5555
2025-12-31 17:06
0
雪    币: 4089
活跃值: (3822)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
一直没有解决的问题。看看这里能不能学到。
5天前
0
雪    币: 0
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
感谢分享
2天前
0
游客
登录 | 注册 方可回帖
返回