diff --git a/libexeinfo/ELF/ELF.cs b/libexeinfo/ELF/ELF.cs index 8e66e62..191dbb3 100644 --- a/libexeinfo/ELF/ELF.cs +++ b/libexeinfo/ELF/ELF.cs @@ -190,7 +190,7 @@ namespace libexeinfo buffer = new byte[sections[i].sh_size]; BaseStream.Read(buffer, 0, buffer.Length); - if(sectionNames[i] == ".interp" || sectionNames[i] == ".dynstr" || sectionNames[i] == ".comment") + if(sectionNames[i] == ".interp" || sectionNames[i] == ".dynstr" || sectionNames[i] == ".comment" || sectionNames[i] == ".strtab") { strStart = 0; len = 0; @@ -211,7 +211,7 @@ namespace libexeinfo len++; } } - else if(sectionNames[i].StartsWith(".note")) + else if(sectionNames[i].StartsWith(".note") && buffer.Length > 12) { uint namesz = BitConverter.ToUInt32(buffer, 0); uint descsz = BitConverter.ToUInt32(buffer, 4); @@ -237,10 +237,10 @@ namespace libexeinfo switch(Header.ei_class) { case eiClass.ELFCLASS32: - pos += pos % 4; + pos += pos % 4 != 0 ? 4 - (pos % 4) : 0; break; case eiClass.ELFCLASS64: - pos += pos % 8; + pos += pos % 8 != 0 ? 8 - (pos % 8) : 0; break; } @@ -260,7 +260,78 @@ namespace libexeinfo MajorVersion = (int)gnuAbiTag.major, MinorVersion = (int)gnuAbiTag.minor }; + else if(!string.IsNullOrEmpty(interpreter)) + RequiredOperatingSystem = new OperatingSystem {Name = interpreter}; } + else if(notes.TryGetValue(".note.netbsd.ident", out ElfNote netbsdIdent) && netbsdIdent.name == "NetBSD") + { + uint netbsdVersionConstant = BitConverter.ToUInt32(netbsdIdent.contents, 0); + if(IsBigEndian) netbsdVersionConstant = Swapping.Swap(netbsdVersionConstant); + + if(netbsdVersionConstant > 100000000) + { + RequiredOperatingSystem = new OperatingSystem + { + Name = "NetBSD", + MajorVersion = (int)(netbsdVersionConstant / 100000000), + MinorVersion = (int)((netbsdVersionConstant / 1000000) % 100) + }; + } + else + { + RequiredOperatingSystem = new OperatingSystem + { + Name = "NetBSD" + }; + } + } + else if(notes.TryGetValue(".note.minix.ident", out ElfNote minixIdent) && minixIdent.name == "Minix") + { + uint minixVersionConstant = BitConverter.ToUInt32(minixIdent.contents, 0); + if(IsBigEndian) minixVersionConstant = Swapping.Swap(minixVersionConstant); + + if(minixVersionConstant > 100000000) + { + RequiredOperatingSystem = new OperatingSystem + { + Name = "MINIX", + MajorVersion = (int)(minixVersionConstant / 100000000), + MinorVersion = (int)((minixVersionConstant / 1000000) % 100) + }; + } + else + { + RequiredOperatingSystem = new OperatingSystem + { + Name = "MINIX" + }; + } + } + else if(notes.TryGetValue(".note.openbsd.ident", out ElfNote openbsdIdent) && openbsdIdent.name == "OpenBSD") + { + RequiredOperatingSystem = new OperatingSystem + { + Name = "OpenBSD" + }; + } + else if(notes.TryGetValue(".note.tag", out ElfNote freebsdTag) && freebsdTag.name == "FreeBSD") + { + uint freebsdVersionConstant = BitConverter.ToUInt32(freebsdTag.contents, 0); + if(IsBigEndian) freebsdVersionConstant = Swapping.Swap(freebsdVersionConstant); + + FreeBSDTag freeBsdVersion = DecodeFreeBSDTag(freebsdVersionConstant); + + RequiredOperatingSystem = new OperatingSystem + { + Name = "FreeBSD", + MajorVersion = (int)freeBsdVersion.major, + MinorVersion = (int)freeBsdVersion.minor + }; + } + + else if(!string.IsNullOrEmpty(interpreter)) + RequiredOperatingSystem = new OperatingSystem {Name = interpreter}; + if(strings.Count > 0) { diff --git a/libexeinfo/ELF/Enums.cs b/libexeinfo/ELF/Enums.cs index 98ec325..7ce2134 100644 --- a/libexeinfo/ELF/Enums.cs +++ b/libexeinfo/ELF/Enums.cs @@ -944,7 +944,11 @@ namespace libexeinfo enum GnuAbiSystem : uint { - Linux = 0 + Linux = 0, + Hurd = 1, + Solaris = 2, + kFreeBSD = 3, + kNetBSD = 4 } } } \ No newline at end of file diff --git a/libexeinfo/ELF/FreeBSD.cs b/libexeinfo/ELF/FreeBSD.cs new file mode 100644 index 0000000..e73082c --- /dev/null +++ b/libexeinfo/ELF/FreeBSD.cs @@ -0,0 +1,34 @@ +namespace libexeinfo +{ + public partial class ELF + { + static FreeBSDTag DecodeFreeBSDTag(uint desc) + { + FreeBSDTag tag = new FreeBSDTag {major = desc / 100000}; + + if(desc == 460002) + { + tag.major = 4; + tag.minor = 6; + tag.revision = 2; + } + else if(desc < 460100) + { + tag.minor = desc / 10000 % 10; + if(desc / 1000 % 10 > 0) tag.revision = desc / 1000 % 10; + } + else if(desc < 500000) + { + tag.minor = desc / 10000 % 10 + desc / 1000 % 10; + if(desc / 10 % 10 > 0) tag.revision = desc / 10 % 10; + } + else + { + tag.minor = desc / 1000 % 100; + if(desc / 10 % 10 > 0) tag.revision = desc / 10 % 10; + } + + return tag; + } + } +} \ No newline at end of file diff --git a/libexeinfo/ELF/Info.cs b/libexeinfo/ELF/Info.cs index e562391..8899697 100644 --- a/libexeinfo/ELF/Info.cs +++ b/libexeinfo/ELF/Info.cs @@ -1,4 +1,5 @@ -using System.Text; +using System; +using System.Text; namespace libexeinfo { @@ -83,12 +84,91 @@ namespace libexeinfo sb.AppendFormat("\t\t\tLength: {0} bytes", note.contents.Length).AppendLine(); } - if(notes.TryGetValue(".note.ABI-tag", out ElfNote abiTag)) + if(notes.TryGetValue(".note.ABI-tag", out ElfNote abiTag) && abiTag.name == "GNU") { GnuAbiTag gnuAbiTag = DecodeGnuAbiTag(abiTag, IsBigEndian); - if(gnuAbiTag != null) - sb.AppendFormat("\tGNU ABI tag: Requires {0} version {1}.{2}.{3}", gnuAbiTag.system, - gnuAbiTag.major, gnuAbiTag.minor, gnuAbiTag.revision).AppendLine(); + sb.AppendFormat("\tGNU ABI tag: Requires {0} version {1}.{2}.{3}", gnuAbiTag.system, + gnuAbiTag.major, gnuAbiTag.minor, gnuAbiTag.revision).AppendLine(); + } + + if(notes.TryGetValue(".note.netbsd.ident", out ElfNote netbsdIdent) && netbsdIdent.name == "NetBSD") + { + uint netbsdVersionConstant = BitConverter.ToUInt32(netbsdIdent.contents, 0); + if(IsBigEndian) netbsdVersionConstant = Swapping.Swap(netbsdVersionConstant); + + if(netbsdVersionConstant > 100000000) + { + uint nbsdPatch = (netbsdVersionConstant / 100) % 100; + uint nbsdRel = (netbsdVersionConstant / 10000) % 100; + uint nbsdMinor = (netbsdVersionConstant / 1000000) % 100; + uint nbsdMajor = netbsdVersionConstant / 100000000; + + sb.AppendFormat("\tNetBSD version: {0}.{1}", nbsdMajor, nbsdMinor); + + if(nbsdRel == 0 && nbsdPatch != 0) sb.AppendFormat(".{0}", nbsdPatch); + else if(nbsdRel != 0) + { + while(nbsdRel > 26) + { + sb.Append("Z"); + nbsdRel -= 26; + } + + sb.AppendFormat("{0}", (char)('A' + nbsdRel - 1)); + } + + sb.AppendLine(); + } + else + { + sb.AppendFormat("\tNetBSD version constant: {0}", netbsdVersionConstant).AppendLine(); + } + } + + if(notes.TryGetValue(".note.minix.ident", out ElfNote minixIdent) && minixIdent.name == "Minix") + { + uint minixVersionConstant = BitConverter.ToUInt32(minixIdent.contents, 0); + if(IsBigEndian) minixVersionConstant = Swapping.Swap(minixVersionConstant); + + if(minixVersionConstant > 100000000) + { + uint minixPath = (minixVersionConstant / 100) % 100; + uint minixRel = (minixVersionConstant / 10000) % 100; + uint minixMinor = (minixVersionConstant / 1000000) % 100; + uint minixMajor = minixVersionConstant / 100000000; + + sb.AppendFormat("\tMINIX version: {0}.{1}", minixMajor, minixMinor); + + if(minixRel == 0 && minixPath != 0) sb.AppendFormat(".{0}", minixPath); + else if(minixRel != 0) + { + while(minixRel > 26) + { + sb.Append("Z"); + minixRel -= 26; + } + + sb.AppendFormat("{0}", (char)('A' + minixRel - 1)); + } + + sb.AppendLine(); + } + else + { + sb.AppendFormat("\tMINIX version constant: {0}", minixVersionConstant).AppendLine(); + } + } + + if(notes.TryGetValue(".note.tag", out ElfNote freebsdTag) && freebsdTag.name == "FreeBSD") + { + uint freebsdVersionConstant = BitConverter.ToUInt32(freebsdTag.contents, 0); + if(IsBigEndian) freebsdVersionConstant = Swapping.Swap(freebsdVersionConstant); + + FreeBSDTag freeBsdVersion = DecodeFreeBSDTag(freebsdVersionConstant); + + sb.AppendFormat("\tFreeBSD version: {0}.{1}"); + if(freeBsdVersion.revision > 0) sb.AppendFormat("{0}", freeBsdVersion.revision); + sb.AppendLine(); } if(notes.TryGetValue(".note.gnu.build-id", out ElfNote buildId)) diff --git a/libexeinfo/ELF/Structs.cs b/libexeinfo/ELF/Structs.cs index 6d62ba1..803f00e 100644 --- a/libexeinfo/ELF/Structs.cs +++ b/libexeinfo/ELF/Structs.cs @@ -384,5 +384,12 @@ namespace libexeinfo public uint minor; public uint revision; } + + struct FreeBSDTag + { + public uint major; + public uint minor; + public uint revision; + } } } \ No newline at end of file diff --git a/libexeinfo/libexeinfo.csproj b/libexeinfo/libexeinfo.csproj index 7c7b39a..9eb4087 100644 --- a/libexeinfo/libexeinfo.csproj +++ b/libexeinfo/libexeinfo.csproj @@ -57,6 +57,7 @@ +