This commit is contained in:
n1474335 2022-06-09 15:04:46 +01:00
commit 23b168515c
6 changed files with 1381 additions and 3 deletions

View File

@ -413,7 +413,8 @@
"Extract RGBA",
"View Bit Plane",
"Randomize Colour Palette",
"Extract LSB"
"Extract LSB",
"ELF Info"
]
},
{

View File

@ -48,12 +48,14 @@ export default class Stream {
* Interpret the following bytes as a string, stopping at the next null byte or
* the supplied limit.
*
* @param {number} numBytes
* @param {number} [numBytes=-1]
* @returns {string}
*/
readString(numBytes) {
readString(numBytes=-1) {
if (this.position > this.length) return undefined;
if (numBytes === -1) numBytes = this.length - this.position;
let result = "";
for (let i = this.position; i < this.position + numBytes; i++) {
const currentByte = this.bytes[i];

View File

@ -0,0 +1,913 @@
/**
* @author n1073645 [n1073645@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Stream from "../lib/Stream.mjs";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* ELF Info operation
*/
class ELFInfo extends Operation {
/**
* ELFInfo constructor
*/
constructor() {
super();
this.name = "ELF Info";
this.module = "Default";
this.description = "Implements readelf-like functionality. This operation will extract the ELF Header, Program Headers, Section Headers and Symbol Table for an ELF file.";
this.infoURL = "https://www.wikipedia.org/wiki/Executable_and_Linkable_Format";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
let phoff = 0;
let phEntries = 0;
let shoff = 0;
let shEntries = 0;
let shentSize = 0;
let entry = 0;
let format = 0;
let endianness = "";
let shstrtab = 0;
let namesOffset = 0;
let symtabOffset = 0;
let symtabSize = 0;
let symtabEntSize = 0;
let strtabOffset = 0;
const align = 30;
/**
* This function reads characters until it hits a null terminator.
*
* @param {stream} stream
* @param {integer} namesOffset
* @param {integer} nameOffset
* @returns {string}
*/
function readString(stream, namesOffset, nameOffset) {
const preMove = stream.position;
stream.moveTo(namesOffset + nameOffset);
const nameResult = stream.readString();
stream.moveTo(preMove);
return nameResult;
}
/**
* This function parses and extracts relevant information from the ELF Header.
*
* @param {stream} stream
* @returns {string}
*/
function elfHeader(stream) {
/**
* The ELF Header is comprised of the following structures depending on the binary's format.
*
* e_ident - The Magic Number 0x7F,0x45,0x4c,0x46
* - Byte set to 1 or 2 to signify 32-bit or 64-bit format, respectively.
* - Byte set to 1 or 2 to signify little of big endianness, respectively.
* - Byte set to 1 for the version of ELF.
* - Byte identifying the target OS ABI.
* - Byte further identifying the OS ABI Version.
* - 7 Padding Bytes.
* e_type - 2 bytes identifying the object file type.
* e_machine - 2 bytes identifying the instruction set architecture.
* e_version - Byte set to 1 for the version of ELF.
*
* 32-bit:
* e_entry - 4 Bytes specifying the entry point.
* e_phoff - 4 Bytes specifying the offset of the Program Header Table.
* e_shoff - 4 Bytes specifying the offset of the Section Header Table.
*
* 64-bit:
* e_entry - 8 Bytes specifying the entry point.
* e_phoff - 8 Bytes specifying the offset of the Program Header Table.
* e_shoff - 8 Bytes specifying the offset of the Section Header Table.
*
* e_flags - 4 Bytes specifying processor specific flags.
* e_ehsize - 2 Bytes specifying the size of the ELF Header.
* e_phentsize - 2 Bytes specifying the size of a Program Header Table Entry.
* e_phnum - 2 Bytes specifying the number of entries in the Program Header Table.
* e_shentsize - 2 Bytes specifying the size of a Section Header Table Entry.
* e_shnum - 2 Bytes specifying the number of entries in the Section Header Table.
* e_shstrndx - 2 Bytes specifying the index of the section containing the section names in the Section Header Table.
*/
const ehResult = [];
const magic = stream.getBytes(4);
if (magic.join("") !== [0x7f, 0x45, 0x4c, 0x46].join(""))
throw new OperationError("Invalid ELF");
ehResult.push("Magic:".padEnd(align) + `${Utils.byteArrayToChars(magic)}`);
format = stream.readInt(1);
ehResult.push("Format:".padEnd(align) + `${format === 1 ? "32-bit" : "64-bit"}`);
endianness = stream.readInt(1) === 1 ? "le" : "be";
ehResult.push("Endianness:".padEnd(align) + `${endianness === "le" ? "Little" : "Big"}`);
ehResult.push("Version:".padEnd(align) + `${stream.readInt(1).toString()}`);
let ABI = "";
switch (stream.readInt(1)) {
case 0x00:
ABI = "System V";
break;
case 0x01:
ABI = "HP-UX";
break;
case 0x02:
ABI = "NetBSD";
break;
case 0x03:
ABI = "Linux";
break;
case 0x04:
ABI = "GNU Hurd";
break;
case 0x06:
ABI = "Solaris";
break;
case 0x07:
ABI = "AIX";
break;
case 0x08:
ABI = "IRIX";
break;
case 0x09:
ABI = "FreeBSD";
break;
case 0x0A:
ABI = "Tru64";
break;
case 0x0B:
ABI = "Novell Modesto";
break;
case 0x0C:
ABI = "OpenBSD";
break;
case 0x0D:
ABI = "OpenVMS";
break;
case 0x0E:
ABI = "NonStop Kernel";
break;
case 0x0F:
ABI = "AROS";
break;
case 0x10:
ABI = "Fenix OS";
break;
case 0x11:
ABI = "CloudABI";
break;
case 0x12:
ABI = "Stratus Technologies OpenVOS";
break;
default:
break;
}
ehResult.push("ABI:".padEnd(align) + ABI);
// Linux Kernel does not use ABI Version.
const abiVersion = stream.readInt(1).toString();
if (ABI !== "Linux")
ehResult.push("ABI Version:".padEnd(align) + abiVersion);
stream.moveForwardsBy(7);
let eType = "";
switch (stream.readInt(2, endianness)) {
case 0x0000:
eType = "Unknown";
break;
case 0x0001:
eType = "Relocatable File";
break;
case 0x0002:
eType = "Executable File";
break;
case 0x0003:
eType = "Shared Object";
break;
case 0x0004:
eType = "Core File";
break;
case 0xFE00:
eType = "LOOS";
break;
case 0xFEFF:
eType = "HIOS";
break;
case 0xFF00:
eType = "LOPROC";
break;
case 0xFFFF:
eType = "HIPROC";
break;
default:
break;
}
ehResult.push("Type:".padEnd(align) + eType);
let ISA = "";
switch (stream.readInt(2, endianness)) {
case 0x0000:
ISA = "No specific instruction set";
break;
case 0x0001:
ISA = "AT&T WE 32100";
break;
case 0x0002:
ISA = "SPARC";
break;
case 0x0003:
ISA = "x86";
break;
case 0x0004:
ISA = "Motorola 68000 (M68k)";
break;
case 0x0005:
ISA = "Motorola 88000 (M88k)";
break;
case 0x0006:
ISA = "Intel MCU";
break;
case 0x0007:
ISA = "Intel 80860";
break;
case 0x0008:
ISA = "MIPS";
break;
case 0x0009:
ISA = "IBM System/370";
break;
case 0x000A:
ISA = "MIPS RS3000 Little-endian";
break;
case 0x000B:
case 0x000C:
case 0x000D:
case 0x000E:
case 0x0018:
case 0x0019:
case 0x001A:
case 0x001B:
case 0x001C:
case 0x001D:
case 0x001E:
case 0x001F:
case 0x0020:
case 0x0021:
case 0x0022:
case 0x0023:
ISA = "Reserved for future use";
break;
case 0x000F:
ISA = "Hewlett-Packard PA-RISC";
break;
case 0x0011:
ISA = "Fujitsu VPP500";
break;
case 0x0012:
ISA = "Enhanced instruction set SPARC";
break;
case 0x0013:
ISA = "Intel 80960";
break;
case 0x0014:
ISA = "PowerPC";
break;
case 0x0015:
ISA = "PowerPC (64-bit)";
break;
case 0x0016:
ISA = "S390, including S390";
break;
case 0x0017:
ISA = "IBM SPU/SPC";
break;
case 0x0024:
ISA = "NEC V800";
break;
case 0x0025:
ISA = "Fujitsu FR20";
break;
case 0x0026:
ISA = "TRW RH-32";
break;
case 0x0027:
ISA = "Motorola RCE";
break;
case 0x0028:
ISA = "ARM (up to ARMv7/Aarch32)";
break;
case 0x0029:
ISA = "Digital Alpha";
break;
case 0x002A:
ISA = "SuperH";
break;
case 0x002B:
ISA = "SPARC Version 9";
break;
case 0x002C:
ISA = "Siemens TriCore embedded processor";
break;
case 0x002D:
ISA = "Argonaut RISC Core";
break;
case 0x002E:
ISA = "Hitachi H8/300";
break;
case 0x002F:
ISA = "Hitachi H8/300H";
break;
case 0x0030:
ISA = "Hitachi H8S";
break;
case 0x0031:
ISA = "Hitachi H8/500";
break;
case 0x0032:
ISA = "IA-64";
break;
case 0x0033:
ISA = "Standford MIPS-X";
break;
case 0x0034:
ISA = "Motorola ColdFire";
break;
case 0x0035:
ISA = "Motorola M68HC12";
break;
case 0x0036:
ISA = "Fujitsu MMA Multimedia Accelerator";
break;
case 0x0037:
ISA = "Siemens PCP";
break;
case 0x0038:
ISA = "Sony nCPU embedded RISC processor";
break;
case 0x0039:
ISA = "Denso NDR1 microprocessor";
break;
case 0x003A:
ISA = "Motorola Star*Core processor";
break;
case 0x003B:
ISA = "Toyota ME16 processor";
break;
case 0x003C:
ISA = "STMicroelectronics ST100 processor";
break;
case 0x003D:
ISA = "Advanced Logic Corp. TinyJ embedded processor family";
break;
case 0x003E:
ISA = "AMD x86-64";
break;
case 0x003F:
ISA = "Sony DSP Processor";
break;
case 0x0040:
ISA = "Digital Equipment Corp. PDP-10";
break;
case 0x0041:
ISA = "Digital Equipment Corp. PDP-11";
break;
case 0x0042:
ISA = "Siemens FX66 microcontroller";
break;
case 0x0043:
ISA = "STMicroelectronics ST9+ 8/16 bit microcontroller";
break;
case 0x0044:
ISA = "STMicroelectronics ST7 8-bit microcontroller";
break;
case 0x0045:
ISA = "Motorola MC68HC16 Microcontroller";
break;
case 0x0046:
ISA = "Motorola MC68HC11 Microcontroller";
break;
case 0x0047:
ISA = "Motorola MC68HC08 Microcontroller";
break;
case 0x0048:
ISA = "Motorola MC68HC05 Microcontroller";
break;
case 0x0049:
ISA = "Silicon Graphics SVx";
break;
case 0x004A:
ISA = "STMicroelectronics ST19 8-bit microcontroller";
break;
case 0x004B:
ISA = "Digital VAX";
break;
case 0x004C:
ISA = "Axis Communications 32-bit embedded processor";
break;
case 0x004D:
ISA = "Infineon Technologies 32-bit embedded processor";
break;
case 0x004E:
ISA = "Element 14 64-bit DSP Processor";
break;
case 0x004F:
ISA = "LSI Logic 16-bit DSP Processor";
break;
case 0x0050:
ISA = "Donald Knuth's educational 64-bit processor";
break;
case 0x0051:
ISA = "Harvard University machine-independent object files";
break;
case 0x0052:
ISA = "SiTera Prism";
break;
case 0x0053:
ISA = "Atmel AVR 8-bit microcontroller";
break;
case 0x0054:
ISA = "Fujitsu FR30";
break;
case 0x0055:
ISA = "Mitsubishi D10V";
break;
case 0x0056:
ISA = "Mitsubishi D30V";
break;
case 0x0057:
ISA = "NEC v850";
break;
case 0x0058:
ISA = "Mitsubishi M32R";
break;
case 0x0059:
ISA = "Matsushita MN10300";
break;
case 0x005A:
ISA = "Matsushita MN10200";
break;
case 0x005B:
ISA = "picoJava";
break;
case 0x005C:
ISA = "OpenRISC 32-bit embedded processor";
break;
case 0x005D:
ISA = "ARC Cores Tangent-A5";
break;
case 0x005E:
ISA = "Tensilica Xtensa Architecture";
break;
case 0x005F:
ISA = "Alphamosaic VideoCore processor";
break;
case 0x0060:
ISA = "Thompson Multimedia General Purpose Processor";
break;
case 0x0061:
ISA = "National Semiconductor 32000 series";
break;
case 0x0062:
ISA = "Tenor Network TPC processor";
break;
case 0x0063:
ISA = "Trebia SNP 1000 processor";
break;
case 0x0064:
ISA = "STMicroelectronics (www.st.com) ST200 microcontroller";
break;
case 0x008C:
ISA = "TMS320C6000 Family";
break;
case 0x00AF:
ISA = "MCST Elbrus e2k";
break;
case 0x00B7:
ISA = "ARM 64-bits (ARMv8/Aarch64)";
break;
case 0x00F3:
ISA = "RISC-V";
break;
case 0x00F7:
ISA = "Berkeley Packet Filter";
break;
case 0x0101:
ISA = "WDC 65C816";
break;
default:
ISA = "Unimplemented";
break;
}
ehResult.push("Instruction Set Architecture:".padEnd(align) + ISA);
ehResult.push("ELF Version:".padEnd(align) + `${stream.readInt(4, endianness)}`);
const readSize = format === 1 ? 4 : 8;
entry = stream.readInt(readSize, endianness);
phoff = stream.readInt(readSize, endianness);
shoff = stream.readInt(readSize, endianness);
ehResult.push("Entry Point:".padEnd(align) + `0x${Utils.hex(entry)}`);
ehResult.push("Entry PHOFF:".padEnd(align) + `0x${Utils.hex(phoff)}`);
ehResult.push("Entry SHOFF:".padEnd(align) + `0x${Utils.hex(shoff)}`);
const flags = stream.readInt(4, endianness);
ehResult.push("Flags:".padEnd(align) + `${Utils.bin(flags)}`);
ehResult.push("ELF Header Size:".padEnd(align) + `${stream.readInt(2, endianness)} bytes`);
ehResult.push("Program Header Size:".padEnd(align) + `${stream.readInt(2, endianness)} bytes`);
phEntries = stream.readInt(2, endianness);
ehResult.push("Program Header Entries:".padEnd(align) + phEntries);
shentSize = stream.readInt(2, endianness);
ehResult.push("Section Header Size:".padEnd(align) + shentSize + " bytes");
shEntries = stream.readInt(2, endianness);
ehResult.push("Section Header Entries:".padEnd(align) + shEntries);
shstrtab = stream.readInt(2, endianness);
ehResult.push("Section Header Names:".padEnd(align) + shstrtab);
return ehResult.join("\n");
}
/**
* This function parses and extracts relevant information from a Program Header.
*
* @param {stream} stream
* @returns {string}
*/
function programHeader(stream) {
/**
* A Program Header is comprised of the following structures depending on the binary's format.
*
* p_type - 4 Bytes identifying the type of the segment.
*
* 32-bit:
* p_offset - 4 Bytes specifying the offset of the segment.
* p_vaddr - 4 Bytes specifying the virtual address of the segment in memory.
* p_paddr - 4 Bytes specifying the physical address of the segment in memory.
* p_filesz - 4 Bytes specifying the size in bytes of the segment in the file image.
* p_memsz - 4 Bytes specifying the size in bytes of the segment in memory.
* p_flags - 4 Bytes identifying the segment dependent flags.
* p_align - 4 Bytes set to 0 or 1 for alignment or no alignment, respectively.
*
* 64-bit:
* p_flags - 4 Bytes identifying segment dependent flags.
* p_offset - 8 Bytes specifying the offset of the segment.
* p_vaddr - 8 Bytes specifying the virtual address of the segment in memory.
* p_paddr - 8 Bytes specifying the physical address of the segment in memory.
* p_filesz - 8 Bytes specifying the size in bytes of the segment in the file image.
* p_memsz - 8 Bytes specifying the size in bytes of the segment in memory.
* p_align - 8 Bytes set to 0 or 1 for alignment or no alignment, respectively.
*/
/**
* This function decodes the flags bitmask for the Program Header.
*
* @param {integer} flags
* @returns {string}
*/
function readFlags(flags) {
const result = [];
if (flags & 0x1)
result.push("Execute");
if (flags & 0x2)
result.push("Write");
if (flags & 0x4)
result.push("Read");
if (flags & 0xf0000000)
result.push("Unspecified");
return result.join(",");
}
const phResult = [];
let pType = "";
const programHeaderType = stream.readInt(4, endianness);
switch (true) {
case (programHeaderType === 0x00000000):
pType = "Unused";
break;
case (programHeaderType === 0x00000001):
pType = "Loadable Segment";
break;
case (programHeaderType === 0x00000002):
pType = "Dynamic linking information";
break;
case (programHeaderType === 0x00000003):
pType = "Interpreter Information";
break;
case (programHeaderType === 0x00000004):
pType = "Auxiliary Information";
break;
case (programHeaderType === 0x00000005):
pType = "Reserved";
break;
case (programHeaderType === 0x00000006):
pType = "Program Header Table";
break;
case (programHeaderType === 0x00000007):
pType = "Thread-Local Storage Template";
break;
case (programHeaderType >= 0x60000000 && programHeaderType <= 0x6FFFFFFF):
pType = "Reserved Inclusive Range. OS Specific";
break;
case (programHeaderType >= 0x70000000 && programHeaderType <= 0x7FFFFFFF):
pType = "Reserved Inclusive Range. Processor Specific";
break;
default:
break;
}
phResult.push("Program Header Type:".padEnd(align) + pType);
if (format === 2)
phResult.push("Flags:".padEnd(align) + readFlags(stream.readInt(4, endianness)));
const readSize = format === 1? 4 : 8;
phResult.push("Offset Of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)}`);
phResult.push("Virtual Address of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)}`);
phResult.push("Physical Address of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)}`);
phResult.push("Size of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)} bytes`);
phResult.push("Size of Segment in Memory:".padEnd(align) + `${stream.readInt(readSize, endianness)} bytes`);
if (format === 1)
phResult.push("Flags:".padEnd(align) + readFlags(stream.readInt(4, endianness)));
stream.moveForwardsBy(readSize);
return phResult.join("\n");
}
/**
* This function parses and extracts relevant information from a Section Header.
*
* @param {stream} stream
* @returns {string}
*/
function sectionHeader(stream) {
/**
* A Section Header is comprised of the following structures depending on the binary's format.
*
* sh_name - 4 Bytes identifying the offset into the .shstrtab for the name of this section.
* sh_type - 4 Bytes identifying the type of this header.
*
* 32-bit:
* sh_flags - 4 Bytes identifying section specific flags.
* sh_addr - 4 Bytes identifying the virtual address of the section in memory.
* sh_offset - 4 Bytes identifying the offset of the section in the file.
* sh_size - 4 Bytes specifying the size in bytes of the section in the file image.
* sh_link - 4 Bytes identifying the index of an associated section.
* sh_info - 4 Bytes specifying extra information about the section.
* sh_addralign - 4 Bytes containing the alignment for the section.
* sh_entsize - 4 Bytes specifying the size, in bytes, of each entry in the section.
*
* 64-bit:
* sh_flags - 8 Bytes identifying section specific flags.
* sh_addr - 8 Bytes identifying the virtual address of the section in memory.
* sh_offset - 8 Bytes identifying the offset of the section in the file.
* sh_size - 8 Bytes specifying the size in bytes of the section in the file image.
* sh_link - 4 Bytes identifying the index of an associated section.
* sh_info - 4 Bytes specifying extra information about the section.
* sh_addralign - 8 Bytes containing the alignment for the section.
* sh_entsize - 8 Bytes specifying the size, in bytes, of each entry in the section.
*/
const shResult = [];
const nameOffset = stream.readInt(4, endianness);
let type = "";
const shType = stream.readInt(4, endianness);
switch (true) {
case (shType === 0x00000001):
type = "Program Data";
break;
case (shType === 0x00000002):
type = "Symbol Table";
break;
case (shType === 0x00000003):
type = "String Table";
break;
case (shType === 0x00000004):
type = "Relocation Entries with Addens";
break;
case (shType === 0x00000005):
type = "Symbol Hash Table";
break;
case (shType === 0x00000006):
type = "Dynamic Linking Information";
break;
case (shType === 0x00000007):
type = "Notes";
break;
case (shType === 0x00000008):
type = "Program Space with No Data";
break;
case (shType === 0x00000009):
type = "Relocation Entries with no Addens";
break;
case (shType === 0x0000000A):
type = "Reserved";
break;
case (shType === 0x0000000B):
type = "Dynamic Linker Symbol Table";
break;
case (shType === 0x0000000E):
type = "Array of Constructors";
break;
case (shType === 0x0000000F):
type = "Array of Destructors";
break;
case (shType === 0x00000010):
type = "Array of pre-constructors";
break;
case (shType === 0x00000011):
type = "Section group";
break;
case (shType === 0x00000012):
type = "Extended section indices";
break;
case (shType === 0x00000013):
type = "Number of defined types";
break;
case (shType >= 0x60000000 && shType <= 0x6fffffff):
type = "OS-specific";
break;
case (shType >= 0x70000000 && shType <= 0x7fffffff):
type = "Processor-specific";
break;
case (shType >= 0x80000000 && shType <= 0x8fffffff):
type = "Application-specific";
break;
default:
type = "Unused";
break;
}
shResult.push("Type:".padEnd(align) + type);
let nameResult = "";
if (type !== "Unused") {
nameResult = readString(stream, namesOffset, nameOffset);
shResult.push("Section Name: ".padEnd(align) + nameResult);
}
const readSize = (format === 1) ? 4 : 8;
const flags = stream.readInt(readSize, endianness);
const shFlags = [];
const bitMasks = [
[0x00000001, "Writable"],
[0x00000002, "Alloc"],
[0x00000004, "Executable"],
[0x00000010, "Merge"],
[0x00000020, "Strings"],
[0x00000040, "SHT Info Link"],
[0x00000080, "Link Order"],
[0x00000100, "OS Specific Handling"],
[0x00000200, "Group"],
[0x00000400, "Thread Local Data"],
[0x0FF00000, "OS-Specific"],
[0xF0000000, "Processor Specific"],
[0x04000000, "Special Ordering (Solaris)"],
[0x08000000, "Excluded (Solaris)"]
];
bitMasks.forEach(elem => {
if (flags & elem[0])
shFlags.push(elem[1]);
});
shResult.push("Flags:".padEnd(align) + shFlags);
const vaddr = stream.readInt(readSize, endianness);
shResult.push("Section Vaddr in memory:".padEnd(align) + vaddr);
const shoffset = stream.readInt(readSize, endianness);
shResult.push("Offset of the section:".padEnd(align) + shoffset);
const secSize = stream.readInt(readSize, endianness);
shResult.push("Section Size:".padEnd(align) + secSize);
const associatedSection = stream.readInt(4, endianness);
shResult.push("Associated Section:".padEnd(align) + associatedSection);
const extraInfo = stream.readInt(4, endianness);
shResult.push("Section Extra Information:".padEnd(align) + extraInfo);
// Jump over alignment field.
stream.moveForwardsBy(readSize);
const entSize = stream.readInt(readSize, endianness);
switch (nameResult) {
case ".strtab":
strtabOffset = shoffset;
break;
case ".symtab":
symtabOffset = shoffset;
symtabSize = secSize;
symtabEntSize = entSize;
break;
default:
break;
}
return shResult.join("\n");
}
/**
* This function returns the offset of the Section Header Names Section.
*
* @param {stream} stream
*/
function getNamesOffset(stream) {
const preMove = stream.position;
stream.moveTo(shoff + (shentSize * shstrtab));
if (format === 1) {
stream.moveForwardsBy(0x10);
namesOffset = stream.readInt(4, endianness);
} else {
stream.moveForwardsBy(0x18);
namesOffset = stream.readInt(8, endianness);
}
stream.position = preMove;
}
/**
* This function returns a symbol's name from the string table.
*
* @param {stream} stream
* @returns {string}
*/
function getSymbols(stream) {
/**
* The Symbol Table is comprised of Symbol Table Entries whose structure depends on the binary's format.
*
* 32-bit:
* st_name - 4 Bytes specifying an index in the files symbol string table.
* st_value - 4 Bytes identifying the value associated with the symbol.
* st_size - 4 Bytes specifying the size associated with the symbol (this is not the size of the symbol).
* st_info - A byte specifying the type and binding of the symbol.
* st_other - A byte specifying the symbol's visibility.
* st_shndx - 2 Bytes identifying the section that this symbol is related to.
*
* 64-bit:
* st_name - 4 Bytes specifying an index in the files symbol string table.
* st_info - A byte specifying the type and binding of the symbol.
* st_other - A byte specifying the symbol's visibility.
* st_shndx - 2 Bytes identifying the section that this symbol is related to.
* st_value - 8 Bytes identifying the value associated with the symbol.
* st_size - 8 Bytes specifying the size associated with the symbol (this is not the size of the symbol).
*/
const nameOffset = stream.readInt(4, endianness);
stream.moveForwardsBy(format === 2 ? 20 : 12);
return readString(stream, strtabOffset, nameOffset);
}
input = new Uint8Array(input);
const stream = new Stream(input);
const result = ["=".repeat(align) + " ELF Header " + "=".repeat(align)];
result.push(elfHeader(stream) + "\n");
getNamesOffset(stream);
result.push("=".repeat(align) + " Program Header " + "=".repeat(align));
stream.moveTo(phoff);
for (let i = 0; i < phEntries; i++)
result.push(programHeader(stream) + "\n");
result.push("=".repeat(align) + " Section Header " + "=".repeat(align));
stream.moveTo(shoff);
for (let i = 0; i < shEntries; i++)
result.push(sectionHeader(stream) + "\n");
result.push("=".repeat(align) + " Symbol Table " + "=".repeat(align));
stream.moveTo(symtabOffset);
let elem = "";
for (let i = 0; i < (symtabSize / symtabEntSize); i++)
if ((elem = getSymbols(stream)) !== "")
result.push("Symbol Name:".padEnd(align) + elem);
return result.join("\n");
}
}
export default ELFInfo;

View File

@ -113,6 +113,7 @@ import "./tests/JA3SFingerprint.mjs";
import "./tests/HASSH.mjs";
import "./tests/GetAllCasings.mjs";
import "./tests/SIGABA.mjs";
import "./tests/ELFInfo.mjs";
// Cannot test operations that use the File type yet

View File

@ -0,0 +1,86 @@
/**
* @author n1073645 [n1073645@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
import {ELF32_LE, ELF32_BE, ELF64_LE, ELF64_BE} from "../../samples/Executables.mjs";
const ELF32_LE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 32-bit\nEndianness: Little\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: x86\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x34\nEntry SHOFF: 0x54\nFlags: 00000000\nELF Header Size: 52 bytes\nProgram Header Size: 32 bytes\nProgram Header Entries: 1\nSection Header Size: 40 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\nFlags: Execute,Read\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 204\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 230\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 245\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
const ELF32_BE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 32-bit\nEndianness: Big\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: x86\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x34\nEntry SHOFF: 0x54\nFlags: 00000000\nELF Header Size: 52 bytes\nProgram Header Size: 32 bytes\nProgram Header Entries: 1\nSection Header Size: 40 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\nFlags: Execute,Read\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 204\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 230\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 245\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
const ELF64_LE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 64-bit\nEndianness: Little\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: AMD x86-64\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x40\nEntry SHOFF: 0x78\nFlags: 00000000\nELF Header Size: 64 bytes\nProgram Header Size: 56 bytes\nProgram Header Entries: 1\nSection Header Size: 64 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nFlags: Execute,Read\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 312\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 336\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 361\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
const ELF64_BE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 64-bit\nEndianness: Big\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: AMD x86-64\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x40\nEntry SHOFF: 0x78\nFlags: 00000000\nELF Header Size: 64 bytes\nProgram Header Size: 56 bytes\nProgram Header Entries: 1\nSection Header Size: 64 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nFlags: Execute,Read\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 312\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 336\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 361\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
TestRegister.addTests([
{
name: "ELF Info invalid ELF.",
input: "\x7f\x00\x00\x00",
expectedOutput: "Invalid ELF",
recipeConfig: [
{
op: "ELF Info",
args: [],
},
],
},
{
name: "ELF Info 32-bit ELF Little Endian.",
input: ELF32_LE,
expectedOutput: ELF32_LE_OUTPUT,
recipeConfig: [
{
op: "From Hex",
args: ["None"],
},
{
op: "ELF Info",
args: [],
},
],
},
{
name: "ELF Info 32-bit ELF Big Endian.",
input: ELF32_BE,
expectedOutput: ELF32_BE_OUTPUT,
recipeConfig: [
{
op: "From Hex",
args: ["None"],
},
{
op: "ELF Info",
args: [],
},
],
},
{
name: "ELF Info 64-bit ELF Little Endian.",
input: ELF64_LE,
expectedOutput: ELF64_LE_OUTPUT,
recipeConfig: [
{
op: "From Hex",
args: ["None"],
},
{
op: "ELF Info",
args: [],
},
],
},
{
name: "ELF Info 64-bit ELF Big Endian.",
input: ELF64_BE,
expectedOutput: ELF64_BE_OUTPUT,
recipeConfig: [
{
op: "From Hex",
args: ["None"],
},
{
op: "ELF Info",
args: [],
},
],
},
]);

View File

@ -0,0 +1,375 @@
/**
* Executables in various formats for use in tests.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
/**
* ---------------ELF Header---------------
* 7f454c46 - Magic: .ELF
* 01 - Format: 32 bit
* 01 - Endianness: Little
* 01 - ELF Version: 1
* 00 - Target ABI: System V
* 00 - ABI Version: 0
* 00000000000000 - Padding
* 0200 - File Type: Executable File
* 0300 - ISA: x86
* 01000000 - ELF Version: 1
* 50210608 - Entry Point: 0x8062150
* 34000000 - PH Offset: 0x34
* 54000000 - SH Offset: 0x54
* 00000000 - Flags: 0
* 3400 - ELF Header Size: 0x34
* 2000 - PH Header Size: 0x20
* 0100 - PH Entries: 1
* 2800 - SH Size: 0x28
* 0300 - SH Entries: 0x3
* 0000 - SH Names Offset: 0x0
*
* -------------Program Header-------------
* 06000000 - PH Type: Program Header Table
* 34000000 - Segment Offset: 0x34
* 34800408 - VAddr of segment: 134512692
* 34800408 - PAddr of segment: 134512692
* 00010000 - Size of segment: 256
* 00010000 - Size of segment: 256
* 05000000 - Flags: Execute,Read
* 04000000 - Alignment
*
* --------------SH .shstrtab--------------
* 00000000 - SH Name Offset: 0
* 03000000 - SH Type: String Table
* 00000000 - Flags:
* 00000000 - VAddr of section: 0
* cc000000 - Section offset: 204
* 1c000000 - Section size: 28
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 00000000 - Alignment
* 00000000 - Entry Size: 0
*
* ---------------SH .symtab---------------
* 09000000 - SH Name Offset: 9
* 02000000 - SH Type: Symbol Table
* 00000000 - Flags:
* 00000000 - VAddr of section: 0
* e6000000 - Section offset: 230
* 10000000 - Section size: 16
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 00000000 - Alignment
* 10000000 - Entry Size: 16
*
* ---------------SH .strtab---------------
* 11000000 - SH Name Offset: 17
* 03000000 - SH Type: String Table
* 00000000 - Flags:
* 00000000 - VAddr of section: 0
* f5000000 - Section offset: 245
* 04000000 - Section size: 4
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 00000000 - Alignment
* 00000000 - Entry Size: 0
*
* ---------------.shstrtab---------------
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
*
* ----------------.symtab----------------
* 00000000 - Name Offset: 0
* 00000000 - Value: 0
* 00000000 - Size: 0
* 00 - Info
* 00 - other
* 0000 - shdx
*
* ----------------.strtab----------------
* 74657374 - test
*/
export const ELF32_LE = "7f454c46010101000000000000000000020003000100000050210608340000005400000000000000340020000100280003000000" +
"0600000034000000348004083480040800010000000100000500000004000000" +
"00000000030000000000000000000000cc0000001c00000000000000000000000000000000000000" +
"09000000020000000000000000000000e60000001000000000000000000000000000000010000000" +
"11000000030000000000000000000000f50000000400000000000000000000000000000000000000" +
"2e73687374726162002e73796d746162002e73747274616200" +
"00000000000000000000000000000000" +
"74657374";
/**
* ---------------ELF Header---------------
* 7f454c46 - Magic: .ELF
* 01 - Format: 32 bit
* 02 - Endianness: Big
* 01 - ELF Version: 1
* 00 - Target ABI: System V
* 00 - ABI Version: 0
* 00000000000000 - Padding
* 0002 - File Type: Executable File
* 0003 - ISA: x86
* 00000001 - ELF Version: 1
* 08062150 - Entry Point: 0x8062150
* 00000034 - PH Offset: 0x34
* 00000054 - SH Offset: 0x54
* 00000000 - Flags: 0
* 0034 - ELF Header Size: 0x34
* 0020 - PH Header Size: 0x20
* 0001 - PH Entries: 1
* 0028 - SH Size: 0x28
* 0003 - SH Entries: 0x3
* 0000 - SH Names Offset: 0x0
*
* -------------Program Header-------------
* 00000006 - PH Type: Program Header Table
* 00000034 - Segment Offset: 0x34
* 08048034 - VAddr of segment: 134512692
* 08048034 - PAddr of segment: 134512692
* 00000100 - Size of segment: 256
* 00000100 - Size of segment: 256
* 00000005 - Flags: Execute,Read
* 00000004 - Alignment
*
* --------------SH .shstrtab--------------
* 00000000 - SH Name Offset: 0
* 00000003 - SH Type: String Table
* 00000000 - Flags:
* 00000000 - VAddr of section: 0
* 000000cc - Section offset: 204
* 0000001c - Section size: 28
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 00000000 - Alignment
* 00000000 - Entry Size: 0
*
* ---------------SH .symtab---------------
* 00000009 - SH Name Offset: 9
* 00000002 - SH Type: Symbol Table
* 00000000 - Flags:
* 00000000 - VAddr of section: 0
* 000000e6 - Section offset: 230
* 00000010 - Section size: 16
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 00000000 - Alignment
* 00000010 - Entry Size: 16
*
* ---------------SH .strtab---------------
* 00000011 - SH Name Offset: 17
* 00000003 - SH Type: String Table
* 00000000 - Flags:
* 00000000 - VAddr of section: 0
* 000000f5 - Section offset: 245
* 00000004 - Section size: 4
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 00000000 - Alignment
* 00000000 - Entry Size: 0
*
* ---------------.shstrtab---------------
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
*
* ----------------.symtab----------------
* 00000000 - Name Offset: 0
* 00000000 - Value: 0
* 00000000 - Size: 0
* 00 - Info
* 00 - other
* 0000 - shdx
*
* ----------------.strtab----------------
* 74657374 - test
*/
export const ELF32_BE = "7f454c46010201000000000000000000000200030000000108062150000000340000005400000000003400200001002800030000" +
"0000000600000034080480340804803400000100000001000000000500000004" +
"00000000000000030000000000000000000000cc0000001c00000000000000000000000000000000" +
"00000009000000020000000000000000000000e60000001000000000000000000000000000000010" +
"00000011000000030000000000000000000000f50000000400000000000000000000000000000000" +
"2e73687374726162002e73796d746162002e73747274616200" +
"00000000000000000000000000000000" +
"74657374";
/**
* ---------------ELF Header---------------
* 7f454c46 - Magic: .ELF
* 02 - Format: 64 bit
* 01 - Endianness: Little
* 01 - ELF Version: 1
* 00 - Target ABI: System V
* 00 - ABI Version: 0
* 00000000000000 - Padding
* 0200 - File Type: Executable File
* 3e00 - ISA: AMD x86-64
* 01000000 - ELF Version: 1
* 5021060800000000 - Entry Point: 0x8062150
* 4000000000000000 - PH Offset: 0x40
* 7800000000000000 - SH Offset: 0x78
* 00000000 - Flags: 0
* 4000 - ELF Header Size: 0x40
* 3800 - PH Header Size: 0x38
* 0100 - PH Entries: 1
* 4000 - SH Size: 0x40
* 0300 - SH Entries: 0x3
* 0000 - SH Names Offset: 0x0
*
* -------------Program Header-------------
* 06000000 - PH Type: Program Header Table
* 05000000 - Flags: Execute,Read
* 3400000000000000 - Segment Offset: 0x34
* 3480040800000000 - VAddr of segment: 134512692
* 3480040800000000 - PAddr of segment: 134512692
* 0001000000000000 - Size of segment: 256
* 0001000000000000 - Size of segment: 256
* 0400000000000000 - Alignment
*
* --------------SH .shstrtab--------------
* 00000000 - SH Name Offset: 0
* 03000000 - SH Type: String Table
* 0000000000000000 - Flags:
* 0000000000000000 - VAddr of section: 0
* 3801000000000000 - Section offset: 312
* 1c00000000000000 - Section size: 28
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 0000000000000000 - Alignment
* 0000000000000000 - Entry Size: 0
*
* ---------------SH .symtab---------------
* 09000000 - SH Name Offset: 9
* 02000000 - SH Type: Symbol Table
* 0000000000000000 - Flags:
* 0000000000000000 - VAddr of section: 0
* 5001000000000000 - Section offset: 336
* 1000000000000000 - Section size: 16
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 0000000000000000 - Alignment
* 1800000000000000 - Entry Size: 24
*
* ---------------SH .strtab---------------
* 11000000 - SH Name Offset: 17
* 03000000 - SH Type: String Table
* 0000000000000000 - Flags:
* 0000000000000000 - VAddr of section: 0
* 6901000000000000 - Section offset: 361
* 0400000000000000 - Section size: 4
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 0000000000000000 - Alignment
* 0000000000000000 - Entry Size: 0
*
* ---------------.shstrtab---------------
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
*
* ----------------.symtab----------------
* 00000000 - Name Offset: 0
* 00 - Info
* 00 - other
* 0000 - shdx
* 0000000000000000 - Value: 0
* 0000000000000000 - Size: 0
*
* ----------------.strtab----------------
* 74657374 - test
*/
export const ELF64_LE = "7f454c4602010100000000000000000002003e000100000050210608000000004000000000000000780000000000000000000000400038000100400003000000" +
"0600000005000000340000000000000034800408000000003480040800000000000100000000000000010000000000000400000000000000" +
"00000000030000000000000000000000000000000000000038010000000000001c00000000000000000000000000000000000000000000000000000000000000" +
"09000000020000000000000000000000000000000000000050010000000000001000000000000000000000000000000000000000000000001800000000000000" +
"11000000030000000000000000000000000000000000000069010000000000000400000000000000000000000000000000000000000000000000000000000000" +
"2e73687374726162002e73796d746162002e73747274616200" +
"000000000000000000000000000000000000000000000000" +
"74657374";
/**
* ---------------ELF Header---------------
* 7f454c46 - Magic: .ELF
* 02 - Format: 64 bit
* 02 - Endianness: Big
* 01 - ELF Version: 1
* 00 - Target ABI: System V
* 00 - ABI Version: 0
* 00000000000000 - Padding
* 0002 - File Type: Executable File
* 003e - ISA: AMD x86-64
* 00000001 - ELF Version: 1
* 0000000008062150 - Entry Point: 0x8062150
* 0000000000000040 - PH Offset: 0x40
* 0000000000000078 - SH Offset: 0x78
* 00000000 - Flags: 0
* 0040 - ELF Header Size: 0x40
* 0038 - PH Header Size: 0x38
* 0001 - PH Entries: 1
* 0040 - SH Size: 0x40
* 0003 - SH Entries: 0x3
* 0000 - SH Names Offset: 0x0
*
* -------------Program Header-------------
* 00000006 - PH Type: Program Header Table
* 00000005 - Flags: Execute,Read
* 0000000000000034 - Segment Offset: 0x34
* 0000000008048034 - VAddr of segment: 134512692
* 0000000008048034 - PAddr of segment: 134512692
* 0000000000000100 - Size of segment: 256
* 0000000000000100 - Size of segment: 256
* 0400000000000000 - Alignment
*
* --------------SH .shstrtab--------------
* 00000000 - SH Name Offset: 0
* 00000003 - SH Type: String Table
* 0000000000000000 - Flags:
* 0000000000000000 - VAddr of section: 0
* 0000000000000138 - Section offset: 312
* 000000000000001c - Section size: 28
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 0000000000000000 - Alignment
* 0000000000000000 - Entry Size: 0
*
* ---------------SH .symtab---------------
* 00000009 - SH Name Offset: 9
* 00000002 - SH Type: Symbol Table
* 0000000000000000 - Flags:
* 0000000000000000 - VAddr of section: 0
* 0000000000000150 - Section offset: 336
* 0000000000000010 - Section size: 16
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 0000000000000000 - Alignment
* 0000000000000018 - Entry Size: 24
*
* ---------------SH .strtab---------------
* 00000011 - SH Name Offset: 17
* 00000003 - SH Type: String Table
* 0000000000000000 - Flags:
* 0000000000000000 - VAddr of section: 0
* 0000000000000169 - Section offset: 361
* 0000000000000004 - Section size: 4
* 00000000 - Associated: 0
* 00000000 - Extra Info: 0
* 0000000000000000 - Alignment
* 0000000000000000 - Entry Size: 0
*
* ---------------.shstrtab---------------
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
*
* ----------------.symtab----------------
* 00000000 - Name Offset: 0
* 00 - Info
* 00 - other
* 0000 - shdx
* 0000000000000000 - Value: 0
* 0000000000000000 - Size: 0
*
* ----------------.strtab----------------
* 74657374 - test
*/
export const ELF64_BE = "7f454c460202010000000000000000000002003e0000000100000000080621500000000000000040000000000000007800000000004000380001004000030000" +
"0000000600000005000000000000003400000000080480340000000008048034000000000000010000000000000001000400000000000000" +
"0000000000000003000000000000000000000000000000000000000000000138000000000000001c000000000000000000000000000000000000000000000000" +
"00000009000000020000000000000000000000000000000000000000000001500000000000000010000000000000000000000000000000000000000000000018" +
"00000011000000030000000000000000000000000000000000000000000001690000000000000004000000000000000000000000000000000000000000000000" +
"2e73687374726162002e73796d746162002e73747274616200" +
"000000000000000000000000000000000000000000000000" +
"74657374";