From 2813e2be58ef52f9eef6c2e6a65a5033685b5283 Mon Sep 17 00:00:00 2001 From: Washi Date: Wed, 21 Jun 2023 15:44:52 +0200 Subject: [PATCH] BUGFIX: Filter out invalid UTF-8 characters from section names. --- .../Headers/SectionHeader.cs | 69 ++++++++++-------- test/AsmResolver.PE.File.Tests/PEFileTest.cs | 14 ++++ .../Properties/Resources.Designer.cs | 10 +++ .../Properties/Resources.resx | 9 ++- .../HelloWorld.InvalidSectionName.exe | Bin 0 -> 4608 bytes 5 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 test/AsmResolver.PE.File.Tests/Resources/HelloWorld.InvalidSectionName.exe diff --git a/src/AsmResolver.PE.File/Headers/SectionHeader.cs b/src/AsmResolver.PE.File/Headers/SectionHeader.cs index f2a72e7d0..a5de4f389 100644 --- a/src/AsmResolver.PE.File/Headers/SectionHeader.cs +++ b/src/AsmResolver.PE.File/Headers/SectionHeader.cs @@ -19,35 +19,6 @@ public class SectionHeader : SegmentBase, IOffsetConverter private string _name; - /// - /// Reads a single section header at the current position of the provided input stream. - /// - /// The input stream to read from. - /// The section header that was read. - public static SectionHeader FromReader(ref BinaryStreamReader reader) - { - ulong offset = reader.Offset; - uint rva = reader.Rva; - - var nameBytes = new byte[8]; - reader.ReadBytes(nameBytes, 0, nameBytes.Length); - - return new SectionHeader(Encoding.UTF8.GetString(nameBytes).Replace("\0", ""), 0) - { - Offset = offset, - Rva = rva, - VirtualSize = reader.ReadUInt32(), - VirtualAddress = reader.ReadUInt32(), - SizeOfRawData = reader.ReadUInt32(), - PointerToRawData = reader.ReadUInt32(), - PointerToRelocations = reader.ReadUInt32(), - PointerToLineNumbers = reader.ReadUInt32(), - NumberOfRelocations = reader.ReadUInt16(), - NumberOfLineNumbers = reader.ReadUInt16(), - Characteristics = (SectionFlags) reader.ReadUInt32() - }; - } - /// /// Creates a new section header with the provided name. /// @@ -194,6 +165,46 @@ public SectionFlags Characteristics set; } + /// + /// Reads a single section header at the current position of the provided input stream. + /// + /// The input stream to read from. + /// The section header that was read. + public static SectionHeader FromReader(ref BinaryStreamReader reader) + { + ulong offset = reader.Offset; + uint rva = reader.Rva; + + // Read name field. + byte[] nameBytes = new byte[8]; + reader.ReadBytes(nameBytes, 0, nameBytes.Length); + + // Interpret as UTF-8, discarding all invalid UTF-8 characters. + string name = Encoding.UTF8.GetString(nameBytes).Replace("\xfffd", ""); + + // Trim to last null-byte if it exists. + int index = name.IndexOf('\0'); + if (index >= 0) + name = name.Remove(index); + + return new SectionHeader(name, 0) + { + Offset = offset, + Rva = rva, + + // Read remainder of section header. + VirtualSize = reader.ReadUInt32(), + VirtualAddress = reader.ReadUInt32(), + SizeOfRawData = reader.ReadUInt32(), + PointerToRawData = reader.ReadUInt32(), + PointerToRelocations = reader.ReadUInt32(), + PointerToLineNumbers = reader.ReadUInt32(), + NumberOfRelocations = reader.ReadUInt16(), + NumberOfLineNumbers = reader.ReadUInt16(), + Characteristics = (SectionFlags) reader.ReadUInt32() + }; + } + /// public override uint GetPhysicalSize() => SectionHeaderSize; diff --git a/test/AsmResolver.PE.File.Tests/PEFileTest.cs b/test/AsmResolver.PE.File.Tests/PEFileTest.cs index 7a1c47463..5ce0a2b96 100644 --- a/test/AsmResolver.PE.File.Tests/PEFileTest.cs +++ b/test/AsmResolver.PE.File.Tests/PEFileTest.cs @@ -240,5 +240,19 @@ public void RemoveExistingEofData() var newFile = PEFile.FromBytes(newFileBytes); Assert.Null(newFile.EofData); } + + [Fact] + public void ReadSections() + { + var file = PEFile.FromBytes(Properties.Resources.HelloWorld); + Assert.Equal(new[] {".text", ".rsrc", ".reloc"}, file.Sections.Select(x => x.Name)); + } + + [Fact] + public void ReadInvalidSectionName() + { + var file = PEFile.FromBytes(Properties.Resources.HelloWorld_InvalidSectionName); + Assert.Equal(new[] {".text", ".rsrc", ".reloc"}, file.Sections.Select(x => x.Name)); + } } } diff --git a/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs b/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs index f2f817fd5..57a37ab19 100644 --- a/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs +++ b/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs @@ -90,6 +90,16 @@ public static byte[] HelloWorld_EOF { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + public static byte[] HelloWorld_InvalidSectionName { + get { + object obj = ResourceManager.GetObject("HelloWorld_InvalidSectionName", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/test/AsmResolver.PE.File.Tests/Properties/Resources.resx b/test/AsmResolver.PE.File.Tests/Properties/Resources.resx index c33ee0174..b075ab67e 100644 --- a/test/AsmResolver.PE.File.Tests/Properties/Resources.resx +++ b/test/AsmResolver.PE.File.Tests/Properties/Resources.resx @@ -127,7 +127,10 @@ ..\Resources\HelloWorld.EOF.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\NativeMemoryDemos.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + ..\Resources\HelloWorld.InvalidSectionName.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\NativeMemoryDemos.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + diff --git a/test/AsmResolver.PE.File.Tests/Resources/HelloWorld.InvalidSectionName.exe b/test/AsmResolver.PE.File.Tests/Resources/HelloWorld.InvalidSectionName.exe new file mode 100644 index 0000000000000000000000000000000000000000..8947b3b639c91fdf2f4c872fc6662b32464f5d02 GIT binary patch literal 4608 zcmeHK-EUk+6+h$HuI*quQD~JENGI#G4S`&*V-uypPS*C?iNPOR@7fVzp}Bi^yuR)I zSnk|)ynw2RFR2osRBEM2eL&(5Co2 zR@!#8tVdxjvVG~;K@i5WqGZ$vq#MZmT2cC8RawKsL&sCog$1Hzv5$T~`rL0?tKFgu z?H5_10dTmZefJRniJn7eATjhLegiZ9^GMgx!RNM*a^EC6VE#H|N+v3F4tCcV&kY+St=Xf5Z4!#*1;} z1~ttZZ{mV}6yw-Nk^TXkw>5TgV=0eu0KWc?={YZ~VC06ai;MRY4KndhF-Z?3`x#DT zCNx;W#EL`7ICr8&k&ONHTY6FS(+R;aOD~8~`V~a|^m*CX61 z;2*>_NRQGrV=}SJQ4sJy6o+WS;04L+K1)xFG0*Ofc2K)#;4md_v06#(B2b`oI z0e+fZ1DvN{0)E!;i-5h?TM>d&rX2!A=-chV?n^nn5>^|YI#0fK!pL(gbV+$$co}$= z=EFdTo}$Z<8>?kEP?T4dMy+O7JT)8R)GLix(X7_WuXxRp8+Wryc2raGBGQYx7Di9) z)n9ZywW%WQhQVIpQm_?9z8ynod-v3WgIjK`5gEOXk@?WCyPjdLE6?6FnC{419v32P z-ih}L*nk~0JA(B_5WBuI{MfCyo*Q>bJ0Y{wuA*X7$I7?TIacaDJ`uu#oNrSNTCv@r zt*y2^cj&8A9hLdfosHmbH*HJn>9V~=H1&IUDv{rc%X3gOr zxkL(Iuty!>>KrnDV}*R+5hefxzlnNr^S)GwfxmzLW*+4cIrmUn*Fc)~j#N$S#eA{g z9KQL-!sglwxvRB}@(-G9BY&=(p0|%9DbJ6UXSKhs@I~#Ys2nRDmrDS1ZeT~Q(&c;@ zud2A**;F~KJXucnR1Q=;mF*H*^=gHRmu63Y>I|i;Kh#7)t3!jy)cWEYQqQAXI#5Wml8r1R|Iifd`kJ#|u=$XQ}Nkw`BaDmo= zE#ZZ>3VI1}F?p@gtG#dkEBUGtTdn$Z!B|OZQ%jPvh~EnWR&C^{MRJj+6l?~xg{;Nx zIB`WQL284mA-7T8T}T5XC;DOU6nqu%DTbB{e(f%n4j7#*-VMobiYmZ}&Y%Jd)Yg!E zs+%>M*pUqi*#)hWNjrIz`RC2NmdAN$YjVu`^*j8#*ZeH9sc8GTiTM#MboMoYTAyuq zUT+lo9GTeY2Jq4A^7L-&SkT->=XL^FS3X9IL;z=8hi6`svdSF zaii{xXlD+`l_;Jk`g7N1eEX-bO<&mcJ&Baf50#k=DoIAFzzM5J>NA;*(&DMJ8L4AC zsM=l_sF_St>CA=m!$ZSE({}nak}whInM@-J&S_^``L;ggyG|79a4SCLg#I~O`_|4x zM*4Q(ZlNl)ilSK$#-wZ;TdFENM&jljK5?nb$N-gcCbQC*II$K0V$J0u-jlTPJj$ YzlQgDlga-