Decode ELF GNU ABI tag and build ID.

This commit is contained in:
2018-03-13 18:33:05 +00:00
parent 3945a53fce
commit bb6b17800f
6 changed files with 99 additions and 21 deletions

View File

@@ -4,18 +4,17 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading;
namespace libexeinfo namespace libexeinfo
{ {
public partial class ELF : IExecutable public partial class ELF : IExecutable
{ {
List<Architecture> architectures; List<Architecture> architectures;
Elf64_Ehdr Header; Elf64_Ehdr Header;
string interpreter; string interpreter;
string[] sectionNames;
Elf64_Shdr[] sections;
Dictionary<string, ElfNote> notes; Dictionary<string, ElfNote> notes;
string[] sectionNames;
Elf64_Shdr[] sections;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:libexeinfo.ELF" /> class. /// Initializes a new instance of the <see cref="T:libexeinfo.ELF" /> class.
@@ -58,7 +57,7 @@ namespace libexeinfo
public IEnumerable<Architecture> Architectures => architectures; public IEnumerable<Architecture> Architectures => architectures;
public OperatingSystem RequiredOperatingSystem { get; private set; } public OperatingSystem RequiredOperatingSystem { get; private set; }
public IEnumerable<string> Strings { get; private set; } public IEnumerable<string> Strings { get; private set; }
public IEnumerable<Segment> Segments { get; } public IEnumerable<Segment> Segments { get; private set; }
/// <summary> /// <summary>
/// The <see cref="FileStream" /> that contains the executable represented by this instance /// The <see cref="FileStream" /> that contains the executable represented by this instance
@@ -181,7 +180,7 @@ namespace libexeinfo
len++; len++;
} }
notes = new Dictionary<string, ElfNote>(); notes = new Dictionary<string, ElfNote>();
// Sections that contain an array of null-terminated strings by definition // Sections that contain an array of null-terminated strings by definition
@@ -214,40 +213,55 @@ namespace libexeinfo
} }
else if(sectionNames[i].StartsWith(".note")) else if(sectionNames[i].StartsWith(".note"))
{ {
uint namesz = BitConverter.ToUInt32(buffer, 0); uint namesz = BitConverter.ToUInt32(buffer, 0);
uint descsz = BitConverter.ToUInt32(buffer, 4); uint descsz = BitConverter.ToUInt32(buffer, 4);
uint notetype = BitConverter.ToUInt32(buffer, 8); uint notetype = BitConverter.ToUInt32(buffer, 8);
pos = 12; pos = 12;
if(IsBigEndian) if(IsBigEndian)
{ {
namesz= Swapping.Swap(namesz); namesz = Swapping.Swap(namesz);
descsz = Swapping.Swap(descsz); descsz = Swapping.Swap(descsz);
notetype = Swapping.Swap(notetype); notetype = Swapping.Swap(notetype);
} }
ElfNote note = new ElfNote ElfNote note = new ElfNote
{ {
name = Encoding.ASCII.GetString(buffer, pos, (int)(namesz - 1)), name = Encoding.ASCII.GetString(buffer, pos, (int)(namesz - 1)),
type = notetype, type = notetype,
contents = new byte[descsz] contents = new byte[descsz]
}; };
pos += (int)namesz; pos += (int)namesz;
switch(Header.ei_class) { switch(Header.ei_class)
case eiClass.ELFCLASS32: pos += pos % 4; {
case eiClass.ELFCLASS32:
pos += pos % 4;
break; break;
case eiClass.ELFCLASS64: pos += pos % 8; case eiClass.ELFCLASS64:
pos += pos % 8;
break; break;
} }
Array.Copy(buffer, pos, note.contents, 0, descsz); Array.Copy(buffer, pos, note.contents, 0, descsz);
notes.Add(sectionNames[i], note); notes.Add(sectionNames[i], note);
} }
} }
if(notes.TryGetValue(".note.ABI-tag", out ElfNote abiTag))
{
GnuAbiTag gnuAbiTag = DecodeGnuAbiTag(abiTag, IsBigEndian);
if(gnuAbiTag != null)
RequiredOperatingSystem = new OperatingSystem
{
Name = $"{gnuAbiTag.system}",
MajorVersion = (int)gnuAbiTag.major,
MinorVersion = (int)gnuAbiTag.minor
};
}
if(strings.Count > 0) if(strings.Count > 0)
{ {
strings.Remove(null); strings.Remove(null);
@@ -255,6 +269,8 @@ namespace libexeinfo
strings.Sort(); strings.Sort();
Strings = strings.Distinct(); Strings = strings.Distinct();
} }
Segments = segments;
} }
static Elf64_Ehdr UpBits(byte[] buffer, bool bigEndian) static Elf64_Ehdr UpBits(byte[] buffer, bool bigEndian)

View File

@@ -941,5 +941,10 @@ namespace libexeinfo
/// <summary>PA-RISC 2.0</summary> /// <summary>PA-RISC 2.0</summary>
EFA_PARISC_2_0 = 0x0214 EFA_PARISC_2_0 = 0x0214
} }
enum GnuAbiSystem : uint
{
Linux = 0
}
} }
} }

37
libexeinfo/ELF/GNU.cs Normal file
View File

@@ -0,0 +1,37 @@
using System;
using System.Text;
namespace libexeinfo
{
public partial class ELF
{
static GnuAbiTag DecodeGnuAbiTag(ElfNote note, bool bigEndian)
{
if(note.name != "GNU") return null;
return bigEndian
? new GnuAbiTag
{
system = (GnuAbiSystem)Swapping.Swap(BitConverter.ToUInt32(note.contents, 0)),
major = Swapping.Swap(BitConverter.ToUInt32(note.contents, 4)),
minor = Swapping.Swap(BitConverter.ToUInt32(note.contents, 8)),
revision = Swapping.Swap(BitConverter.ToUInt32(note.contents, 0))
}
: new GnuAbiTag
{
system = (GnuAbiSystem)BitConverter.ToUInt32(note.contents, 0),
major = BitConverter.ToUInt32(note.contents, 4),
minor = BitConverter.ToUInt32(note.contents, 8),
revision = BitConverter.ToUInt32(note.contents, 0)
};
}
static string DecodeGnuBuildId(ElfNote note)
{
StringBuilder sb = new StringBuilder();
foreach(byte b in note.contents) { sb.AppendFormat("{0:x2}", b); }
return sb.ToString();
}
}
}

View File

@@ -74,7 +74,7 @@ namespace libexeinfo
sb.AppendFormat("\t\tSection is aligned to {0} bytes", sections[i].sh_addralign).AppendLine(); sb.AppendFormat("\t\tSection is aligned to {0} bytes", sections[i].sh_addralign).AppendLine();
if(sections[i].sh_entsize > 0) if(sections[i].sh_entsize > 0)
sb.AppendFormat("\t\tIndex to name: {0}", sections[i].sh_entsize).AppendLine(); sb.AppendFormat("\t\tIndex to name: {0}", sections[i].sh_entsize).AppendLine();
if(!notes.TryGetValue(sectionNames[i], out ElfNote note)) continue; if(!notes.TryGetValue(sectionNames[i], out ElfNote note)) continue;
sb.AppendLine("\t\tNote contents:"); sb.AppendLine("\t\tNote contents:");
@@ -83,6 +83,17 @@ namespace libexeinfo
sb.AppendFormat("\t\t\tLength: {0} bytes", note.contents.Length).AppendLine(); sb.AppendFormat("\t\t\tLength: {0} bytes", note.contents.Length).AppendLine();
} }
if(notes.TryGetValue(".note.ABI-tag", out ElfNote abiTag))
{
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();
}
if(notes.TryGetValue(".note.gnu.build-id", out ElfNote buildId))
sb.AppendFormat("\tGNU build ID: {0}", DecodeGnuBuildId(buildId));
return sb.ToString(); return sb.ToString();
} }
} }

View File

@@ -376,5 +376,13 @@ namespace libexeinfo
public uint type; public uint type;
public byte[] contents; public byte[] contents;
} }
class GnuAbiTag
{
public GnuAbiSystem system;
public uint major;
public uint minor;
public uint revision;
}
} }
} }

View File

@@ -57,6 +57,7 @@
<Compile Include="ELF\Consts.cs" /> <Compile Include="ELF\Consts.cs" />
<Compile Include="ELF\ELF.cs" /> <Compile Include="ELF\ELF.cs" />
<Compile Include="ELF\Enums.cs" /> <Compile Include="ELF\Enums.cs" />
<Compile Include="ELF\GNU.cs" />
<Compile Include="ELF\Info.cs" /> <Compile Include="ELF\Info.cs" />
<Compile Include="ELF\Structs.cs" /> <Compile Include="ELF\Structs.cs" />
<Compile Include="Enums.cs" /> <Compile Include="Enums.cs" />