-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAddressTable.cpp
312 lines (265 loc) · 8.81 KB
/
AddressTable.cpp
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#include "AddressTable.h"
#include "BackendGlobalDef.h"
// Address table XML serialization logic.
void AddressTable::Xmlize(XmlIO& s)
{
// Retrieve CrySearch's major and minor version number to flush into the file.
WORD major;
WORD minor;
CrySearchGetMajorMinorVersion(&major, &minor);
const DWORD appname[] = {0x53797243, 0x63726165, 0x68}; //"CrySearch"
String appnameStr = (char*)appname;
String procName = mMemoryScanner->GetProcessName();
// Write the address table to the XML serializer.
s
(appnameStr + "Version", Format("%i.%i", major, minor))
("ProcessName", procName)
("Entries", this->mEntries)
("MemoryDissections", this->mDissections)
;
}
AddressTable::AddressTable()
{
}
AddressTable::~AddressTable()
{
}
// Removes a set of entries from the address table.
void AddressTable::Remove(const Vector<int>& entries)
{
this->mEntries.Remove(entries);
}
// Removes all address table entries from the address table.
void AddressTable::Clear()
{
this->mEntries.Clear();
}
// Finds an entry in the table.
#ifdef _WIN64
const int AddressTable::Find(const __int64 address, const CCryDataType valueType) const
{
const int count = this->mEntries.GetCount();
for (int i = 0; i < count; ++i)
{
if ((this->mEntries[i].Address == address) && this->mEntries[i].ValueType == valueType)
{
return i;
}
}
return -1;
}
#else
const int AddressTable::Find(const int address, const CCryDataType valueType) const
{
const int count = this->mEntries.GetCount();
for (int i = 0; i < count; ++i)
{
if ((this->mEntries[i].Address == address) && this->mEntries[i].ValueType == valueType)
{
return i;
}
}
return -1;
}
#endif
// Returns the amount of address table entries in the table.
const int AddressTable::GetCount() const
{
return this->mEntries.GetCount();
}
// Returns the filename that the address table will save the file to.
const String& AddressTable::GetFileName() const
{
return this->mSavedFileName;
}
// Sets the filename that the address table file will save the file to.
void AddressTable::SetFileName(const char* str)
{
this->mSavedFileName = str;
}
// Retrieves a memory dissection entry at the specified index.
MemoryDissectionEntry* const AddressTable::GetDissection(const int index)
{
return &this->mDissections[index];
}
// Gets the amount of dissection entries currently in the address table.
const int AddressTable::GetDissectionCount() const
{
return this->mDissections.GetCount();
}
// Adds a new memory dissection entry to the address table.
void AddressTable::AddDissection(const char* pFriendlyName, const SIZE_T baseAddress, const DWORD memorySize)
{
this->mDissections.Add(MemoryDissectionEntry(pFriendlyName, baseAddress, memorySize));
}
// Removes a memory dissection entry from the address table and destroys associated resources.
void AddressTable::RemoveDissection(const int index)
{
// Remove the dissection entry from the list.
this->mDissections.Remove(index);
}
// Retrieves the module base and address table entry address and constructs a UI showable representation.
const bool AddressTable::GetRelativeDisplayString(const AddressTableEntry* entry, String& outString)
{
// Retrieve the module that the address points into.
const Win32ModuleInformation* mod = mModuleManager->GetModuleFromContainedAddress(entry->Address);
// If the address did not point into a module the function should return false.
if (!mod)
{
return false;
}
// Still here, so calculate the offset.
const LONG_PTR offset = entry->Address - mod->BaseAddress;
outString = Format("%s+%lX", mModuleManager->GetModuleFilename(mod->BaseAddress), offset);
// The function succeeded, return accordingly.
return true;
}
// Adds / removes an entry in/from the address table.
#ifdef _WIN64
AddressTableEntry* AddressTable::Add(const String& description, const __int64 address, const BOOLEAN IsRelative, const CCryDataType valueType)
{
AddressTableEntry ent;
ent.Frozen = false;
ent.Description = description;
ent.Address = address;
ent.ValueType = valueType;
ent.IsRelative = IsRelative;
// Address is relative. Try to retrieve the module name.
if (IsRelative == TRUE)
{
// Retrieve the module that the address points into.
const Win32ModuleInformation* mod = mModuleManager->GetModuleFromContainedAddress(address);
// If module was found, set module name.
if (mod)
{
ent.ModuleName = mModuleManager->GetModuleFilename(mod->BaseAddress);
}
}
return &(this->mEntries.Add(ent));
}
void AddressTable::Remove(const __int64 address, const CCryDataType valueType)
{
const int count = this->mEntries.GetCount();
for (int i = 0; i < count; ++i)
{
if (this->mEntries[i].Address == address && this->mEntries[i].ValueType == valueType)
{
this->mEntries.Remove(i);
break;
}
}
}
#else
AddressTableEntry* AddressTable::Add(const String& description, const int address, const BOOLEAN IsRelative, const CCryDataType valueType)
{
AddressTableEntry ent;
ent.Frozen = false;
ent.Description = description;
ent.Address = address;
ent.ValueType = valueType;
ent.IsRelative = IsRelative;
// Address is relative. Try to retrieve the module name.
if (IsRelative == TRUE)
{
// Retrieve the module that the address points into.
const Win32ModuleInformation* mod = mModuleManager->GetModuleFromContainedAddress(address);
// If module was found, set module name.
if (mod)
{
ent.ModuleName = mModuleManager->GetModuleFilename(mod->BaseAddress);
}
}
return &(this->mEntries.Add(ent));
}
void AddressTable::Remove(const int address, const CCryDataType valueType)
{
const int count = this->mEntries.GetCount();
for (int i = 0; i < count; ++i)
{
if (this->mEntries[i].Address == address && this->mEntries[i].ValueType == valueType)
{
this->mEntries.Remove(i);
break;
}
}
}
#endif
// ---------------------------------------------------------------------------------------------
// Resolves the address table entry as single entity.
void AddressTable::ResolveEntryRelative(AddressTableEntry* const entry)
{
if (entry->IsRelative == TRUE)
{
// Resolve module base and calculate real address.
const Win32ModuleInformation* const foundMod = mModuleManager->FindModule(entry->ModuleName);
// If module was not found, for example when no process was opened, the application would crash.
// This check prevents CrySearch from crashing. A process must be opened.
if (foundMod)
{
entry->Address = foundMod->BaseAddress + entry->Address;
}
else
{
// It may be possible that saved relative entries do not resolve to a valid module upon load.
// Resaving these entries will crash the application if they are saved as relatives.
entry->IsRelative = ADDRESS_ENTRY_DANGLING;
}
}
else if (entry->IsRelative == ADDRESS_ENTRY_DANGLING)
{
// When a process is loaded after the address table was opened, the entry is dangling.
entry->IsRelative = TRUE;
this->ResolveEntryRelative(entry);
}
}
// Resolves relative address table entries to their associated module.
void AddressTable::ResolveRelativeEntries(AddressTable& at)
{
const int aCount = at.GetCount();
for (int i = 0; i < aCount; ++i)
{
// Resolve each entry seperately.
at.ResolveEntryRelative(at[i]);
}
}
// Creates an address table from a .csat XML data file.
void AddressTable::CreateAddressTableFromFile(AddressTable& at, const String& filename)
{
// Load address table from persisted file.
LoadFromXMLFile(at, filename);
at.SetFileName(filename);
// Resolve the addresses of relative entries.
AddressTable::ResolveRelativeEntries(at);
}
// Stores an in-memory address table to a .csat XML data file.
void AddressTable::SaveAddressTableToFile(AddressTable& pTable, const String& filename)
{
const int aCount = pTable.GetCount();
// Temporary vector container to hold addresses to restore when the address table is saved.
// If we don't do this, the addresses are replaced in memory.
Vector<LONG_PTR> memAddresses;
memAddresses.Reserve(aCount);
// Convert real runtime addresses of relative entries to offsets.
for (int i = 0; i < aCount; ++i)
{
AddressTableEntry* const cur = pTable[i];
// Save memory held address in temporary storage to prevent inconsistency.
memAddresses << cur->Address;
// If the address is relative it should be recalculated to the file.
if (cur->IsRelative == TRUE)
{
// Set offset from module base as address before persisting.
cur->Address = cur->Address - mModuleManager->FindModule(cur->ModuleName)->BaseAddress;
}
}
// Persist address table to file.
const DWORD appname[] = {0x53797243, 0x63726165, 0x68}; //"CrySearch"
String appnameStr = (char*)appname;
StoreAsXMLFile(pTable, appnameStr + "AddressTable", filename);
pTable.SetFileName(filename);
// Restore temporary saved addresses in memory address table.
for (int x = 0; x < aCount; ++x)
{
pTable[x]->Address = memAddresses[x];
}
}