public void AddEntry(CopiedProcessModule processModule) { var exports = processModule.Image.Exports; if (exports == null) { return; } foreach (var export in exports.Entries) { var exportDirectory = processModule.ImageFileOnDisk.OptionalHeader.DataDirectories[OptionalHeader.ExportDirectoryIndex]; // forwarded exports can f**k off for now // TODO: fix this garbage if (export.Address.Rva >= exportDirectory.VirtualAddress && export.Address.Rva < exportDirectory.VirtualAddress + exportDirectory.Size) { continue; } var entry = new ExportEntry { Module = processModule, Symbol = export }; ReverseExports[$"{processModule.ModuleName}.{export.Name}"] = entry; Exports[IntPtr.Add(processModule.BaseAddress, (int)export.Address.Rva)] = entry; } }
public List <HookAnalysisResult> AnalyzeModule(ProcessAnalyzer analyzer, CopiedProcessModule module) { var results = new List <HookAnalysisResult>(); foreach (var importThunk in module.Image.Imports) { foreach (var symbol in importThunk.Symbols.Where(s => s.IsImportByName)) { if (!analyzer.EMapper.TryGetEntry(importThunk.Name, symbol.Name, out var expected)) { continue; } var expectedAbs = (ulong)expected.Module.BaseAddress.ToInt64() + expected.Symbol.Address.Rva; if (symbol.Address != expectedAbs) { results.Add(new HookAnalysisResult($"{importThunk.Name}!{symbol.Name}", "IAT") { ModuleName = module.ModuleName, OriginalData = expectedAbs.ToString("X8"), PatchedData = symbol.Address.ToString("X8"), AdditionalInfo = "" }); } } } return(results); }
public List <HookAnalysisResult> AnalyzeModule(ProcessAnalyzer analyzer, CopiedProcessModule module) { var results = new List <HookAnalysisResult>(); if (module.Image.Exports == null || module.ImageOnDisk.Exports == null) { return(results); } for (int i = 0; i < module.Image.Exports.Entries.Count; i++) { var export = module.Image.Exports.Entries[i]; if (module.ImageOnDisk.Exports.Entries.Count <= i) { break; } var exportOnDisk = module.ImageOnDisk.Exports.Entries[i]; if (exportOnDisk.Address.Rva != export.Address.Rva) { results.Add(new HookAnalysisResult($"{export.Name}", "EAT") { ModuleName = module.ModuleName, OriginalData = $"[RVA] - {exportOnDisk.Address.Rva:X8}", PatchedData = $"[RVA] - {export.Address.Rva:X8}", AdditionalInfo = "" }); } } return(results); }
public void AddEntry(CopiedProcessModule processModule) { var exports = processModule.Image.Exports; if (exports == null) { return; } foreach (var export in exports.Entries) { var entry = new ExportEntry { Module = processModule, Symbol = export }; ReverseExports[$"{processModule.ModuleName}!{export.Name}"] = entry; Exports[IntPtr.Add(processModule.BaseAddress, (int)export.Address.Rva)] = entry; } }
public List <HookAnalysisResult> AnalyzeModule(ProcessAnalyzer analyzer, CopiedProcessModule module) { var results = new List <HookAnalysisResult>(); foreach (var section in module.ImageFile.Sections) { if (section.IsMemoryWrite || !section.IsMemoryExecute) { continue; } var onDiskSection = module.ImageFileOnDisk.GetSectionContainingRva(section.Rva); if (onDiskSection.GetPhysicalSize() == 0) { continue; } var inMemoryData = (DataSegment)((VirtualSegment)section.Contents).PhysicalContents; var onDiskData = (DataSegment)((VirtualSegment)onDiskSection.Contents).PhysicalContents; //this is a ghetto reloc fix but whatever var toSkip = new Dictionary <uint, uint>(); foreach (var reloc in module.Image.Relocations) { toSkip[reloc.Location.Rva] = (reloc.Type == AsmResolver.PE.Relocations.RelocationType.Dir64 ? 8U : 4U); } //this is an even more ghetto fix for IAT entries in readonly places foreach (var import in module.Image.Imports) { var dataReader = module.ImageFile.CreateReaderAtRva(import.AddressRva); uint c = 0; while (dataReader.ReadNativeInt(module.Image.PEKind == OptionalHeaderMagic.Pe32) != 0) { var offs = module.Image.PEKind == OptionalHeaderMagic.Pe32 ? 4U : 8U; toSkip[import.AddressRva + c] = offs; c += offs; } } //isolate rvas we want toSkip = toSkip.Where(v => section.ContainsRva(v.Key)).ToDictionary(kvp => kvp.Key - section.Rva, kvp => kvp.Value); //these datatypes make me want to kill myself lol var diffList = new List <Tuple <uint, List <Tuple <byte, byte> > > >(); Tuple <uint, List <Tuple <byte, byte> > > currDiff = null; int tolerance = 0; for (uint i = 0; i < section.GetPhysicalSize();) { //skip delta if (toSkip.TryGetValue(i, out var j)) { // handle overlapping cases while (j != 0) { i++; j--; if (toSkip.TryGetValue(i, out var k)) { j = Math.Max(j, k); } } continue; } if (onDiskData.Data[i] != inMemoryData.Data[i]) { tolerance = 4; if (currDiff == null || currDiff.Item2.Count == 0) { currDiff = Tuple.Create(i, new List <Tuple <byte, byte> >()); } currDiff.Item2.Add(Tuple.Create(onDiskData.Data[i], inMemoryData.Data[i])); } else if (--tolerance < 0) { if (currDiff != null && currDiff.Item2.Count != 0) { diffList.Add(currDiff); currDiff = null; } } else { currDiff.Item2.Add(Tuple.Create(onDiskData.Data[i], inMemoryData.Data[i])); } if (tolerance < 0) { tolerance = 0; } i++; } if (currDiff != null && currDiff.Item2.Count != 0) { diffList.Add(currDiff); } foreach (var diffEntry in diffList) { var originalSb = new StringBuilder(); var modifiedSb = new StringBuilder(); for (int i = 0; i < diffEntry.Item2.Count; i++) { var b = diffEntry.Item2[i]; if (i != 0) { originalSb.Append(' '); modifiedSb.Append(' '); } originalSb.Append(b.Item1.ToString("X2")); modifiedSb.Append(b.Item2.ToString("X2")); } var addr = module.BaseAddress.ToInt64() + section.Rva + diffEntry.Item1; //todo: improve this trash ass logic var closestExport = analyzer.EMapper.Exports .Where(kvp => kvp.Key.ToInt64() <= addr) .OrderByDescending(kvp => kvp.Key.ToInt64()) .FirstOrDefault(); if (closestExport.Key == IntPtr.Zero) { results.Add(new HookAnalysisResult($"{(addr):X8} ({section.Name}!0x{diffEntry.Item1:X})", "Inline") { ModuleName = module.ModuleName, OriginalData = originalSb.ToString(), PatchedData = modifiedSb.ToString(), AdditionalInfo = "" }); } else { var val = closestExport.Value; var k = addr - closestExport.Key.ToInt64(); results.Add(new HookAnalysisResult($"{(addr):X8} ({val.Module.ModuleName}!{val.Symbol.Name}+0x{k:X})", "Inline") { ModuleName = module.ModuleName, OriginalData = originalSb.ToString(), PatchedData = modifiedSb.ToString(), AdditionalInfo = "" }); } } } return(results); }