public void Load(string file) { FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs); try { buffer = br.ReadBytes((int)fs.Length); dosHeader = ReadDosHeader(buffer, 0); ntHeader = ReadNTHeader(buffer, dosHeader.lfanew); sectionAlignment = ntHeader.NTOptionalHeader.SectionAlignment; uint pos = dosHeader.lfanew + IMAGE_NT_HEADERS.StructSize; uint va = ntHeader.NTOptionalHeader.DataDirectory.runtimeHeader.VirtualAddress; sectHeaders = new IMAGE_SECTION_HEADER[ntHeader.NTFileHeader.NumberOfSections]; for (uint i = 0; i < ntHeader.NTFileHeader.NumberOfSections; i++) { IMAGE_SECTION_HEADER sectHeader = ReadSectionHeader(buffer, pos); pos += IMAGE_SECTION_HEADER.StructSize; sectHeaders[i] = sectHeader; } newSectHeaderPos = pos; pos = GetFileOffset(va); corHeader = ReadCor20Header(buffer, pos); uint metadataRVA = corHeader.MetaData.VirtualAddress; uint metadataSize = corHeader.MetaData.Size; pos = GetFileOffset(metadataRVA); metadata = ReadMetadataTables(buffer, pos, metadataSize); } finally { br.Close(); fs.Close(); fs.Dispose(); } }
public void Save(string file, IMAGE_SECTION_HEADER header, byte[] newSection) { FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); try { uint size = header.PointerToRawData + header.SizeOfRawData; byte[] buf = new byte[size]; buf.Initialize(); WriteDosHeader(buf, 0, dosHeader); uint pos = dosHeader.lfanew; WriteNTHeader(buf, pos, ntHeader); pos = dosHeader.lfanew + IMAGE_NT_HEADERS.StructSize; for (uint i = 0; i < newSectHeaders.Length; i++) { WriteSectionHeader(buf, pos, newSectHeaders[i]); pos += IMAGE_SECTION_HEADER.StructSize; } WriteSectionHeader(buf, newSectHeaderPos, header); for (uint i = 0; i < newSectHeaders.Length; i++) { Array.Copy(buffer, sectHeaders[i].PointerToRawData, buf, newSectHeaders[i].PointerToRawData, sectHeaders[i].SizeOfRawData); } Array.Copy(newSection, 0, buf, header.PointerToRawData, newSection.Length); bw.Write(buf); } finally { bw.Close(); fs.Close(); fs.Dispose(); } }
private static unsafe void WriteSectionHeader(byte[] buffer, uint pos, IMAGE_SECTION_HEADER header) { fixed(byte *p = buffer) { IMAGE_SECTION_HEADER *ptr = (IMAGE_SECTION_HEADER *)(p + pos); *ptr = header; } }
private static unsafe IMAGE_SECTION_HEADER ReadSectionHeader(byte[] buffer, uint pos) { IMAGE_SECTION_HEADER dosHeader = new IMAGE_SECTION_HEADER(); fixed(byte *p = buffer) { IMAGE_SECTION_HEADER *ptr = (IMAGE_SECTION_HEADER *)(p + pos); dosHeader = *ptr; } return(dosHeader); }
public IMAGE_SECTION_HEADER PrepareNewSectionHeader(string name, uint sectSize, bool forMetadata) { uint curRVA = Alignment.Calc(newSectHeaderPos + IMAGE_SECTION_HEADER.StructSize, sectionAlignment); ntHeader.NTFileHeader.NumberOfSections++; ntHeader.NTOptionalHeader.FileAlignment = sectionAlignment;//必须让文件对齐与段对齐一样,这样才能保证跨段偏移对文件与对内存一致 ntHeader.NTOptionalHeader.SizeOfHeaders = curRVA; newSectHeaders = new IMAGE_SECTION_HEADER[sectHeaders.Length]; for (uint i = 0; i < newSectHeaders.Length; i++) { newSectHeaders[i] = sectHeaders[i]; newSectHeaders[i].VirtualAddress = curRVA; newSectHeaders[i].SizeOfRawData = Alignment.Calc(newSectHeaders[i].SizeOfRawData, sectionAlignment); newSectHeaders[i].PointerToRawData = curRVA; curRVA = Alignment.Calc(curRVA + newSectHeaders[i].SizeOfRawData, sectionAlignment); } //添加新段 IMAGE_SECTION_HEADER header = new IMAGE_SECTION_HEADER(); header.Name = name; header.VirtualSize = sectSize; header.VirtualAddress = curRVA; header.SizeOfRawData = Alignment.Calc(sectSize, sectionAlignment); header.PointerToRawData = curRVA; header.PointerToRelocations = 0; header.PointerToLinenumbers = 0; header.NumberOfRelocations = 0; header.NumberOfLinenumbers = 0; header.Characteristics = 0x60000020; ntHeader.NTOptionalHeader.SizeOfImage = Alignment.Calc(header.VirtualAddress + header.SizeOfRawData, sectionAlignment); if (forMetadata) { corHeader.MetaData.VirtualAddress = header.VirtualAddress; corHeader.MetaData.Size = sectSize; uint va = ntHeader.NTOptionalHeader.DataDirectory.runtimeHeader.VirtualAddress; uint pos = GetFileOffset(va); WriteCor20Header(buffer, pos, corHeader);//改写原映像数据中的Cor20头,这些修改在Save时会随着所属段一起拷贝到新映像数据中 } return(header); }
public uint GetFileOffset(uint va) { int n = sectHeaders.Length; uint sva = 0; uint addr = 0; for (uint i = 0; i < n; i++) { IMAGE_SECTION_HEADER sectHeader = sectHeaders[i]; if (sectHeader.VirtualAddress <= va) { if (sva <= sectHeader.VirtualAddress) { sva = sectHeader.VirtualAddress; addr = sectHeader.PointerToRawData; } } } return(va - sva + addr); }