public void Add(PESection section) { string groupName = section.Name; if (groupName.Contains("$")) { groupName = groupName.Substring(0, groupName.IndexOf('$')); } ArrayList sectionGroup = null; if (sectionDict.Contains(groupName)) { sectionGroup = (ArrayList)sectionDict[groupName]; } else { sectionGroup = new ArrayList(); sectionDict.Add(groupName, sectionGroup); } int index = 0; foreach (PESection s in sectionGroup) { if (PESection.Compare(section, s) < 0) { sectionGroup.Insert(index, section); return; } index++; } sectionGroup.Add(section); }
public void PopulateSection(PESection section) { uint offset = 0; foreach (var entry in bodies.OrderBy(entry => entry.Key)) { Debug.Assert(entry.Value != null); section.Add(entry.Value, 4); entry.Value.Offset = offset; Debug.Assert(entry.Value.GetFileLength() % 4 == 0); offset += entry.Value.GetFileLength(); } }
public void PopulateSection(PESection section) { uint offset = 0; foreach (var entry in bodies.OrderBy(entry => entry.Key)) { Debug.Assert(entry.Value != null); section.Add(entry.Value, 4); entry.Value.Offset = offset; Debug.Assert(entry.Value.GetFileLength() % 4 == 0); offset += entry.Value.GetFileLength(); } }
public override void Execute() { InjectLoader(_stubModule, typeof(PeSectionLoader)); var peImage = _stubModule.ToPEImage(); var fileBuilder = new ManagedPEFileBuilder(); var peFile = fileBuilder.CreateFile(peImage); var section = new PESection(Name, SectionFlags.MemoryRead | SectionFlags.MemoryWrite | SectionFlags.ContentUninitializedData, new DataSegment(Payload.Compress(Name))); peFile.Sections.Add(section); peFile.Write(OutputPath); }
/// <summary> /// Create the new section to the exe /// </summary> private void CreateSection() { // Create the new section. var section = new PESection(".trad", SectionFlags.MemoryRead | SectionFlags.ContentInitializedData | SectionFlags.MemoryExecute | SectionFlags.MemoryWrite); // Initialize the data var physicalContents = new DataSegment(new byte[newSize]); section.Contents = new VirtualSegment(physicalContents, newSize); // Add the new section into the exe. peFile.Sections.Add(section); // Update the exe headers. peFile.UpdateHeaders(); }
private static void OnWriterEvent(object sender, ModuleWriterEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.Event == ModuleWriterEvent.PESectionsCreated) { var section = new PESection(".origami", 0xC0000080 /*0x40000080*/); writer.AddSection(section); Console.WriteLine($"Created new pe section {section.Name} with characteristics {section.Characteristics:X}"); section.Add(new ByteArrayChunk(_payload.Compress()), 4); Console.WriteLine($"Wrote {_payload.Length.ToString()} bytes to section {section.Name}"); } }
private static void OnWriterEvent(object sender, ModuleWriterEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.Event == ModuleWriterEvent.PESectionsCreated) { var section = new PESection(".origami", 0x40000080); writer.AddSection(section); Console.WriteLine("Created new pe section {0} with characteristics {1}", section.Name, section.Characteristics.ToString("x8")); section.Add(new ByteArrayChunk(Compress(payload)), 4); Console.WriteLine("Wrote {0} bytes to section {1}", payload.Length.ToString(), section.Name); } }
public void RoundTripPE() { // This test validates that a PE can be loaded, copied, and written, without altering the data var originalBytes = Properties.Resources.NativeMemoryDemos; var peFile = PEFile.FromBytes(originalBytes); var msOutput = new MemoryStream(); var output = new PEFile(peFile.DosHeader, peFile.FileHeader, peFile.OptionalHeader); foreach (var section in peFile.Sections) { var newSection = new PESection(section); output.Sections.Add(newSection); } output.Write(new BinaryStreamWriter(msOutput)); Assert.Equal(originalBytes, msOutput.ToArray()); }
private void CalculateRealSectionSize(int processId, IntPtr sectionPointer, PESection section) { const int maxReadSize = 100; int readSize = section.InitialSize; int currentReadSize = readSize % maxReadSize; if (currentReadSize == 0) { currentReadSize = maxReadSize; } IntPtr currentOffset = sectionPointer + readSize - currentReadSize; while (currentOffset.ToInt64() >= sectionPointer.ToInt64()) { byte[] buffer = ReadProcessBytes(processId, currentOffset, currentReadSize); int codeByteCount = GetInstructionByteCount(buffer); if (codeByteCount != 0) { currentOffset += codeByteCount; if (sectionPointer.ToInt64() < currentOffset.ToInt64()) { section.DataSize = (int)(currentOffset.ToInt64() - sectionPointer.ToInt64()); section.DataSize += 4; if (section.InitialSize < section.DataSize) { section.DataSize = section.InitialSize; } } break; } currentReadSize = maxReadSize; currentOffset -= currentReadSize; } }
// Gets notified during module writing public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { switch (evt) { case ModuleWriterEvent.PESectionsCreated: // Add a PE section var sect1 = new PESection(".dummy", 0x40000040); writer.Sections.Add(sect1); // Let's add data sect1.Add(new ByteArrayChunk(new byte[123]), 4); sect1.Add(new ByteArrayChunk(new byte[10]), 4); break; case ModuleWriterEvent.MDEndCreateTables: // All types, methods etc have gotten their new RIDs. Let's print the new values Console.WriteLine("Old -> new type and method tokens"); foreach (var type in writer.Module.GetTypes()) { Console.WriteLine("TYPE: {0:X8} -> {1:X8} {2}", type.MDToken.Raw, new MDToken(Table.TypeDef, writer.MetaData.GetRid(type)).Raw, type.FullName); foreach (var method in type.Methods) { Console.WriteLine(" METH: {0:X8} -> {1:X8} {2}", method.MDToken.Raw, new MDToken(Table.Method, writer.MetaData.GetRid(method)).Raw, method.FullName); } } break; default: break; } }
void CreateSections(ModuleWriterBase writer) { var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.Insert(0, newSection); // insert first to ensure proper RVA uint alignment; alignment = writer.TextSection.Remove(writer.MetaData).Value; writer.TextSection.Add(writer.MetaData, alignment); alignment = writer.TextSection.Remove(writer.NetResources).Value; writer.TextSection.Add(writer.NetResources, alignment); alignment = writer.TextSection.Remove(writer.Constants).Value; newSection.Add(writer.Constants, alignment); // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } var managedWriter = writer as ModuleWriter; if (managedWriter != null) { if (managedWriter.ImportAddressTable != null) { alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value; peSection.Add(managedWriter.ImportAddressTable, alignment); moved = true; } if (managedWriter.StartupStub != null) { alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value; peSection.Add(managedWriter.StartupStub, alignment); moved = true; } } if (moved) { writer.Sections.Add(peSection); } // move encrypted methods var encryptedChunk = new MethodBodyChunks(writer.TheOptions.ShareMethodBodies); newSection.Add(encryptedChunk, 4); foreach (MethodDef method in methods) { if (!method.HasBody) { continue; } MethodBody body = writer.MetaData.GetMethodBody(method); bool ok = writer.MethodBodies.Remove(body); encryptedChunk.Add(body); } // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }
static void Main(string[] args) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); shiftJisEncoding = Encoding.GetEncoding(932); if (args.Length != 4) { Console.WriteLine("Usage: DgfTextInject <exeSrcPath> <exeDestPath> <lectSrcPath> <lsSrcPath>"); Environment.Exit(2); } string exeSrcPath = args[0]; string exeDestPath = args[1]; string lectSrcPath = args[2]; string lsSrcPath = args[3]; try { int numLectEntries = 151; uint lectdatRva = 0x15FE10; int lectStringsSize = 0; int numLsEntries = 24; uint lsmenuRva = 0x1D9488; int lsStringsSize = 0; var pe = PEFile.FromFile(exeSrcPath); // This dumps text files //using (StreamWriter sw = File.CreateText(lectSrcPath)) // DumpStrings(pe, lectdatRva, numLectEntries, 0x2c, 0x50, sw); //using (StreamWriter sw = File.CreateText(lsSrcPath)) // DumpStrings(pe, lsmenuRva, numLsEntries, 0x04, 0x0c, sw); //return; string[] newLectStrings = File.ReadAllLines(lectSrcPath); if (newLectStrings.Length != numLectEntries) { throw new InvalidDataException("Lectures source file does not contain same number of lines as number of lecture definitions."); } uint newLectSpace = CalcSpaceRequired(newLectStrings); string[] newLsStrings = File.ReadAllLines(lsSrcPath); if (newLsStrings.Length != numLsEntries) { throw new InvalidDataException("LS source file does not contain same number of lines as number of LS definitions."); } uint newLsSpace = CalcSpaceRequired(newLsStrings); bool lectInNewSection = true; // newLectSpace > lectStringsSize; bool lsInNewSection = true; // newLsSpace > lsStringsSize; Dictionary <string, uint> writtenLectStrings = new Dictionary <string, uint>(); Dictionary <string, uint> writtenLsStrings = new Dictionary <string, uint>(); List <uint> lectOffsets = new List <uint>(); List <uint> lsOffsets = new List <uint>(); using MemoryStream newSectionMs = new MemoryStream(); using MemoryStream newLectMs = new MemoryStream(); using MemoryStream newLsMs = new MemoryStream(); WriteStrings(lectInNewSection ? newSectionMs : newLectMs, newLectStrings, writtenLectStrings, lectOffsets); WriteStrings(lsInNewSection ? newSectionMs : newLsMs, newLsStrings, writtenLsStrings, lsOffsets); PESection newSection = null; if (lectInNewSection || lsInNewSection) { newSection = new PESection(".trans", SectionFlags.MemoryRead | SectionFlags.ContentInitializedData); newSection.Contents = new DataSegment(newSectionMs.ToArray()); pe.Sections.Add(newSection); pe.UpdateHeaders(); } uint additionalNewSectOffset = 0; uint stringsRva = UpdateTable(pe, lectdatRva, 0x2c, 0x50, lectOffsets, lectInNewSection ? (uint?)(newSection.Rva + additionalNewSectOffset) : null); if (lectInNewSection) { additionalNewSectOffset += newLectSpace; } else { var dataSect = pe.GetSectionContainingRva(stringsRva); using (MemoryStream ms = new MemoryStream((dataSect.Contents as DataSegment).Data)) { ms.Seek(stringsRva - dataSect.Rva, SeekOrigin.Begin); ms.Write(newLectMs.ToArray()); } } stringsRva = UpdateTable(pe, lsmenuRva, 0x04, 0x0c, lsOffsets, lsInNewSection ? (uint?)(newSection.Rva + additionalNewSectOffset) : null); if (lsInNewSection) { additionalNewSectOffset += newLsSpace; } else { var dataSect = pe.GetSectionContainingRva(stringsRva); using (MemoryStream ms = new MemoryStream((dataSect.Contents as DataSegment).Data)) { ms.Seek(stringsRva - dataSect.Rva, SeekOrigin.Begin); ms.Write(newLsMs.ToArray()); } } pe.Write(exeDestPath); } catch (Exception ex) { Console.WriteLine("Something went wrong: " + ex.ToString()); Environment.Exit(1); } }
PESection MergeSectionGroup(ArrayList group) { // Create new section, copy the header from the first // section to get us started. PESection section = new PESection(((PESection)group[0]).Header); // Calculate total raw section size int sectionSize = 0; foreach (PESection s in group) sectionSize += s.Data.Length; byte[] sectionData = new byte[sectionSize]; int offset = 0; foreach (PESection s in group) { Array.Copy(s.Data, 0, sectionData, offset, s.Data.Length); offset += s.Data.Length; } section.Data = sectionData; section.RawSize = (uint)sectionSize; section.PhysicalAddress = 0; return section; }
void CreateSections(ModuleWriterBase writer) { var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.Insert(0, newSection); // insert first to ensure proper RVA uint alignment; alignment = writer.TextSection.Remove(writer.MetaData).Value; writer.TextSection.Add(writer.MetaData, alignment); alignment = writer.TextSection.Remove(writer.NetResources).Value; writer.TextSection.Add(writer.NetResources, alignment); alignment = writer.TextSection.Remove(writer.Constants).Value; newSection.Add(writer.Constants, alignment); // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } var managedWriter = writer as ModuleWriter; if (managedWriter != null) { if (managedWriter.ImportAddressTable != null) { alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value; peSection.Add(managedWriter.ImportAddressTable, alignment); moved = true; } if (managedWriter.StartupStub != null) { alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value; peSection.Add(managedWriter.StartupStub, alignment); moved = true; } } if (moved) writer.Sections.Add(peSection); // move encrypted methods var encryptedChunk = new MethodBodyChunks(writer.TheOptions.ShareMethodBodies); newSection.Add(encryptedChunk, 4); foreach (MethodDef method in methods) { if (!method.HasBody) continue; MethodBody body = writer.MetaData.GetMethodBody(method); bool ok = writer.MethodBodies.Remove(body); encryptedChunk.Add(body); } // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }
void CreateSection(ModuleWriterBase writer) { // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; uint alignment; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } var managedWriter = writer as ModuleWriter; if (managedWriter != null) { if (managedWriter.ImportAddressTable != null) { alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value; peSection.Add(managedWriter.ImportAddressTable, alignment); moved = true; } if (managedWriter.StartupStub != null) { alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value; peSection.Add(managedWriter.StartupStub, alignment); moved = true; } } if (moved) writer.Sections.Add(peSection); // create section var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.Insert(random.NextInt32(writer.Sections.Count), newSection); // random padding at beginning to prevent revealing hash key newSection.Add(new ByteArrayChunk(random.NextBytes(0x10)), 0x10); // create index var bodyIndex = new JITBodyIndex(methods.Select(method => writer.MetaData.GetToken(method).Raw)); newSection.Add(bodyIndex, 0x10); // save methods foreach (MethodDef method in methods.WithProgress(context.Logger)) { if (!method.HasBody) continue; MDToken token = writer.MetaData.GetToken(method); var jitBody = new JITMethodBody(); var bodyWriter = new JITMethodBodyWriter(writer.MetaData, method.Body, jitBody, random.NextUInt32(), writer.MetaData.KeepOldMaxStack || method.Body.KeepOldMaxStack); bodyWriter.Write(); jitBody.Serialize(token.Raw, key, fieldLayout); bodyIndex.Add(token.Raw, jitBody); method.Body = NopBody; writer.MetaData.TablesHeap.MethodTable[token.Rid].ImplFlags |= (ushort)MethodImplAttributes.NoInlining; context.CheckCancellation(); } bodyIndex.PopulateSection(newSection); // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }
private void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) { ModuleWriterBase moduleWriterBase = (ModuleWriterBase)sender; if (e.WriterEvent == ModuleWriterEvent.MDEndCreateTables) { PESection pESection = new PESection("Rzy", 1073741888u); moduleWriterBase.Sections.Add(pESection); pESection.Add(new ByteArrayChunk(new byte[123]), 4u); pESection.Add(new ByteArrayChunk(new byte[10]), 4u); string text = ".Rzy"; string s = null; for (int i = 0; i < 80; i++) { text += FakeNative.FakeNativePhase.GetRandomString(); } for (int j = 0; j < 80; j++) { byte[] bytes = Encoding.ASCII.GetBytes(text); s = Utils.EncodeString(bytes, FakeNative.FakeNativePhase.asciiCharset); } byte[] bytes2 = Encoding.ASCII.GetBytes(s); moduleWriterBase.TheOptions.MetaDataOptions.OtherHeapsEnd.Add(new FakeNative.RawHeap("#Rzy-Private-Protector", bytes2)); pESection.Add(new ByteArrayChunk(bytes2), 4u); var writer = (ModuleWriterBase)sender; uint signature = (uint)(moduleWriterBase.MetaData.TablesHeap.TypeSpecTable.Rows + 1); List <uint> list = (from row in moduleWriterBase.MetaData.TablesHeap.TypeDefTable select row.Namespace).Distinct <uint>().ToList <uint>(); List <uint> list2 = (from row in moduleWriterBase.MetaData.TablesHeap.MethodTable select row.Name).Distinct <uint>().ToList <uint>(); uint num2 = Convert.ToUInt32(FakeNative.R.Next(15, 3546)); using (List <uint> .Enumerator enumerator = list.GetEnumerator()) { while (enumerator.MoveNext()) { uint current = enumerator.Current; if (current != 0u) { foreach (uint current2 in list2) { if (current2 != 0u) { moduleWriterBase.MetaData.TablesHeap.TypeSpecTable.Add(new RawTypeSpecRow(signature)); moduleWriterBase.MetaData.TablesHeap.ModuleTable.Add(new RawModuleRow(65535, 0u, 4294967295u, 4294967295u, 4294967295u)); moduleWriterBase.MetaData.TablesHeap.ParamTable.Add(new RawParamRow(254, 254, moduleWriterBase.MetaData.TablesHeap.ENCMapTable.Add(new RawENCMapRow(this.random.NextUInt32())))); moduleWriterBase.MetaData.TablesHeap.FieldTable.Add(new RawFieldRow((ushort)(num2 * 4u + 77u), 31u + num2 / 2u * 3u, this.random.NextUInt32())); moduleWriterBase.MetaData.TablesHeap.MemberRefTable.Add(new RawMemberRefRow(num2 + 18u, num2 * 4u + 77u, 31u + num2 / 2u * 3u)); moduleWriterBase.MetaData.TablesHeap.TypeSpecTable.Add(new RawTypeSpecRow(3391u + num2 / 2u * 3u)); moduleWriterBase.MetaData.TablesHeap.PropertyTable.Add(new RawPropertyRow((ushort)(num2 + 44u - 1332u), num2 / 2u + 2u, this.random.NextUInt32())); moduleWriterBase.MetaData.TablesHeap.TypeSpecTable.Add(new RawTypeSpecRow(3391u + num2 / 2u * 3u)); moduleWriterBase.MetaData.TablesHeap.PropertyPtrTable.Add(new RawPropertyPtrRow(this.random.NextUInt32())); moduleWriterBase.MetaData.TablesHeap.AssemblyRefTable.Add(new RawAssemblyRefRow(55, 44, 66, 500, this.random.NextUInt32(), this.random.NextUInt32(), moduleWriterBase.MetaData.TablesHeap.ENCMapTable.Add(new RawENCMapRow(this.random.NextUInt32())), this.random.NextUInt32(), this.random.NextUInt32())); moduleWriterBase.MetaData.TablesHeap.ENCLogTable.Add(new RawENCLogRow(this.random.NextUInt32(), moduleWriterBase.MetaData.TablesHeap.ENCMapTable.Add(new RawENCMapRow(this.random.NextUInt32())))); moduleWriterBase.MetaData.TablesHeap.ENCLogTable.Add(new RawENCLogRow(this.random.NextUInt32(), (uint)(moduleWriterBase.MetaData.TablesHeap.ENCMapTable.Rows - 1))); moduleWriterBase.MetaData.TablesHeap.ImplMapTable.Add(new RawImplMapRow(18, num2 * 4u + 77u, 31u + num2 / 2u * 3u, num2 * 4u + 77u)); } } } } } } if (e.WriterEvent == ModuleWriterEvent.MDOnAllTablesSorted) { moduleWriterBase.MetaData.TablesHeap.DeclSecurityTable.Add(new RawDeclSecurityRow(32767, 4294934527u, 4294934527u)); } }
internal MemoryCursor/*!*/ GetNewCursor(int RVA, out PESection targetSection) { MemoryCursor c = new MemoryCursor(this.cursor); c.Position = this.RvaToOffset(RVA, out targetSection); return c; }
private void Parse(Stream stream) { rawData = new byte[stream.Length]; stream.Read(rawData, 0, (int)stream.Length); stream.Seek(0, SeekOrigin.Begin); BinaryReader reader = new BinaryReader(stream); fileHeader = PEUtility.FromBinaryReader<IMAGE_FILE_HEADER>(reader); // Read the sections sections = new List<PESection>(); for (int i = 0; i < fileHeader.NumberOfSections; i++) { IMAGE_SECTION_HEADER header; header = PEUtility.FromBinaryReader<IMAGE_SECTION_HEADER>(reader); PESection section = new PESection(this, header); section.Parse(ref rawData); sections.Add(section); } // Read the symbol table from fileHeader.PointerToSymbolTable symbolTable = new SymbolTable(fileHeader.NumberOfSymbols); stream.Seek(fileHeader.PointerToSymbolTable, SeekOrigin.Begin); for (int i = 0; i < fileHeader.NumberOfSymbols; i++) { IMAGE_SYMBOL symbol; symbol = PEUtility.FromBinaryReader<IMAGE_SYMBOL>(reader); symbolTable.AddSymbol(symbol, i); } uint pointerToStringTable = fileHeader.PointerToSymbolTable + (uint)(fileHeader.NumberOfSymbols * Marshal.SizeOf(typeof(IMAGE_SYMBOL))); stream.Seek(pointerToStringTable, SeekOrigin.Begin); uint stringTableSize = PEUtility.FromBinaryReader<UInt32>(reader); for (ushort i = (ushort)Marshal.SizeOf(typeof(UInt32)); i < stringTableSize; ) { String stringEntry = PEUtility.StringFromBinaryReader(reader); symbolTable.AddString(stringEntry, i); i += (ushort)(stringEntry.Length + 1); // include NULL terminator } Console.WriteLine("Object File: {0}", sourceFile); Console.WriteLine(symbolTable.ToString()); Console.WriteLine("Sections:"); foreach (PESection s in sections) { Console.WriteLine(s.ToString()); } Console.WriteLine(); }
void CreateSections() { sections = new List<PESection>(); sections.Add(textSection = new PESection(".text", 0x60000020)); if (GetWin32Resources() != null) sections.Add(rsrcSection = new PESection(".rsrc", 0x40000040)); if (!Options.Is64Bit) sections.Add(relocSection = new PESection(".reloc", 0x42000040)); }
private byte[] GetInitialData(int fieldIndex, TypeNode fieldType, out PESection targetSection) { targetSection = PESection.Text; FieldRvaRow[] fieldRvaTable = this.tables.FieldRvaTable; bool sorted = (this.sortedTablesMask >> (int)TableIndices.FieldRva) % 2 == 1; int i = 0, n = fieldRvaTable.Length, j = n - 1; if (n == 0) return null; if (sorted) { while (i < j) { int k = (i + j) / 2; if (fieldRvaTable[k].Field < fieldIndex) i = k + 1; else j = k; } } else for (; i < j; i++) if (fieldRvaTable[i].Field == fieldIndex) break; FieldRvaRow frr = fieldRvaTable[i]; if (frr.Field != fieldIndex) return null; Field fld = this.tables.FieldTable[fieldIndex - 1].Field; if (fld != null) fld.Offset = frr.RVA; fieldType = TypeNode.StripModifiers(fieldType); EnumNode enumType = fieldType as EnumNode; if (enumType != null) fieldType = TypeNode.StripModifiers(enumType.UnderlyingType); if (fieldType == null) { Debug.Fail(""); return null; } int size = fieldType.ClassSize; if (size <= 0) { switch (fieldType.typeCode) { case ElementType.Boolean: size = 1; break; case ElementType.Char: size = 2; break; case ElementType.Double: size = 8; break; case ElementType.Int16: size = 2; break; case ElementType.Int32: size = 4; break; case ElementType.Int64: size = 8; break; case ElementType.Int8: size = 1; break; case ElementType.Single: size = 4; break; case ElementType.UInt16: size = 2; break; case ElementType.UInt32: size = 4; break; case ElementType.UInt64: size = 8; break; case ElementType.UInt8: size = 1; break; default: if (fieldType is Pointer || fieldType is FunctionPointer) { size = 4; break; } //TODO: this seems wrong if (i < n - 1) size = fieldRvaTable[i + 1].RVA - frr.RVA; else if (targetSection != PESection.Text) size = this.tables.GetOffsetToEndOfSection(frr.RVA); break; } } if (size <= 0) return null; if (this.tables.NoOffsetFor(frr.RVA) || this.tables.NoOffsetFor(frr.RVA + size - 1)) return null; MemoryCursor c = this.tables.GetNewCursor(frr.RVA, out targetSection); byte[] result = new byte[size]; for (i = 0; i < size; i++) result[i] = c.ReadByte(); return result; }
internal static void InsertBeforeReloc(this List <PESection> sections, int preferredIndex, PESection newSection) { if (sections == null) { throw new ArgumentNullException(nameof(sections)); } if (preferredIndex < 0 || preferredIndex > sections.Count) { throw new ArgumentOutOfRangeException(nameof(preferredIndex), preferredIndex, "Preferred index is out of range."); } if (newSection == null) { throw new ArgumentNullException(nameof(newSection)); } var relocIndex = sections.FindIndex(0, Math.Min(preferredIndex + 1, sections.Count), IsRelocSection); if (relocIndex == -1) { sections.Insert(preferredIndex, newSection); } else { sections.Insert(relocIndex, newSection); } }
public void Write() { var peImage = mdEditor.RealMetadata.PEImage; bool is32Bit = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; sections.Add(textSection = new PESection(".text", 0x60000020)); StrongNameSignatureSectionData snData = null; var cor20 = mdEditor.RealMetadata.ImageCor20Header; if ((cor20.Flags & ComImageFlags.StrongNameSigned) != 0 && cor20.StrongNameSignature.Size != 0 && cor20.StrongNameSignature.VirtualAddress != 0) { snData = new StrongNameSignatureSectionData(cor20.StrongNameSignature.Size); } if (snData != null) { textSection.SectionData.Add(snData); } var mdData = new DotNetMetadataSectionData(mdEditor); textSection.SectionData.Add(new ImageCor20HeaderSectionData(mdData, snData)); textSection.SectionData.Add(mdData); // DOS MZ header stream.Write(dosHeader); // PE\0\0 Debug.Assert(stream.Position == BitConverter.ToUInt32(dosHeader, 0x7C)); stream.Write(0x00004550); // IMAGE_FILE_HEADER var ifh = peImage.ImageNTHeaders.FileHeader; stream.Write((ushort)ifh.Machine); Debug.Assert(sections.Count <= ushort.MaxValue); stream.Write((ushort)sections.Count); stream.Write(ifh.TimeDateStamp); stream.Position += 8; // PointerToSymbolTable & NumberOfSymbols stream.Write((ushort)(is32Bit ? 0xE0 : 0xF0)); stream.Write((ushort)ifh.Characteristics); // IMAGE_OPTIONAL_HEADER var optHeaderPos = stream.Position; if (is32Bit) { var opt = (ImageOptionalHeader32)peImage.ImageNTHeaders.OptionalHeader; var start = stream.Position; stream.Write(opt.Magic); stream.Write(opt.MajorLinkerVersion); stream.Write(opt.MinorLinkerVersion); // SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData // AddressOfEntryPoint, BaseOfCode, BaseOfData stream.Position += 6 * 4; stream.Write((uint)opt.ImageBase); stream.Write((uint)SectionAlignment); stream.Write((uint)FileAlignment); stream.Write(opt.MajorOperatingSystemVersion); stream.Write(opt.MinorOperatingSystemVersion); stream.Write(opt.MajorImageVersion); stream.Write(opt.MinorImageVersion); stream.Write(opt.MajorSubsystemVersion); stream.Write(opt.MinorSubsystemVersion); stream.Write(opt.Win32VersionValue); // SizeOfImage, SizeOfHeaders, CheckSum stream.Position += 3 * 4; stream.Write((ushort)opt.Subsystem); stream.Write((ushort)opt.DllCharacteristics); stream.Write((uint)opt.SizeOfStackReserve); stream.Write((uint)opt.SizeOfStackCommit); stream.Write((uint)opt.SizeOfHeapReserve); stream.Write((uint)opt.SizeOfHeapCommit); stream.Write(opt.LoaderFlags); stream.Write(0x10); // NumberOfRvaAndSizes Debug.Assert((stream.Position - start) == 0x60); } else { var opt = (ImageOptionalHeader64)peImage.ImageNTHeaders.OptionalHeader; var start = stream.Position; stream.Write(opt.Magic); stream.Write(opt.MajorLinkerVersion); stream.Write(opt.MinorLinkerVersion); // SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData // AddressOfEntryPoint, BaseOfCode stream.Position += 5 * 4; stream.Write(opt.ImageBase); stream.Write((uint)SectionAlignment); stream.Write((uint)FileAlignment); stream.Write(opt.MajorOperatingSystemVersion); stream.Write(opt.MinorOperatingSystemVersion); stream.Write(opt.MajorImageVersion); stream.Write(opt.MinorImageVersion); stream.Write(opt.MajorSubsystemVersion); stream.Write(opt.MinorSubsystemVersion); stream.Write(opt.Win32VersionValue); // SizeOfImage, SizeOfHeaders, CheckSum stream.Position += 3 * 4; stream.Write((ushort)opt.Subsystem); stream.Write((ushort)opt.DllCharacteristics); stream.Write(opt.SizeOfStackReserve); stream.Write(opt.SizeOfStackCommit); stream.Write(opt.SizeOfHeapReserve); stream.Write(opt.SizeOfHeapCommit); stream.Write(opt.LoaderFlags); stream.Write(0x10); // NumberOfRvaAndSizes Debug.Assert((stream.Position - start) == 0x70); } // IMAGE_DATA_DIRECTORY dataDirPosition = stream.Position; stream.Position += 0x10 * 8; // IMAGE_SECTION_HEADER var sectionPos = stream.Position; foreach (var section in sections) { Debug.Assert(section.Name.Length == 8); stream.Write(section.Name); // VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData // PointerToRelocations, PointerToLinenumbers, NumberOfRelocations, NumberOfLinenumbers stream.Position += 6 * 4 + 2 * 2; stream.Write(section.Characteristics); } uint headerLength = (uint)stream.Position; AlignUp(FileAlignment); // Write all sections uint rva = SectionAlignment; foreach (var section in sections) { section.VirtualAddress = rva; section.PointerToRawData = (uint)stream.Position; foreach (var data in section.SectionData) { var pos = stream.Position; AlignUp(data.Alignment); rva += (uint)(stream.Position - pos); pos = stream.Position; data.Write(this, rva, stream); rva += (uint)(stream.Position - pos); } Debug.Assert(stream.Position != section.PointerToRawData); if (stream.Position == section.PointerToRawData) { stream.Position++; } section.VirtualSize = (uint)stream.Position - section.PointerToRawData; section.SizeOfRawData = ((uint)stream.Position - section.PointerToRawData + FileAlignment - 1) & ~(FileAlignment - 1); rva = (rva + SectionAlignment - 1) & ~(SectionAlignment - 1); AlignUp(FileAlignment); } stream.Length = stream.Position; // Update IMAGE_SECTION_HEADER stream.Position = sectionPos; foreach (var section in sections) { stream.Position += 8; stream.Write(section.VirtualSize); stream.Write(section.VirtualAddress); stream.Write(section.SizeOfRawData); stream.Write(section.PointerToRawData); stream.Position += 16; } // Update IMAGE_OPTIONAL_HEADER var sectionSizes = new SectionSizes(FileAlignment, SectionAlignment, headerLength, () => GetSectionSizeInfos()); stream.Position = optHeaderPos; if (is32Bit) { var opt = (ImageOptionalHeader32)peImage.ImageNTHeaders.OptionalHeader; stream.Position += 4; stream.Write(sectionSizes.SizeOfCode); stream.Write(sectionSizes.SizeOfInitdData); stream.Write(sectionSizes.SizeOfUninitdData); stream.Position += 4; stream.Write(sectionSizes.BaseOfCode); stream.Write(sectionSizes.BaseOfData); stream.Position += 0x1C; stream.Write(sectionSizes.SizeOfImage); stream.Write(sectionSizes.SizeOfHeaders); } else { var opt = (ImageOptionalHeader64)peImage.ImageNTHeaders.OptionalHeader; stream.Position += 4; stream.Write(sectionSizes.SizeOfCode); stream.Write(sectionSizes.SizeOfInitdData); stream.Write(sectionSizes.SizeOfUninitdData); stream.Position += 4; stream.Write(sectionSizes.BaseOfCode); stream.Position += 0x20; stream.Write(sectionSizes.SizeOfImage); stream.Write(sectionSizes.SizeOfHeaders); } foreach (var section in sections) { foreach (var data in section.SectionData) { data.Finish(this, stream); } } }
// Gets notified during module writing public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { switch (evt) { case ModuleWriterEvent.PESectionsCreated: // Add a PE section var sect1 = new PESection(".dummy", 0x40000040); writer.Sections.Add(sect1); // Let's add data sect1.Add(new ByteArrayChunk(new byte[123]), 4); sect1.Add(new ByteArrayChunk(new byte[10]), 4); break; case ModuleWriterEvent.MDEndCreateTables: // All types, methods etc have gotten their new RIDs. Let's print the new values Console.WriteLine("Old -> new type and method tokens"); foreach (var type in writer.Module.GetTypes()) { Console.WriteLine("TYPE: {0:X8} -> {1:X8} {2}", type.MDToken.Raw, new MDToken(Table.TypeDef, writer.MetaData.GetRid(type)).Raw, type.FullName); foreach (var method in type.Methods) Console.WriteLine(" METH: {0:X8} -> {1:X8} {2}", method.MDToken.Raw, new MDToken(Table.Method, writer.MetaData.GetRid(method)).Raw, method.FullName); } break; default: break; } }
private static bool IsRelocSection(PESection section) => section.Name.Equals(".reloc", StringComparison.Ordinal);
void CreateSection(ModuleWriterBase writer) { // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; uint alignment; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } var managedWriter = writer as ModuleWriter; if (managedWriter != null) { if (managedWriter.ImportAddressTable != null) { alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value; peSection.Add(managedWriter.ImportAddressTable, alignment); moved = true; } if (managedWriter.StartupStub != null) { alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value; peSection.Add(managedWriter.StartupStub, alignment); moved = true; } } if (moved) { writer.Sections.Add(peSection); } // create section var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.Insert(random.NextInt32(writer.Sections.Count), newSection); // random padding at beginning to prevent revealing hash key newSection.Add(new ByteArrayChunk(random.NextBytes(0x10)), 0x10); // create index var bodyIndex = new JITBodyIndex(methods.Select(method => writer.MetaData.GetToken(method).Raw)); newSection.Add(bodyIndex, 0x10); // save methods foreach (MethodDef method in methods.WithProgress(context.Logger)) { if (!method.HasBody) { continue; } MDToken token = writer.MetaData.GetToken(method); var jitBody = new JITMethodBody(); var bodyWriter = new JITMethodBodyWriter(writer.MetaData, method.Body, jitBody, random.NextUInt32(), writer.MetaData.KeepOldMaxStack || method.Body.KeepOldMaxStack); bodyWriter.Write(); jitBody.Serialize(token.Raw, key, fieldLayout); bodyIndex.Add(token.Raw, jitBody); method.Body = NopBody; writer.MetaData.TablesHeap.MethodTable[token.Rid].ImplFlags |= (ushort)MethodImplAttributes.NoInlining; context.CheckCancellation(); } bodyIndex.PopulateSection(newSection); // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }
private int RvaToOffset(int virtualAddress, out PESection targetSection) { foreach (SectionHeader section in this.sectionHeaders) if (virtualAddress >= section.virtualAddress && virtualAddress < section.virtualAddress + section.sizeOfRawData) { if (section.name == ".tls") targetSection = PESection.TLS; else if (section.name == ".sdata") targetSection = PESection.SData; else targetSection = PESection.Text; return (virtualAddress - section.virtualAddress + section.pointerToRawData); } throw new InvalidMetadataException(String.Format( CultureInfo.CurrentCulture, ExceptionStrings.UnknownVirtualAddress, +virtualAddress)); }