private static byte[] DumpDotNetModule(NativeModule module, ImageLayout imageLayout, out string fileName) { try { byte[] peImageData; bool isDotNet; peImageData = PEImageHelper.DirectCopy(module, imageLayout); peImageData = PEImageHelper.ConvertImageLayout(peImageData, imageLayout, ImageLayout.File); using (PEImage peImage = new PEImage(peImageData, true)) { // 确保为有效PE文件 fileName = peImage.GetOriginalFilename() ?? ((IntPtr)module.Handle).ToString((ulong)module.Handle > uint.MaxValue ? "X16" : "X8"); isDotNet = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14].VirtualAddress != 0; if (isDotNet) { try { using (ModuleDefMD moduleDef = ModuleDefMD.Load(peImage)) { } // 再次验证是否为.NET程序集 } catch { isDotNet = false; } } } return(isDotNet ? peImageData : null); } catch { fileName = default; return(null); } }
private static void FileLayoutToMemoryLayout(ref byte[] peImageData, MetadataInfo metadataInfo) { peImageData = PEImageHelper.ConvertImageLayout(peImageData, ImageLayout.File, ImageLayout.Memory); using (PEImage peHeader = new PEImage(peImageData, ImageLayout.File, false)) { // 用于转换RVA与FOA,必须指定imageLayout参数为ImageLayout.File DotNetPEInfo peInfo; if (!(metadataInfo.TableStream is null)) { metadataInfo.TableStream.Rva = (uint)peHeader.ToRVA((FileOffset)metadataInfo.TableStream.Rva); } if (!(metadataInfo.StringHeap is null)) { metadataInfo.StringHeap.Rva = (uint)peHeader.ToRVA((FileOffset)metadataInfo.StringHeap.Rva); } if (!(metadataInfo.UserStringHeap is null)) { metadataInfo.UserStringHeap.Rva = (uint)peHeader.ToRVA((FileOffset)metadataInfo.UserStringHeap.Rva); } if (!(metadataInfo.GuidHeap is null)) { metadataInfo.GuidHeap.Rva = (uint)peHeader.ToRVA((FileOffset)metadataInfo.GuidHeap.Rva); } if (!(metadataInfo.BlobHeap is null)) { metadataInfo.BlobHeap.Rva = (uint)peHeader.ToRVA((FileOffset)metadataInfo.BlobHeap.Rva); } peInfo = metadataInfo.PEInfo; peInfo.ImageLayout = MetadataLocator.ImageLayout.Memory; peInfo.Cor20HeaderRva = (uint)peHeader.ToRVA((FileOffset)peInfo.Cor20HeaderRva); peInfo.MetadataRva = (uint)peHeader.ToRVA((FileOffset)peInfo.MetadataRva); } }
public bool DumpModule(IntPtr moduleHandle, ImageLayout imageLayout, string filePath) { try { byte[] peImageData; peImageData = PEImageHelper.DirectCopy(_process.UnsafeGetModule((void *)moduleHandle), imageLayout); peImageData = PEImageHelper.ConvertImageLayout(peImageData, imageLayout, ImageLayout.File); File.WriteAllBytes(filePath, peImageData); return(true); } catch { return(false); } }
private static byte[] DumpModule(NativeModule module, ImageLayout imageLayout, MetadataInfo metadataInfo, string imagePath) { byte[] peImageData; peImageData = PEImageHelper.DirectCopy(module, imageLayout, !(imagePath is null), imagePath); if (imageLayout == ImageLayout.File) { // 统一为内存格式,方便修复 FileLayoutToMemoryLayout(ref peImageData, metadataInfo); } FixDotNetHeaders(peImageData, metadataInfo); // 修复.NET头 peImageData = PEImageHelper.ConvertImageLayout(peImageData, ImageLayout.Memory, ImageLayout.File); // 转换回文件格式用于保存 return(peImageData); }
public bool DumpModule(IntPtr moduleHandle, ImageLayout imageLayout, string filePath) { ClrModule dacModule; InjectionClrVersion clrVersion; Injection.Options options; AntiAntiDumpService antiAntiDumpService; AntiAntiDumpInfo antiAntiDumpInfo; MetadataInfo metadataInfo; byte[] peImageData; dacModule = TryGetDacModule(moduleHandle); if (dacModule == null) { return(false); } switch (dacModule.Runtime.ClrInfo.Version.Major) { case 2: clrVersion = InjectionClrVersion.V2; break; case 4: clrVersion = InjectionClrVersion.V4; break; default: return(false); } // 判断要dump的模块的CLR版本 options = new Injection.Options { PortName = Guid.NewGuid().ToString(), ObjectName = Guid.NewGuid().ToString() }; using (NativeProcess process = NativeProcess.Open(_processId)) if (!process.InjectManaged(typeof(AntiAntiDumpService).Assembly.Location, typeof(Injection).FullName, "Main", options.Serialize(), clrVersion, out int result) || result != 0) { return(false); } antiAntiDumpService = (AntiAntiDumpService)Activator.GetObject(typeof(AntiAntiDumpService), $"Ipc://{options.PortName}/{options.ObjectName}"); // 注入DLL,通过.NET Remoting获取AntiAntiDumpService实例 antiAntiDumpInfo = antiAntiDumpService.GetAntiAntiDumpInfo(moduleHandle); if (!antiAntiDumpInfo.CanAntiAntiDump) { return(false); } imageLayout = (ImageLayout)antiAntiDumpInfo.ImageLayout; // 覆盖通过DAC获取的,不确定DAC获取的是否准确,毕竟DAC的bug还不少 metadataInfo = antiAntiDumpInfo.MetadataInfo; PrintStreamInfo("#~ or #-", metadataInfo.TableStream); PrintStreamInfo("#Strings", metadataInfo.StringHeap); PrintStreamInfo("#US", metadataInfo.UserStringHeap); PrintStreamInfo("#GUID", metadataInfo.GuidHeap); PrintStreamInfo("#Blob", metadataInfo.BlobHeap); peImageData = PEImageHelper.DirectCopy(_processId, (void *)moduleHandle, imageLayout); FixHeader(peImageData, antiAntiDumpInfo); peImageData = PEImageHelper.ConvertImageLayout(peImageData, imageLayout, ImageLayout.File); File.WriteAllBytes(filePath, peImageData); return(true); }
private void FixHeader(byte[] peImageData, AntiAntiDumpInfo antiAntiDumpInfo) { ImageLayout imageLayout; uint cor20HeaderRva; uint metadataRva; uint metadataSize; MetadataInfo metadataInfo; MetadataStreamInfo tableStreamInfo; MetadataStreamInfo stringHeapInfo; MetadataStreamInfo userStringHeapInfo; MetadataStreamInfo guidHeapInfo; MetadataStreamInfo blobHeapInfo; imageLayout = (ImageLayout)antiAntiDumpInfo.ImageLayout; cor20HeaderRva = antiAntiDumpInfo.Cor20HeaderRva; metadataRva = antiAntiDumpInfo.MetadataRva; metadataSize = antiAntiDumpInfo.MetadataSize; metadataInfo = antiAntiDumpInfo.MetadataInfo; tableStreamInfo = metadataInfo.TableStream; stringHeapInfo = metadataInfo.StringHeap; userStringHeapInfo = metadataInfo.UserStringHeap; guidHeapInfo = metadataInfo.GuidHeap; blobHeapInfo = metadataInfo.BlobHeap; using (PEImage peHeader = new PEImage(peImageData, ImageLayout.File, false)) { // 用于转换RVA与FOA,必须指定imageLayout参数为ImageLayout.File switch (imageLayout) { case ImageLayout.File: peImageData = PEImageHelper.ConvertImageLayout(peImageData, imageLayout, ImageLayout.Memory); cor20HeaderRva = (uint)peHeader.ToRVA((FileOffset)cor20HeaderRva); metadataRva = (uint)peHeader.ToRVA((FileOffset)metadataRva); break; case ImageLayout.Memory: break; default: throw new NotSupportedException(); } fixed(byte *p = peImageData) { IMAGE_DATA_DIRECTORY *pNETDirectory; IMAGE_COR20_HEADER * pCor20Header; STORAGESIGNATURE * pStorageSignature; byte[] versionString; STORAGEHEADER *pStorageHeader; uint * pStreamHeader; pNETDirectory = (IMAGE_DATA_DIRECTORY *)(p + (uint)peHeader.ImageNTHeaders.OptionalHeader.DataDirectories[14].StartOffset); pNETDirectory->VirtualAddress = cor20HeaderRva; pNETDirectory->Size = IMAGE_COR20_HEADER.UnmanagedSize; // Set Data Directories pCor20Header = (IMAGE_COR20_HEADER *)(p + cor20HeaderRva); pCor20Header->cb = IMAGE_COR20_HEADER.UnmanagedSize; pCor20Header->MajorRuntimeVersion = 0x2; pCor20Header->MinorRuntimeVersion = 0x5; pCor20Header->MetaData.VirtualAddress = metadataRva; pCor20Header->MetaData.Size = metadataSize; // Set .NET Directory pStorageSignature = (STORAGESIGNATURE *)(p + metadataRva); pStorageSignature->lSignature = 0x424A5342; pStorageSignature->iMajorVer = 0x1; pStorageSignature->iMinorVer = 0x1; pStorageSignature->iExtraData = 0x0; pStorageSignature->iVersionString = 0xC; versionString = Encoding.ASCII.GetBytes("v4.0.30319"); for (int i = 0; i < versionString.Length; i++) { pStorageSignature->pVersion[i] = versionString[i]; } // versionString仅仅占位用,程序集具体运行时版本用dnlib获取 // Set StorageSignature pStorageHeader = (STORAGEHEADER *)((byte *)pStorageSignature + STORAGESIGNATURE.UnmanagedSize + pStorageSignature->iVersionString); pStorageHeader->fFlags = 0x0; pStorageHeader->pad = 0x0; pStorageHeader->iStreams = 0x5; // Set StorageHeader pStreamHeader = (uint *)((byte *)pStorageHeader + STORAGEHEADER.UnmanagedSize); if (tableStreamInfo != null) { *pStreamHeader = imageLayout == ImageLayout.Memory ? tableStreamInfo.Rva : (uint)peHeader.ToRVA((FileOffset)tableStreamInfo.Rva); *pStreamHeader -= metadataRva; pStreamHeader++; *pStreamHeader = tableStreamInfo.Length; pStreamHeader++; *pStreamHeader = 0x00007E23; // #~ 暂时不支持#-表流的程序集 pStreamHeader++; } if (stringHeapInfo != null) { *pStreamHeader = imageLayout == ImageLayout.Memory ? stringHeapInfo.Rva : (uint)peHeader.ToRVA((FileOffset)stringHeapInfo.Rva); *pStreamHeader -= metadataRva; pStreamHeader++; *pStreamHeader = stringHeapInfo.Length; pStreamHeader++; *pStreamHeader = 0x72745323; pStreamHeader++; *pStreamHeader = 0x73676E69; pStreamHeader++; *pStreamHeader = 0x00000000; pStreamHeader++; // #Strings } if (userStringHeapInfo != null) { *pStreamHeader = imageLayout == ImageLayout.Memory ? userStringHeapInfo.Rva : (uint)peHeader.ToRVA((FileOffset)userStringHeapInfo.Rva); *pStreamHeader -= metadataRva; pStreamHeader++; *pStreamHeader = userStringHeapInfo.Length; pStreamHeader++; *pStreamHeader = 0x00535523; pStreamHeader++; // #US } if (guidHeapInfo != null) { *pStreamHeader = imageLayout == ImageLayout.Memory ? guidHeapInfo.Rva : (uint)peHeader.ToRVA((FileOffset)guidHeapInfo.Rva); *pStreamHeader -= metadataRva; pStreamHeader++; *pStreamHeader = guidHeapInfo.Length; pStreamHeader++; *pStreamHeader = 0x49554723; pStreamHeader++; *pStreamHeader = 0x00000044; pStreamHeader++; // #GUID } if (blobHeapInfo != null) { *pStreamHeader = imageLayout == ImageLayout.Memory ? blobHeapInfo.Rva : (uint)peHeader.ToRVA((FileOffset)blobHeapInfo.Rva); *pStreamHeader -= metadataRva; pStreamHeader++; *pStreamHeader = blobHeapInfo.Length; pStreamHeader++; *pStreamHeader = 0x6F6C4223; pStreamHeader++; *pStreamHeader = 0x00000062; pStreamHeader++; // #GUID } } } using (ModuleDefMD moduleDef = ModuleDefMD.Load(new PEImage(peImageData, imageLayout, false))) fixed(byte *p = peImageData) { STORAGESIGNATURE *pStorageSignature; byte[] versionString; pStorageSignature = (STORAGESIGNATURE *)(p + metadataRva); switch (moduleDef.CorLibTypes.AssemblyRef.Version.Major) { case 2: versionString = Encoding.ASCII.GetBytes("v2.0.50727"); break; case 4: versionString = Encoding.ASCII.GetBytes("v4.0.30319"); break; default: throw new NotSupportedException(); } for (int i = 0; i < versionString.Length; i++) { pStorageSignature->pVersion[i] = versionString[i]; } } }