IL2CPP: Fix off-by-1 pointer error in non-PE x86/64 files (#123)

This commit is contained in:
Katy Coe
2021-01-11 19:13:09 +01:00
parent 87e6ea47e7
commit 52f477698e
2 changed files with 21 additions and 7 deletions

View File

@@ -60,9 +60,9 @@ namespace Il2CppInspector
public List<Il2CppGenericInst> GenericInstances => Binary.GenericInstances; public List<Il2CppGenericInst> GenericInstances => Binary.GenericInstances;
public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules; public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules;
public ulong[] CustomAttributeGenerators { get; } public ulong[] CustomAttributeGenerators { get; }
public ulong[] MethodInvokePointers => Binary.MethodInvokePointers; public ulong[] MethodInvokePointers { get; }
public Il2CppMethodSpec[] MethodSpecs => Binary.MethodSpecs; public Il2CppMethodSpec[] MethodSpecs => Binary.MethodSpecs;
public Dictionary<Il2CppMethodSpec, ulong> GenericMethodPointers => Binary.GenericMethodPointers; public Dictionary<Il2CppMethodSpec, ulong> GenericMethodPointers { get; }
public Dictionary<Il2CppMethodSpec, int> GenericMethodInvokerIndices => Binary.GenericMethodInvokerIndices; public Dictionary<Il2CppMethodSpec, int> GenericMethodInvokerIndices => Binary.GenericMethodInvokerIndices;
// TODO: Finish all file access in the constructor and eliminate the need for this // TODO: Finish all file access in the constructor and eliminate the need for this
@@ -218,6 +218,14 @@ namespace Il2CppInspector
return null; return null;
} }
// Thumb instruction pointers have the bottom bit set to signify a switch from ARM to Thumb when jumping
private ulong getDecodedAddress(ulong addr) {
if (BinaryImage.Arch != "ARM" && BinaryImage.Arch != "ARM64")
return addr;
return addr & 0xffff_ffff_ffff_fffe;
}
public Il2CppInspector(Il2CppBinary binary, Metadata metadata) { public Il2CppInspector(Il2CppBinary binary, Metadata metadata) {
// Store stream representations // Store stream representations
Binary = binary; Binary = binary;
@@ -277,11 +285,16 @@ namespace Il2CppInspector
} }
} }
// Decode addresses for Thumb etc. without altering the Il2CppBinary structure data
CustomAttributeGenerators = CustomAttributeGenerators.Select(a => getDecodedAddress(a)).ToArray();
MethodInvokePointers = Binary.MethodInvokePointers.Select(a => getDecodedAddress(a)).ToArray();
GenericMethodPointers = Binary.GenericMethodPointers.ToDictionary(a => a.Key, a => getDecodedAddress(a.Value));
// Get sorted list of function pointers from all sources // Get sorted list of function pointers from all sources
// TODO: This does not include IL2CPP API functions // TODO: This does not include IL2CPP API functions
var sortedFunctionPointers = (Version <= 24.1)? var sortedFunctionPointers = (Version <= 24.1)?
Binary.GlobalMethodPointers.ToList() : Binary.GlobalMethodPointers.Select(a => getDecodedAddress(a)).ToList() :
Binary.ModuleMethodPointers.SelectMany(module => module.Value).ToList(); Binary.ModuleMethodPointers.SelectMany(module => module.Value).Select(a => getDecodedAddress(a)).ToList();
sortedFunctionPointers.AddRange(CustomAttributeGenerators); sortedFunctionPointers.AddRange(CustomAttributeGenerators);
sortedFunctionPointers.AddRange(MethodInvokePointers); sortedFunctionPointers.AddRange(MethodInvokePointers);
@@ -354,13 +367,14 @@ namespace Il2CppInspector
// Consider the end of the method to be the start of the next method (or zero) // Consider the end of the method to be the start of the next method (or zero)
// The last method end will be wrong but there is no way to calculate it // The last method end will be wrong but there is no way to calculate it
return (start & 0xffff_ffff_ffff_fffe, FunctionAddresses[start]); start = getDecodedAddress(start);
return (start, FunctionAddresses[start]);
} }
// Get a concrete generic method pointer if available // Get a concrete generic method pointer if available
public (ulong Start, ulong End)? GetGenericMethodPointer(Il2CppMethodSpec spec) { public (ulong Start, ulong End)? GetGenericMethodPointer(Il2CppMethodSpec spec) {
if (GenericMethodPointers.TryGetValue(spec, out var start)) { if (GenericMethodPointers.TryGetValue(spec, out var start)) {
return (start & 0xffff_ffff_ffff_fffe, FunctionAddresses[start]); return (start, FunctionAddresses[start]);
} }
return null; return null;
} }

View File

@@ -47,7 +47,7 @@ namespace Il2CppInspector.Reflection
ParameterTypes = exampleMethod.DeclaredParameters.Select(p => mapParameterType(model, p.ParameterType)).ToArray(); ParameterTypes = exampleMethod.DeclaredParameters.Select(p => mapParameterType(model, p.ParameterType)).ToArray();
var start = Package.MethodInvokePointers[Index]; var start = Package.MethodInvokePointers[Index];
VirtualAddress = (start & 0xffff_ffff_ffff_fffe, Package.FunctionAddresses[start]); VirtualAddress = (start, Package.FunctionAddresses[start]);
} }
// The invokers use Object for all reference types, and SByte for booleans // The invokers use Object for all reference types, and SByte for booleans