internal ulong FindCodeRegistrationUsingMscorlib() { //Works only on >=24.2 var searchBytes = Encoding.ASCII.GetBytes("mscorlib.dll\0"); var mscorlibs = _pe.raw.Search(searchBytes).Select(idx => _pe.MapRawAddressToVirtual(idx)); var usagesOfMscorlib = FindAllMappedWords(mscorlibs); //CodeGenModule address will be in here var codeGenModulesStructAddr = FindAllMappedWords(usagesOfMscorlib); //CodeGenModules list address will be in here var endOfCodeGenRegAddr = FindAllMappedWords(codeGenModulesStructAddr); //The end of the CodeRegistration object will be in here. if (!_pe.is32Bit) { var codeGenAddr = endOfCodeGenRegAddr.First(); 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 allSensibleInstructions = allInstructions.Where(i => i.Mnemonic == Mnemonic.Lea && i.OpCount == 2 && i.Op0Kind == OpKind.Register && i.Op1Kind == OpKind.Memory && i.Op0Register == Register.RCX).ToList(); var sanity = 0; while (sanity++ < 500) { var instruction = allSensibleInstructions.FirstOrDefault(i => i.GetRipBasedInstructionMemoryAddress() == codeGenAddr ); if (instruction != default) { return(codeGenAddr); } codeGenAddr -= 8; //Always 64-bit here so IntPtr is 8 } return(0); } else { IEnumerable <ulong>?codeRegVas = null; var sanity = 0; while ((codeRegVas?.Count() ?? 0) != 1) { if (sanity++ > 500) { break; } endOfCodeGenRegAddr = endOfCodeGenRegAddr.Select(va => va - 4); codeRegVas = FindAllMappedWords(endOfCodeGenRegAddr); } if (endOfCodeGenRegAddr.Count() != 1) { return(0ul); } return(endOfCodeGenRegAddr.First()); } }
internal ulong FindCodeRegistrationUsingMscorlib() { //Works only on >=24.2 var searchBytes = Encoding.ASCII.GetBytes("mscorlib.dll\0"); var mscorlibs = _pe.raw.Search(searchBytes).Select(idx => _pe.MapRawAddressToVirtual(idx)); var pMscorlibCodegenModule = FindAllMappedWords(mscorlibs); //CodeGenModule address will be in here var pMscorlibCodegenEntryInCodegenModulesList = FindAllMappedWords(pMscorlibCodegenModule); //CodeGenModules list address will be in here IEnumerable <ulong>?pCodegenModules = null; if (!(LibCpp2IlMain.MetadataVersion >= 27f)) { //Pre-v27, mscorlib is the first codegen module, so *MscorlibCodegenEntryInCodegenModulesList == g_CodegenModules, so we can just find a pointer to this. var intermediate = pMscorlibCodegenEntryInCodegenModulesList; pCodegenModules = FindAllMappedWords(intermediate); } else { //but in v27 it's close to the LAST codegen module (winrt.dll is an exception), so we need to work back until we find an xref. var sanityCheckNumberOfModules = 200; var pSomewhereInCodegenModules = pMscorlibCodegenEntryInCodegenModulesList; var ptrSize = (_pe.is32Bit ? 4u : 8u); for (var backtrack = 0; backtrack < sanityCheckNumberOfModules && (pCodegenModules?.Count() ?? 0) != 1; backtrack++) { pCodegenModules = FindAllMappedWords(pSomewhereInCodegenModules); //Sanity check the count, which is one pointer back if (pCodegenModules.Count() == 1) { var moduleCount = _pe.ReadClassAtVirtualAddress <int>(pCodegenModules.First() - ptrSize); if (moduleCount < 0 || moduleCount > sanityCheckNumberOfModules) { pCodegenModules = Enumerable.Empty <ulong>(); } } pSomewhereInCodegenModules = pSomewhereInCodegenModules.Select(va => va - ptrSize); } if (!pCodegenModules.Any()) { throw new Exception("Failed to find pCodegenModules"); } if (pCodegenModules.Count() > 1) { throw new Exception("Found more than 1 pointer as pCodegenModules"); } } if (!_pe.is32Bit) { var codeGenAddr = pCodegenModules.First(); 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 allSensibleInstructions = allInstructions.Where(i => i.Mnemonic == Mnemonic.Lea && i.OpCount == 2 && i.Op0Kind == OpKind.Register && i.Op1Kind == OpKind.Memory /*&& i.Op0Register == Register.RCX*/).ToList(); var sanity = 0; while (sanity++ < 500) { var instruction = allSensibleInstructions.FirstOrDefault(i => i.GetRipBasedInstructionMemoryAddress() == codeGenAddr ); if (instruction != default) { return(codeGenAddr); } codeGenAddr -= 8; //Always 64-bit here so IntPtr is 8 } return(0); } else { IEnumerable <ulong>?codeRegVas = null; var sanity = 0; while ((codeRegVas?.Count() ?? 0) != 1) { if (sanity++ > 500) { break; } pCodegenModules = pCodegenModules.Select(va => va - 4); codeRegVas = FindAllMappedWords(pCodegenModules).AsParallel().ToList(); } if (pCodegenModules.Count() != 1) { return(0ul); } return(pCodegenModules.First()); } }