-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathFarlight.hpp
191 lines (161 loc) · 6.14 KB
/
Farlight.hpp
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Updated by Silentninjabee
// Farlight 84 HiBuddy version 16 September 2024
#pragma once
#include "GameProfile.hpp"
// Farlight
// UE 4.25
class FarlightProfile : public IGameProfile
{
public:
FarlightProfile() = default;
std::vector<std::string> GetAppIDs() const override
{
return { "com.farlightgames.farlight84.iosglobal" };
}
MemoryFileInfo GetExecutableInfo() const override
{
return KittyMemory::getMemoryFileInfo("SolarlandClient");
}
bool IsUsingFNamePool() const override
{
return true;
}
uintptr_t GetGUObjectArrayPtr() const override
{
// https://github.com/MJx0/iOS_UE4Dumper/issues/23#issue-1988107342
std::string ida_pattern = "2A 7D ? 13 ? ? ? 12 08 01 09 4B 29 ? ? ? 1F 20 03 D5 29 ? ? ? 29 ? ? F8";
const int step = 0xC;
auto text_seg = GetExecutableInfo().getSegment("__TEXT");
uintptr_t insn_address = KittyScanner::findIdaPatternFirst(text_seg.start, text_seg.end, ida_pattern);
if (insn_address == 0)
return 0;
insn_address += step;
int64 adrp_pc_rel = 0;
int32 ldr_imm12 = 0;
const int page_size = 4096;
const uintptr_t page_off = (insn_address & ~(page_size - 1));
uint32 adrp_insn = vm_rpm_ptr<uint32>((void *)(insn_address));
uint32 ldr_insn = vm_rpm_ptr<uint32>((void *)(insn_address + 8));
if (adrp_insn == 0 || ldr_insn == 0)
return 0;
if (!KittyArm64::decode_adr_imm(adrp_insn, &adrp_pc_rel) || adrp_pc_rel == 0)
return 0;
if (!KittyArm64::decode_ldrstr_uimm(ldr_insn, &ldr_imm12))
return 0;
return (page_off + adrp_pc_rel + ldr_imm12) - GetOffsets()->FUObjectArray.ObjObjects;
}
uintptr_t GetNamesPtr() const override
{
// FNameEntry const* FName::GetEntry(FNameEntryId id);
std::string ida_pattern = "F6 57 BD A9 F4 4F 01 A9 FD 7B 02 A9 FD 83 00 91 F3 03 00 AA ? ? ? ? A8 02 ? 39";
const int step = 0x1C;
auto text_seg = GetExecutableInfo().getSegment("__TEXT");
uintptr_t insn_address = KittyScanner::findIdaPatternFirst(text_seg.start, text_seg.end, ida_pattern);
if (insn_address == 0)
return 0;
insn_address += step;
int64 adrp_pc_rel = 0;
int32 add_imm12 = 0;
const int page_size = 4096;
const uintptr_t page_off = (insn_address & ~(page_size - 1));
uint32 adrp_insn = vm_rpm_ptr<uint32>((void *)(insn_address));
uint32 add_insn = vm_rpm_ptr<uint32>((void *)(insn_address + 4));
if (adrp_insn == 0 || add_insn == 0)
return 0;
if (!KittyArm64::decode_adr_imm(adrp_insn, &adrp_pc_rel) || adrp_pc_rel == 0)
return 0;
add_imm12 = KittyArm64::decode_addsub_imm(add_insn);
return (page_off + adrp_pc_rel + add_imm12);
}
UE_Offsets *GetOffsets() const override
{
struct
{
uint16 Stride = 2; // alignof(FNameEntry)
uint16 FNamePoolBlocks = 0xD0; // usually ios at 0xD0 and android at 0x40
uint16 FNameMaxSize = 0xff;
struct
{
uint16 Number = 4;
} FName;
struct
{ // not needed in UE4.23+
uint16 Name = 0;
} FNameEntry;
struct
{
uint16 Info = 0; // Offset to Memory filled with info about type and size of string
uint16 WideBit = 0; // Offset to bit which shows if string uses wide characters
uint16 LenBit = 6; // Offset to bit which has lenght of string
uint16 HeaderSize = 2; // Size of FNameEntry header (offset where a string begins)
} FNameEntry23;
struct
{
uint16 ObjObjects = 0x10;
} FUObjectArray;
struct
{
uint16 NumElements = 0x14;
} TUObjectArray;
struct
{
uint16 Size = 0x18;
} FUObjectItem;
struct
{
uint16 ObjectFlags = 0x8;
uint16 InternalIndex = 0xC;
uint16 ClassPrivate = 0x10;
uint16 NamePrivate = 0x18;
uint16 OuterPrivate = 0x20;
} UObject;
struct
{
uint16 Next = 0x28; // sizeof(UObject)
} UField;
struct
{
uint16 SuperStruct = 0x40; // sizeof(UField) + 2 pointers?
uint16 Children = 0x48; // UField*
uint16 ChildProperties = 0x50; // FField*
uint16 PropertiesSize = 0x58;
} UStruct;
struct
{
uint16 Names = 0x40; // usually at sizeof(UField) + sizeof(FString)
} UEnum;
struct
{
uint16 EFunctionFlags = 0xB0; // sizeof(UStruct)
uint16 NumParams = EFunctionFlags + 0x4;
uint16 ParamSize = NumParams + 0x2;
uint16 Func = EFunctionFlags + 0x28; // ue3-ue4, always +0x28 from flags location.
} UFunction;
struct
{
uint16 ClassPrivate = 0x8;
uint16 Next = 0x20;
uint16 NamePrivate = 0x28;
uint16 FlagsPrivate = 0x30;
} FField;
struct
{
uint16 ArrayDim = 0x34; // sizeof(FField)
uint16 ElementSize = 0x38;
uint16 PropertyFlags = 0x40;
uint16 Offset_Internal = 0x4C;
uint16 Size = 0x78; // sizeof(FProperty)
} FProperty;
struct
{ // not needed in UE4.25+
uint16 ArrayDim = 0;
uint16 ElementSize = 0;
uint16 PropertyFlags = 0;
uint16 Offset_Internal = 0;
uint16 Size = 0;
} UProperty;
} static profile;
static_assert(sizeof(profile) == sizeof(UE_Offsets));
return (UE_Offsets *)&profile;
}
};