Package: elflepton
OverviewELFLepton is a Lightweight ELF Parsing Tool that was designed specifically for analyzing, editing and fixing binaries with damaged or corrupted ELF headers, such as:binaries that have had the ELF header deliberately mangled as an anti-analysis method (crackmes or malware)Development was prompted by the failure of other tools (likereadelf,pyelftools) to parse ELF binaries with manipulated ELF headers. For example, here'spyelftools(https://github.com/eliben/pyelftools) throwing an exception while trying to load a crackme:In[1]:fromelftools.elf.elffileimportELFFileIn[2]:sample_path="test_binaries/keygenme"In[3]:withopen(sample_path,"rb")asf:...:data=ELFFile(f)...:---------------------------------------------------------------------------FieldErrorTraceback(mostrecentcalllast)......ELFParseError:expected4,found0When using Lepton to parse ELF binaries, one has access to every field in the ELF header, every entry of the program headers table and section headers table. Individual fields can be straightforwardly modified to repair corruption. Lepton succeeds in cases where other parsers because:Like the system ELF loader,elfleptononly relies on the value of thee_machinefield in the ELF header and the ELF magic\x7fELFat offset 0 of the binary. All other values are either derived frome_machinevalue or algorithmically calculated. If the binary can be executed, it is also expected to be parsed correctly byelflepton, regardless of the extent of the corruption in the ELF header.Currently, onlyx86andx86-64binaries are supported.InstallationELFLepton can be installed using pip:pip install elfleptonUsageExample use cases:Fixing Corrupted ELF Header FieldsOne anti-analysis trick involving corrupting the ELF header is writing incorrect values to fields having to do with section information. Some tools will subsequently fail to parse or load the binary. A concrete example of this is a"keygenme" crackme from crackmes.onethat Ghidra v10.1.3 and IDA Home v7.7 load but fail to derive useful section information. The crackme filekeygenmeis included with this repository, in thetest_binariesfolder.For example, section names are not available when the binary is loaded into Ghidra v10.1.3. As can be seen, they're parsed assegment_2,segment_3, etc.In IDA Home v7.7, it's the same story:Usingreadelfit can be seen that theStart of section headers(e_shoff),Size of section headers(e_shentsize) and theSection header string table index(e_shstrndx) all hold bogus values:$readelf-hkeygenme
ELFHeader:Magic:7f454c46020101000000000000000000Class:ELF64Data:2'scomplement,littleendianVersion:1(current)OS/ABI:UNIX-SystemVABIVersion:0Type:DYN(Position-IndependentExecutablefile)Machine:AdvancedMicroDevicesX86-64Version:0x1Entrypointaddress:0x1320Startofprogramheaders:64(bytesintofile)Startofsectionheaders:65535(bytesintofile)Flags:0x0Sizeofthisheader:64(bytes)Sizeofprogramheaders:56(bytes)Numberofprogramheaders:11Sizeofsectionheaders:64(bytes)Numberofsectionheaders:65535Sectionheaderstringtableindex:65535<corrupt:outofrange>
readelf:Error:Reading4194240bytesextendspastendoffileforsectionheadersThese values can be fixed usingelfleptonsuch that all the above tools can successfully load and parse the binary. The following code snippet does the trick. Note the usage ofnew_header=True. This is required to reconstruct the ELF header and section headers table. Withoutnew_header=True, headers are basically cloned.fromelflepton.leptonimportELFFilesample_path="test_binaries/keygenme"withopen(sample_path,"rb")asf:data=ELFFile(f,new_header=True)new_data=data.reconstruct_file()withopen(sample_path+"_fixed","wb")asf:f.write(new_data)Ghidra now successfully imports the binary and displays section names:IDA also successfully imports the binary and displays section names:It can be seen withreadelfthat the ELF headers are now fixed:$ readelf -h keygenme_fixed
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1320
  Start of program headers:          64 (bytes into file)
  Start of section headers:          12584 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         27
  Section header string table index: 26Test BinariesCrackmehttps://crackmes.one/crackme/5d7c66d833c5d46f00e2c45b:test_binaries/keygenmeTODOHandle the case where ELF header and program header overlap