diff --git a/Cpp2IL/Extensions.cs b/Cpp2IL/Extensions.cs index ed65f56b..68d3f095 100644 --- a/Cpp2IL/Extensions.cs +++ b/Cpp2IL/Extensions.cs @@ -9,7 +9,6 @@ namespace Cpp2IL { public static class Extensions { - public static bool IsImmediate(this OpKind opKind) => opKind >= OpKind.Immediate8 && opKind <= OpKind.Immediate32to64; public static T[] SubArray(this T[] data, int index, int length) { var result = new T[length]; diff --git a/LibCpp2IL/Extensions.cs b/LibCpp2IL/Extensions.cs index 4e41f588..3982a2ba 100644 --- a/LibCpp2IL/Extensions.cs +++ b/LibCpp2IL/Extensions.cs @@ -7,6 +7,7 @@ namespace LibCpp2IL { public static class Extensions { + public static bool IsImmediate(this OpKind opKind) => opKind >= OpKind.Immediate8 && opKind <= OpKind.Immediate32to64; public static ulong GetRipBasedInstructionMemoryAddress(this Instruction instruction) => instruction.NextIP + instruction.MemoryDisplacement64; public static T[] SubArray(this T[] data, int index, int length) diff --git a/LibCpp2IL/PE/PE.cs b/LibCpp2IL/PE/PE.cs index 747eb881..b97d4ef9 100644 --- a/LibCpp2IL/PE/PE.cs +++ b/LibCpp2IL/PE/PE.cs @@ -329,7 +329,7 @@ public bool PlusSearch(int methodCount, int typeDefinitionsCount) } } - ulong codeRegistration; + ulong codeRegistration = 0; ulong metadataRegistration; Console.WriteLine("Attempting to locate code and metadata registration functions..."); @@ -353,11 +353,24 @@ public bool PlusSearch(int methodCount, int typeDefinitionsCount) plusSearch.SetExecSections(imageBase, dataSections); metadataRegistration = plusSearch.FindMetadataRegistration64Bit(); } - - if (LibCpp2IlMain.MetadataVersion >= 24.2f) - codeRegistration = plusSearch.FindCodeRegistrationUsingMscorlib(); - else - codeRegistration = is32Bit ? plusSearch.FindCodeRegistration() : plusSearch.FindCodeRegistration64Bit(); + + if (is32Bit && metadataRegistration != 0) + { + codeRegistration = plusSearch.TryFindCodeRegUsingMetaReg(metadataRegistration); + } + + if (codeRegistration == 0) + { + if (LibCpp2IlMain.MetadataVersion >= 24.2f) + { + Console.WriteLine("\tUsing mscorlib full-disassembly approach to get codereg, this may take a while..."); + codeRegistration = plusSearch.FindCodeRegistrationUsingMscorlib(); + } + else + codeRegistration = is32Bit ? plusSearch.FindCodeRegistration() : plusSearch.FindCodeRegistration64Bit(); + } + + #if ALLOW_CODEREG_FALLBACK if (codeRegistration == 0 || metadataRegistration == 0) diff --git a/LibCpp2IL/PlusSearch.cs b/LibCpp2IL/PlusSearch.cs index 760aaf1a..88388b7d 100644 --- a/LibCpp2IL/PlusSearch.cs +++ b/LibCpp2IL/PlusSearch.cs @@ -151,6 +151,25 @@ private IEnumerable FindAllMappedWords(ulong va) // Find all valid virtual address pointers to a set of virtual addresses private IEnumerable FindAllMappedWords(IEnumerable va) => va.SelectMany(FindAllMappedWords); + public ulong TryFindCodeRegUsingMetaReg(ulong metadataRegistration) + { + var textSection = _pe.sections.First(s => s.Name == ".text"); + var toDisasm = _pe.raw.SubArray((int) textSection.PointerToRawData, (int) textSection.SizeOfRawData); + var allInstructions = LibCpp2ILUtils.DisassembleBytesNew(_pe.is32Bit, toDisasm, textSection.VirtualAddress + _pe.imageBase); + + var pushMetaReg = allInstructions.FirstOrDefault(i => i.Mnemonic == Mnemonic.Push && i.Op0Kind.IsImmediate() && i.GetImmediate(0) == metadataRegistration); + if (pushMetaReg.Mnemonic == Mnemonic.Push) //Check non-default. + { + var idx = allInstructions.IndexOf(pushMetaReg); + //Code reg has to be pushed after meta reg, cause that's how functions are called on 32-bit stdcall. + var hopefullyPushCodeReg = allInstructions[idx + 1]; + if (hopefullyPushCodeReg.Mnemonic == Mnemonic.Push && hopefullyPushCodeReg.Op0Kind.IsImmediate()) + return hopefullyPushCodeReg.GetImmediate(0); + } + + return 0; + } + internal ulong FindCodeRegistrationUsingMscorlib() { //Works only on >=24.2 @@ -197,7 +216,7 @@ internal ulong FindCodeRegistrationUsingMscorlib() if (sanity++ > 500) break; endOfCodeGenRegAddr = endOfCodeGenRegAddr.Select(va => va - 4); - codeRegVas = FindAllMappedWords(endOfCodeGenRegAddr); + codeRegVas = FindAllMappedWords(endOfCodeGenRegAddr).AsParallel().ToList(); } if (endOfCodeGenRegAddr.Count() != 1) @@ -206,7 +225,7 @@ internal ulong FindCodeRegistrationUsingMscorlib() return endOfCodeGenRegAddr.First(); } } - + private ulong FindCodeRegistration64BitPost2019() { //NOTE: With 64-bit ELF binaries we should iterate on exec, on everything else data.