首页
社区
课程
招聘
UnrealEngine GName 分析
2024-6-7 18:52 1501

UnrealEngine GName 分析

2024-6-7 18:52
1501

UnrealEngine GName 分析

IDA分析GName:

UnrealNames.cpp中找到如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static bool bNamePoolInitialized;
alignas(FNamePool) static uint8 NamePoolData[sizeof(FNamePool)];
 
// Only call this once per public FName function called
//
// Not using magic statics to run as little code as possible
static FNamePool& GetNamePool()
{
    if (bNamePoolInitialized)
    {
        return *(FNamePool*)NamePoolData;
    }
 
    FNamePool* Singleton = new (NamePoolData) FNamePool;
    bNamePoolInitialized = true;
    return *Singleton;
}
  1. UnrealEngine5.x的引擎版本中,GName以全局变量static uint8 NamePoolData的形式存在.
  2. 被定义的NamePoolData会在环境中通过FNamePool::FNamePool()初始化

我们跟随引用找到相应的FNamePool::FNamePool()函数

1
2
3
4
5
6
7
8
9
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
FNamePool::FNamePool()
{
    for (FNamePoolShardBase& Shard : ComparisonShards)
    {
        Shard.Initialize(Entries);
    }
 
#if WITH_CASE_PRESERVING_NAME
    for (FNamePoolShardBase& Shard : DisplayShards)
    {
        Shard.Initialize(Entries);
    }
#endif
 
    // Register all hardcoded names
#define REGISTER_NAME(num, name) ENameToEntry[num]
    = Store(FNameStringView(#name, FCStringAnsi::Strlen(#name)));
#include "UObject/UnrealNames.inl"
#undef REGISTER_NAME
 
    // Make reverse mapping
    LargestEnameUnstableId = 0;
    for (uint32 ENameIndex = 0;
        ENameIndex < (uint32)EName::MaxHardcodedNameIndex; ++ENameIndex)
    {
        if (ENameIndex == (uint32)NAME_None || ENameToEntry[ENameIndex])
        {
            EntryToEName.Add(ENameToEntry[ENameIndex], (EName)ENameIndex);
            LargestEnameUnstableId =
                FMath::Max(LargestEnameUnstableId,
                ENameToEntry[ENameIndex].ToUnstableInt());
        }
    }
 
    // Verify all ENames are unique
    if (NumAnsiEntries() != EntryToEName.Num())
    {
        if (FPlatformMisc::IsDebuggerPresent())
        {
            UE_DEBUG_BREAK();
        }
        else
        {
            FPlatformMisc::PromptForRemoteDebugging(false);
            FMessageDialog::Open(EAppMsgType::Ok,
                NSLOCTEXT("UnrealEd",
                "DuplicatedHardcodedName",
                "Duplicate hardcoded name"));
            FPlatformMisc::RequestExit(false);
        }
    }
}
  1. 有明显的明文字符串 DuplicatedHardcodedName于是通过IDA搜索字符串

在IDA中搜索字符串

Name Address
aDuplicatedhard 00000001439ADA30

继续跟踪反汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
if ( v336 - v2 != *(_DWORD *)(a1 + 93000) - *(_DWORD *)(a1 + 93092) )
  {
    v338 = sub_140F60170(v685, L"Duplicate hardcoded name", L"UnrealEd", L"DuplicatedHardcodedName");
    sub_141022D50(0i64, v338, 0i64);
    v339 = v686;
    if ( v686 && _InterlockedExchangeAdd(v686 + 2, 0xFFFFFFFF) == 1 )
    {
      (**(void (__fastcall ***)(volatile signed __int32 *))v339)(v339);
      if ( _InterlockedExchangeAdd(v339 + 3, 0xFFFFFFFF) == 1 )
        (*(void (__fastcall **)(volatile signed __int32 *, __int64))(*(_QWORD *)v339 + 8i64))(v339, 1i64);
    }
    sub_1410714B0(0i64);
  }
  1. 这里伪代码很明显就是与上述代码相对应的部分
  2. 可以判断出来这就是构造函数,于是在IDA中改名为void __fastcall FNamePool_FNamePool(__int64 a1)

使用IDA分析交叉引用

Direction Type Address Text
Up p sub_141055510+D1 call FNamePool_FNamePool
Down p sub_141059000+50 call FNamePool_FNamePool
Down p sub_141059110+51 call FNamePool_FNamePool
Down p sub_141059EA0+42 call FNamePool_FNamePool
Down p sub_141059F60+42 call FNamePool_FNamePool
Down p sub_14105A7D0+4E call FNamePool_FNamePool
Down p sub_14105BBC0+20 call FNamePool_FNamePool
Down p sub_14105BC60+31 call FNamePool_FNamePool
Down p sub_14105BCC0+2F call FNamePool_FNamePool
Down p sub_14105BD50+38 call FNamePool_FNamePool
Down p sub_14105BDE0+38 call FNamePool_FNamePool
Down p sub_14105BE50+38 call FNamePool_FNamePool
Down p sub_14105C1A0+47 call FNamePool_FNamePool
Down p sub_14105D4F0+82 call FNamePool_FNamePool
Down p sub_14105F090+A1 call FNamePool_FNamePool
Down p sub_14105F390+11A call FNamePool_FNamePool
Down p sub_141062740+47 call FNamePool_FNamePool
Down p sub_141062740+A8 call FNamePool_FNamePool
Down p sub_1410628E0+51 call FNamePool_FNamePool
Down p sub_1410629D0+49 call FNamePool_FNamePool
Down p sub_141062AA0+47 call FNamePool_FNamePool
Down o .pdata:0000000144CEE0AC RUNTIME_FUNCTION <rva FNamePool_FNamePool, rva algn_141058B15, \
  1. 很显然要继续分析的是第一个表项

这个函数就是完成NamePoolData初始化的函数

1
2
3
4
5
6
7
8
9
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
56
_QWORD *__fastcall sub_141055510(_QWORD *a1, __int64 a2)
{
  bool v2; // zf
  __int64 v3; // r8
  __int64 v5; // rax
  unsigned int v6; // eax
  _QWORD *result; // rax
  RTL_SRWLOCK *v8; // rax
  unsigned int v9; // ecx
  __m128i v10; // [rsp+20h] [rbp-18h] BYREF
  char v11; // [rsp+40h] [rbp+8h] BYREF
 
  v2 = *(_BYTE *)(a2 + 4) == 0;
  v3 = a2 + 6;
  v10.m128i_i64[0] = a2 + 6;
  v5 = -1i64;
  if ( v2 )
  {
    do
      ++v5;
    while ( *(_BYTE *)(v3 + v5) );
    v10.m128i_i8[12] = 0;
  }
  else
  {
    do
      ++v5;
    while ( *(_WORD *)(v3 + 2 * v5) );
    v10.m128i_i8[12] = 1;
  }
  v10.m128i_i32[2] = v5;
  if ( (unsigned int)_mm_cvtsi128_si32(_mm_srli_si128(v10, 8)) < 0x400 )
  {
    if ( byte_144A3AA64 )
    {
      v8 = &stru_144A56400;
    }
    else
    {
      FNamePool_FNamePool((__int64)&stru_144A56400);
      byte_144A3AA64 = 1;
    }
    v9 = *(_DWORD *)sub_1410624C0(v8, &v11, &v10);
    result = a1;
    *a1 = v9;
  }
  else
  {
    v10.m128i_i32[2] = 24;
    v10.m128i_i64[0] = (__int64)"ERROR_NAME_SIZE_EXCEEDED";
    v6 = sub_1410552F0("ERROR_NAME_SIZE_EXCEEDED", &v10.m128i_u64[1]);
    sub_14105F340(a1, &v10, 1i64, v6);
    return a1;
  }
  return result;
}
  1. FNamePool_FNamePool((__int64)&stru_144A56400)完成了对NamePoolData的初始化

  2. 计算0x144A56400-0x140000000=0x4A56400得到GName偏移为0x4A56400,其中0x140000000是所在模块基地址

CE分析GName

在CE中搜索字符串或特定字节数组

  1. 文本:ByteProperty

  2. 字节数组:1E 01 4E 6F 6E 65 10 03 42 79 74 65 50 72 6F 70 65 72 74 79 C0

  3. 跟踪搜到的地址297DAB20000

  4. 得到地址"DeathlyStillnessGame-Win64-Shipping.exe"+4A56410

  5. 计算0x4A56410-0x10=0x4A56400得到GName偏移为0x4A56400


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回