This commit is contained in:
Romain Thomas 2018-09-08 05:17:07 +02:00
parent 9142c2bfb3
commit 4b649ad231
30 changed files with 566 additions and 2860 deletions

View File

@ -14,6 +14,7 @@ ExternalProject_Add(lief_samples
BUILD_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY ${SAMPLES_GIT_URL}
GIT_SHALLOW 1
GIT_TAG ${SAMPLES_TAG}
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
)
@ -33,12 +34,6 @@ set(LIEF_EXAMPLES_DIRECTORY "${PROJECT_SOURCE_DIR}/examples")
set(LIEF_EXAMPLES_BINARY_DIR "${PROJECT_BINARY_DIR}/examples")
#set(LIEF_SAMPLES_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/samples")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/config.yaml.in"
"${CMAKE_CURRENT_BINARY_DIR}/config.yaml"
@ONLY)
if (MSVC)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/utils.py.in"
@ -55,56 +50,11 @@ add_definitions(-DPATH_TO_CONFIG="${CMAKE_CURRENT_BINARY_DIR}")
add_definitions(-DPATH_TO_SAMPLES="${LIEF_SAMPLES_DIRECTORY}")
# YAML CPP
# ========
set(YAMLCPP_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/YAMLCPP")
set(YAMLCPP_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/YAMLCPP")
set(
YAMLCPP_CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${YAMLCPP_INSTALL_DIR}
-DCMAKE_BUILD_TYPE=Release
-DYAML_CPP_BUILD_TOOLS=off
-DYAML_CPP_BUILD_CONTRIB=off
)
if(LIEF_FORCE32)
set(YAMLCPP_CMAKE_ARGS ${YAMLCPP_CMAKE_ARGS}
-DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -m32"
-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -m32")
endif()
if (WIN32)
set(CXX_FLAGS "${CXX_FLAGS} ${LIEF_CRT} /EHsc")
set(YAMLCPP_CMAKE_ARGS ${YAMLCPP_CMAKE_ARGS} -DCMAKE_CXX_FLAGS=${CXX_FLAGS} )
endif()
set(YAMLCPP_VERSION 0.6.2)
set(YAMLCPP_SHA256 SHA256=fa4677e13de0e71bab052a92f4fb527ef35c75fb18bd0177c3f0013aeaa13981)
set(YAMLCPP_URL "${THIRD_PARTY_DIRECTORY}/yaml-cpp-${YAMLCPP_VERSION}.zip" CACHE STRING "URL to the YAMLCPP repo")
ExternalProject_Add(YAMLCPP
PREFIX ${YAMLCPP_PREFIX}
URL ${YAMLCPP_URL}
URL_HASH ${YAMLCPP_SHA256}
INSTALL_DIR ${YAMLCPP_INSTALL_DIR}
CMAKE_ARGS ${YAMLCPP_CMAKE_ARGS}
)
set(YAMLCPP_INCLUDE_DIRS "${YAMLCPP_INSTALL_DIR}/include")
if(WIN32)
set(YAMLCPP_LIBRARY_RELEASE "${YAMLCPP_INSTALL_DIR}/lib/libyaml-cppmd${CMAKE_STATIC_LIBRARY_SUFFIX}")
else()
set(YAMLCPP_LIBRARY_RELEASE "${YAMLCPP_INSTALL_DIR}/lib/libyaml-cpp${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif()
# Catch
# =====
set(CATCH_VERSION 1.10.0)
set(CATCH_SHA256 SHA256=a24b2c7bfa15bd117bf1a6b2cfe68a656f786d232c30eee7a0a08324ecc4fa88)
set(CATCH_URL "${THIRD_PARTY_DIRECTORY}/Catch-${CATCH_VERSION}.zip" CACHE STRING "URL to the Catch repo")
set(CATCH_VERSION 2.2.3)
set(CATCH_SHA256 SHA256=46606cb0eae047a4a5f70f0794244d26c51f72e695b52f4f11c54ea1d1421360)
set(CATCH_URL "${THIRD_PARTY_DIRECTORY}/Catch2-${CATCH_VERSION}.zip" CACHE STRING "URL to the Catch repo")
ExternalProject_Add(catch
PREFIX ${CATCH_PREFIX}
@ -120,32 +70,6 @@ ExternalProject_Get_Property(catch source_dir)
set(CATCH_INCLUDE_DIR "${source_dir}/include" CACHE INTERNAL "Path to include folder for Catch")
# Dirent
# ======
set(DIRENT_INCLUDE_DIR "")
if (WIN32)
set(DIRENT_VERSION 1.22)
set(DIRENT_SHA256 SHA256=3e4ad607ac53a502e184ee48a177790855127ebaadf54faa0e2fd1e77a8881bf)
set(DIRENT_URL "${THIRD_PARTY_DIRECTORY}/dirent-${DIRENT_VERSION}.zip" CACHE STRING "URL to the Dirent package")
ExternalProject_Add(dirent
PREFIX ${DIRENT_PREFIX}
URL ${DIRENT_URL}
URL_HASH ${DIRENT_SHA256}
TIMEOUT 10
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Get_Property(dirent source_dir)
set(DIRENT_INCLUDE_DIR "${source_dir}/include" CACHE INTERNAL "Path to include folder for dirent")
endif()
# Code covergage
# ==============

View File

@ -1,234 +0,0 @@
#!/usr/bin/env python2
#-*- coding: utf-8 -*-
# This file is used to generate config file for LIEF test
# Basically it parse it parse the output of readelf
import re
import yaml
import subprocess
import sys
import hashlib
p = subprocess.Popen(["readelf", "-a", sys.argv[1]], stdout=subprocess.PIPE)
(output, err) = p.communicate()
data = output
binary = dict()
header = dict()
#ELF64
elf64_regex = {
"entrypoint" : "Adresse du point d'entrée:\s+0x([0-9a-f]+)",
"sectionoffset" : "Début des en-têtes de section\s*:\s+([0-9]+)",
"offsetToPhdr" : "Début des en-têtes de programme :\s+([0-9]+)",
"nbShdr" : "Nombre d'en-têtes de section\s*:\s+([0-9]+)",
"nbPhdr" : "Nombre d'en-tête du programme\s*:\s+([0-9]+)",
"sections" : ur'\[\s*(\d+)\]\s?(\S+|\s*)\s+\S+\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)\n\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)',
"segments" : ur'\s+(\w+)\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)\n\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)',
"dynamicSymGlob": ur'^T(?:.*)\.dynsym.*\n((?:\s{2,}(?:.*)\n)+)',
"dynamicSymLoc" : ur'([0-9]+):\s+[0-9a-fA-F]+\s+[0-9]+\s+\S+\s+\S+\s+\S+\s+\S+\s?([^@\n]*)',
"staticSymGlob" : ur'^T(?:.*)\.symtab.*\n((?:.*\n)+)$\s',
"staticSymLoc" : ur'([0-9]+):\s+[0-9a-fA-F]+\s+[0-9]+\s+\S+\s+\S+\s+\S+\s+\S+ (\S*)[@\n]+',
"dynRelocaGlob" : ur'^S(?:.*)\.rel[a]*\.dyn.*\n((?:.{2,}(?:.*)\n)+)',
"dynRelocaLoc" : ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+\S+\s+([0-9a-fA-F]+)\s*(?:\n|(?:\s+(\S+)))',
"pltRelocaGlob" : ur'^S(?:.*)\.rel[a]*\.plt.*\n((?:.{2,}(?:.*)\n)+)',
"pltRelocaLoc" : ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+\S+\s+([0-9a-fA-F]+)\s*(?:\n|(?:\s+(\S+)))'
}
# ELF32
elf64_regex = {
"entrypoint" : "Adresse du point d'entrée:\s+0x([0-9a-f]+)",
"sectionoffset" : "Début des en-têtes de section\s*:\s+([0-9]+)",
"offsetToPhdr" : "Début des en-têtes de programme :\s+([0-9]+)",
"nbShdr" : "Nombre d'en-têtes de section\s*:\s+([0-9]+)",
"nbPhdr" : "Nombre d'en-tête du programme\s*:\s+([0-9]+)",
"sections" : ur'\s+\[\s*([0-9]+)\]\s?(\s|\S+)\s+\S+\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)',
"segments" : ur'\s+(\w+)\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)\s0x([0-9A-Fa-f]+)\s0x([0-9A-Fa-f]+)\s0x([0-9A-Fa-f]+)',
"dynamicSymGlob": ur'^T(?:.*)\.dynsym.*\n((?:\s{2,}(?:.*)\n)+)',
"dynamicSymLoc" : ur'([0-9]+):\s+[0-9a-fA-F]+\s+[0-9]+\s+\S+\s+\S+\s+\S+\s+\S+\s?([^@\n]*)',
"staticSymGlob" : ur'^T(?:.*)\.symtab.*\n((?:.*\n)+)$\s',
"staticSymLoc" : ur'([0-9]+):\s+[0-9a-fA-F]+\s+[0-9]+\s+\S+\s+\S+\s+\S+\s+\S+ (\S*)[@\n]+',
"dynRelocaGlob" : ur'^S(?:.*)\.rel[a]*\.dyn.*\n((?:.{2,}(?:.*)\n)+)',
"dynRelocaLoc" : ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+\S+\s+([0-9a-fA-F]+)\s*(?:\n|(?:\s+([^@\n]+)))',
"pltRelocaGlob" : ur'^S(?:.*)\.rel[a]*\.plt.*\n((?:.{2,}(?:.*)\n)+)',
"pltRelocaLoc" : ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+\S+\s+([0-9a-fA-F]+)\s*(?:\n|(?:\s+([^@\n]+)))'
}
#
# File info
#
binary["filename"] = str(sys.argv[1]).split("/")[-1]
binary["hash"] = hashlib.md5(sys.argv[1]).hexdigest()
#path: "@CMAKE_CURRENT_SOURCE_DIR@/samples/ELF/x86-64/binaries/ls"
#
# header
#
entrypoint = re.search(elf64_regex["entrypoint"], data).groups()[0]
sectionoffset = re.search(elf64_regex["sectionoffset"], data).groups()[0]
offsetToPhdr = re.search(elf64_regex["offsetToPhdr"], data).groups()[0]
nbShdr = re.search(elf64_regex["nbShdr"], data).groups()[0]
nbPhdr = re.search(elf64_regex["nbPhdr"], data).groups()[0]
header['entryPoint'] = int(entrypoint, 16)
header['offsetToShdr'] = int(sectionoffset)
header['offsetToPhdr'] = int(offsetToPhdr)
header['nbShdr'] = int(nbShdr)
header['nbPhdr'] = int(nbPhdr)
#
# Sections
#
section_regexp = re.compile(elf64_regex["sections"], re.MULTILINE)
sections_yaml = []
sections = re.findall(section_regexp, data)
for section in sections:
section_yaml = {
'nb' : int(section[0]),
'name' : '%s' % (section[1].strip()),
'address': int(section[2],16),
'offset' : int(section[3],16),
'size' : int(section[4],16)
}
sections_yaml.append(section_yaml)
#
# Segments
#
segment_regexp = re.compile(elf64_regex["segments"], re.MULTILINE)
segments = re.findall(segment_regexp, data)
segments_yaml = []
for segment in segments:
segment_yaml = {
'offset' : int(segment[1], 16),
'vAddress': int(segment[2], 16),
'pAddress': int(segment[3], 16),
'fSize' : int(segment[4], 16),
'vSize' : int(segment[5], 16)
}
segments_yaml.append(segment_yaml)
#
# Relocations
#
#relocations_regexp = re.compile(ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+(.\S+)\s+([0-9a-fA-F]+)\s+(.\S+)', re.MULTILINE)
#relocations = re.findall(relocations_regexp, data)
#relocations_yaml = []
#for relocation in relocations:
# relocation_yaml = {
# 'offset': int(relocation[0], 16),
# 'info' : int(relocation[1], 16),
# 'name' : relocation[4]
# }
# if relocation_yaml not in relocations_yaml:
# relocations_yaml.append(relocation_yaml);
#
# Dynamic symboles
#
extract_regexp = re.compile(elf64_regex["dynamicSymGlob"], re.MULTILINE)
dynsyms_yaml = []
if len(re.findall(extract_regexp, data)) > 0:
extracted = re.findall(extract_regexp, data)[0]
dynsyms_regexp = re.compile(elf64_regex["dynamicSymLoc"], re.MULTILINE)
dynsyms = re.findall(dynsyms_regexp, extracted)
dynsyms_yaml = []
for dynsym in dynsyms:
dynsym_yaml = {
'num' : int(dynsym[0]),
'name': dynsym[1]
}
dynsyms_yaml.append(dynsym_yaml)
#
# Static symbols
#
extract_regexp = re.compile(elf64_regex["staticSymGlob"], re.MULTILINE)
staticsyms = []
extracted = ""
if len(re.findall(extract_regexp, data)) > 0:
extracted = re.findall(extract_regexp, data)[0]
staticsyms_regexp = re.compile(elf64_regex["staticSymLoc"], re.MULTILINE)
staticsyms = re.findall(staticsyms_regexp, extracted)
staticsyms_yaml = []
for staticsym in staticsyms:
staticsym_yaml = {
'num' : int(staticsym[0]),
'name': staticsym[1]
}
staticsyms_yaml.append(staticsym_yaml)
#
# Dynamic Relocations
#
extract_regexp = re.compile(elf64_regex["dynRelocaGlob"], re.MULTILINE)
relocations_dyn_yaml = []
if len(re.findall(extract_regexp, data)) > 0:
extracted = re.findall(extract_regexp, data)[0]
regexp = re.compile(elf64_regex["dynRelocaLoc"], re.MULTILINE)
relocations = re.findall(regexp, extracted)
relocations_dyn_yaml = []
for reloc in relocations:
relocation_yaml = {
'offset' : int(reloc[0], 16),
'info' : int(reloc[1], 16),
'value' : int(reloc[2], 16),
'name' : reloc[3]
}
relocations_dyn_yaml.append(relocation_yaml)
#
# .plt.got relocations
#
extract_regexp = re.compile(elf64_regex["pltRelocaGlob"], re.MULTILINE)
extracted = re.findall(extract_regexp, data)[0]
regexp = re.compile(elf64_regex["pltRelocaLoc"], re.MULTILINE)
relocations = re.findall(regexp, extracted)
relocations_plt_yaml = []
for reloc in relocations:
relocation_yaml = {
'offset' : int(reloc[0], 16),
'info' : int(reloc[1], 16),
'value' : int(reloc[2], 16),
'name' : reloc[3]
}
relocations_plt_yaml.append(relocation_yaml)
binary['Header'] = header
binary['Sections'] = sections_yaml
binary['Segments'] = segments_yaml
#binary['Relocations'] = relocations_yaml
if len(relocations_plt_yaml) > 0:
binary['PltGotReloc'] = relocations_plt_yaml
if len(dynsyms_yaml) > 0:
binary['DynamicSymbols'] = dynsyms_yaml
if len(relocations_dyn_yaml) > 0:
binary['DynamicReloc'] = relocations_dyn_yaml
if len(staticsyms_yaml) > 0:
binary['StaticSymbols'] = staticsyms_yaml
output = open(binary["filename"] + ".yaml", "w")
yaml.dump(binary, stream=output)
output.close()

View File

@ -1,180 +0,0 @@
#!/usr/bin/env python2
#-*- coding: utf-8 -*-
# This file is used to generate config file for LIEF test
# Basically it parse it parse the output of readelf
import re
import yaml
import subprocess
import sys
import hashlib
p = subprocess.Popen(["readelf", "-a", sys.argv[1]], stdout=subprocess.PIPE)
(output, err) = p.communicate()
data = output
binary = dict()
header = dict()
#
# File info
#
binary["filename"] = str(sys.argv[1]).split("/")[-1]
binary["hash"] = hashlib.md5(sys.argv[1]).hexdigest()
#path: "@CMAKE_CURRENT_SOURCE_DIR@/samples/ELF/x86-64/binaries/ls"
#
# header
#
entrypoint = re.search("Adresse du point d'entrée:\s+0x([0-9a-f]+)", data).groups()[0]
sectionoffset = re.search("Début des en-têtes de section\s*:\s+([0-9]+)", data).groups()[0]
offsetToPhdr = re.search("Début des en-têtes de programme :\s+([0-9]+)", data).groups()[0]
nbShdr = re.search("Nombre d'en-têtes de section\s*:\s+([0-9]+)", data).groups()[0]
nbPhdr = re.search("Nombre d'en-tête du programme\s*:\s+([0-9]+)", data).groups()[0]
header['entryPoint'] = int(entrypoint, 16)
header['offsetToShdr'] = int(sectionoffset)
header['offsetToPhdr'] = int(offsetToPhdr)
header['nbShdr'] = int(nbShdr)
header['nbPhdr'] = int(nbPhdr)
#
# Sections
#
section_regexp = re.compile(ur'\[\s*(\d+)\]\s?(\S+|\s*)\s+\S+\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)\n\s+([0-9A-Fa-f]+)\s+([0-9A-Fa-f]+)', re.MULTILINE)
sections_yaml = []
sections = re.findall(section_regexp, data)
for section in sections:
section_yaml = {
'nb' : int(section[0]),
'name' : '%s' % (section[1].strip()),
'address': int(section[2],16),
'offset' : int(section[3],16),
'size' : int(section[4],16)
}
sections_yaml.append(section_yaml)
#
# Segments
#
segment_regexp = re.compile(ur'\s+(\w+)\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)\n\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)', re.MULTILINE)
segments = re.findall(segment_regexp, data)
segments_yaml = []
for segment in segments:
segment_yaml = {
'offset' : int(segment[1], 16),
'vAddress': int(segment[2], 16),
'pAddress': int(segment[3], 16),
'fSize' : int(segment[4], 16),
'vSize' : int(segment[5], 16)
}
segments_yaml.append(segment_yaml)
#
# Relocations
#
#relocations_regexp = re.compile(ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+(.\S+)\s+([0-9a-fA-F]+)\s+(.\S+)', re.MULTILINE)
#relocations = re.findall(relocations_regexp, data)
#relocations_yaml = []
#for relocation in relocations:
# relocation_yaml = {
# 'offset': int(relocation[0], 16),
# 'info' : int(relocation[1], 16),
# 'name' : relocation[4]
# }
# if relocation_yaml not in relocations_yaml:
# relocations_yaml.append(relocation_yaml);
#
# Dynamic symboles
#
extract_regexp = re.compile(ur'^T(?:.*)\.dynsym.*\n((?:\s{2,}(?:.*)\n)+)', re.MULTILINE)
dynsyms_yaml = []
if len(re.findall(extract_regexp, data)) > 0:
extracted = re.findall(extract_regexp, data)[0]
dynsyms_regexp = re.compile(ur'([0-9]+):\s+[0-9a-fA-F]+\s+[0-9]+\s+\S+\s+\S+\s+\S+\s+\S+\s?([^@\n]*)', re.MULTILINE)
dynsyms = re.findall(dynsyms_regexp, extracted)
dynsyms_yaml = []
for dynsym in dynsyms:
dynsym_yaml = {
'num' : int(dynsym[0]),
'name': dynsym[1]
}
dynsyms_yaml.append(dynsym_yaml)
#
# Static symbols
#
extract_regexp = re.compile(ur'^T(?:.*)\.symtab.*\n((?:.*\n)+)$\s', re.MULTILINE)
staticsyms = []
extracted = ""
if len(re.findall(extract_regexp, data)) > 0:
extracted = re.findall(extract_regexp, data)[0]
staticsyms_regexp = re.compile(ur'([0-9]+):\s+[0-9a-fA-F]+\s+[0-9]+\s+\S+\s+\S+\s+\S+\s+\S+ (\S*)[@\n]+', re.MULTILINE)
staticsyms = re.findall(staticsyms_regexp, extracted)
staticsyms_yaml = []
for staticsym in staticsyms:
staticsym_yaml = {
'num' : int(staticsym[0]),
'name': staticsym[1]
}
staticsyms_yaml.append(staticsym_yaml)
#
# Dynamic Relocations
#
extract_regexp = re.compile(ur'^S(?:.*)\.rel[a]*\.dyn.*\n((?:.{2,}(?:.*)\n)+)', re.MULTILINE)
relocations_dyn_yaml = []
if len(re.findall(extract_regexp, data)) > 0:
extracted = re.findall(extract_regexp, data)[0]
regexp = re.compile(ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+\S+\s+([0-9a-fA-F]+)\s*(?:\n|(?:\s+(\S+)))', re.MULTILINE)
relocations = re.findall(regexp, extracted)
relocations_dyn_yaml = []
for reloc in relocations:
relocation_yaml = {
'offset' : int(reloc[0], 16),
'info' : int(reloc[1], 16),
'value' : int(reloc[2], 16),
'name' : reloc[3]
}
relocations_dyn_yaml.append(relocation_yaml)
#
# .plt.got relocations
#
extract_regexp = re.compile(ur'^S(?:.*)\.rel[a]*\.plt.*\n((?:.{2,}(?:.*)\n)+)', re.MULTILINE)
extracted = re.findall(extract_regexp, data)[0]
regexp = re.compile(ur'^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+\S+\s+([0-9a-fA-F]+)\s*(?:\n|(?:\s+(\S+)))', re.MULTILINE)
relocations = re.findall(regexp, extracted)
relocations_plt_yaml = []
for reloc in relocations:
relocation_yaml = {
'offset' : int(reloc[0], 16),
'info' : int(reloc[1], 16),
'value' : int(reloc[2], 16),
'name' : reloc[3]
}
relocations_plt_yaml.append(relocation_yaml)
binary['Header'] = header
binary['Sections'] = sections_yaml
binary['Segments'] = segments_yaml
#binary['Relocations'] = relocations_yaml
if len(relocations_plt_yaml) > 0:
binary['PltGotReloc'] = relocations_plt_yaml
if len(dynsyms_yaml) > 0:
binary['DynamicSymbols'] = dynsyms_yaml
if len(relocations_dyn_yaml) > 0:
binary['DynamicReloc'] = relocations_dyn_yaml
if len(staticsyms_yaml) > 0:
binary['StaticSymbols'] = staticsyms_yaml
output = open(binary["filename"] + ".yaml", "w")
yaml.dump(binary, stream=output)
output.close()

View File

@ -1,40 +0,0 @@
#!/usr/bin/env python2
#-*- coding: utf-8 -*-
# This file is used to generate config file for LIEF test
# It uses `Macholib`(https://pypi.python.org/pypi/macholib/) to generate yaml config file
import re
import yaml
import hashlib
from macholib.MachO import MachO
import sys
macho = MachO(sys.argv[1])
# Not FAT for now
assert(len(macho.headers) == 1)
binary = dict()
header = dict()
m_header = macho.headers[0]
header["magic"] = m_header.MH_MAGIC
header["cputype"] = m_header.header.cputype
header["cpusubtype"] = m_header.header.cpusubtype
header["filetype"] = m_header.header.filetype
header["ncmds"] = m_header.header.ncmds
header["sizeofcmds"] = m_header.header.sizeofcmds
header["flags"] = m_header.header.flags
header["reserved"] = m_header.header.reserved
binary["header"] = header
for lc, cmd, data in m_header.commands:
print lc.get_cmd_name()
print cmd.describe()
print len(data)
print header

View File

@ -1,188 +0,0 @@
#!/usr/bin/env python2
#-*- coding: utf-8 -*-
# This file is used to generate config file for LIEF test
# It use `pefile`(https://github.com/erocarrera/pefile) to generate yaml config file
import re
import yaml
import hashlib
import pefile
import sys
import os
import copy
def generate_node_config(node):
node_y = dict()
node_y["childs"] = []
if type(node) == pefile.ResourceDirData:
node_y["type"] = 0
node_y["Characteristics"] = node.struct.Characteristics
node_y["TimeDateStamp"] = node.struct.TimeDateStamp
node_y["MajorVersion"] = node.struct.MajorVersion
node_y["MinorVersion"] = node.struct.MinorVersion
node_y["NumberOfNamedEntries"] = node.struct.NumberOfNamedEntries
node_y["NumberOfIdEntries"] = node.struct.NumberOfIdEntries
for rsrc in node.entries:
node_y["childs"].append(generate_node_config(rsrc))
elif type(node) == pefile.ResourceDirEntryData:
node_y["type"] = 1
node_y["Name"] = str(node.name)
node_y["id"] = node.id
node_y["OffsetToData"] = node.struct.OffsetToData
if hasattr(node, "directory"):
node_y["childs"].append(generate_node_config(node.directory))
else:
node_y["childs"].append(generate_node_config(node.data))
elif type(node) == pefile.ResourceDataEntryData:
node_y["type"] = 2
node_y["OffsetToData"] = node.struct.OffsetToData
node_y["Size"] = node.struct.Size
node_y["CodePage"] = node.struct.CodePage
node_y["Reserved"] = node.struct.Reserved
node_y["Reserved"] = node.struct.Reserved
node_y["lang"] = node.lang
node_y["sublang"] = node.sublang
else:
print "Unknown type"
return
return node_y
def generate_config(binary_path):
pe = pefile.PE(binary_path)
binary = dict()
dos_header = dict()
dos_header["e_magic"] = pe.DOS_HEADER.e_magic
dos_header["e_cblp"] = pe.DOS_HEADER.e_cblp
dos_header["e_crlc"] = pe.DOS_HEADER.e_crlc
dos_header["e_cparhdr"] = pe.DOS_HEADER.e_cparhdr
dos_header["e_minalloc"] = pe.DOS_HEADER.e_minalloc
dos_header["e_maxalloc"] = pe.DOS_HEADER.e_maxalloc
dos_header["e_ss"] = pe.DOS_HEADER.e_ss
dos_header["e_sp"] = pe.DOS_HEADER.e_sp
dos_header["e_csum"] = pe.DOS_HEADER.e_csum
header = dict()
header["Machine"] = pe.FILE_HEADER.Machine
header["NumberOfSections"] = pe.FILE_HEADER.NumberOfSections
header["TimeDateStamp"] = pe.FILE_HEADER.TimeDateStamp
header["PointerToSymbolTable"] = pe.FILE_HEADER.PointerToSymbolTable
header["NumberOfSymbols"] = pe.FILE_HEADER.NumberOfSymbols
header["SizeOfOptionalHeader"] = pe.FILE_HEADER.SizeOfOptionalHeader
header["Characteristics"] = pe.FILE_HEADER.Characteristics
optional_header = dict()
optional_header["Magic"] = pe.OPTIONAL_HEADER.Magic
optional_header["MajorLinkerVersion"] = pe.OPTIONAL_HEADER.MajorLinkerVersion
optional_header["MinorLinkerVersion"] = pe.OPTIONAL_HEADER.MinorLinkerVersion
optional_header["SizeOfCode"] = pe.OPTIONAL_HEADER.SizeOfCode
optional_header["SizeOfInitializedData"] = pe.OPTIONAL_HEADER.SizeOfInitializedData
optional_header["SizeOfUninitializedData"] = pe.OPTIONAL_HEADER.SizeOfUninitializedData
optional_header["AddressOfEntryPoint"] = pe.OPTIONAL_HEADER.AddressOfEntryPoint
optional_header["BaseOfCode"] = pe.OPTIONAL_HEADER.BaseOfCode
if pe.OPTIONAL_HEADER.Magic == pefile.OPTIONAL_HEADER_MAGIC_PE:
optional_header["BaseOfData"] = pe.OPTIONAL_HEADER.BaseOfData
optional_header["ImageBase"] = pe.OPTIONAL_HEADER.ImageBase
optional_header["SectionAlignment"] = pe.OPTIONAL_HEADER.SectionAlignment
optional_header["FileAlignment"] = pe.OPTIONAL_HEADER.FileAlignment
optional_header["MajorOperatingSystemVersion"] = pe.OPTIONAL_HEADER.MajorOperatingSystemVersion
optional_header["MinorOperatingSystemVersion"] = pe.OPTIONAL_HEADER.MinorOperatingSystemVersion
optional_header["MajorImageVersion"] = pe.OPTIONAL_HEADER.MajorImageVersion
optional_header["MinorImageVersion"] = pe.OPTIONAL_HEADER.MinorImageVersion
optional_header["MajorSubsystemVersion"] = pe.OPTIONAL_HEADER.MajorSubsystemVersion
optional_header["MinorSubsystemVersion"] = pe.OPTIONAL_HEADER.MinorSubsystemVersion
optional_header["Reserved1"] = pe.OPTIONAL_HEADER.Reserved1
optional_header["SizeOfImage"] = pe.OPTIONAL_HEADER.SizeOfImage
optional_header["SizeOfHeaders"] = pe.OPTIONAL_HEADER.SizeOfHeaders
optional_header["CheckSum"] = pe.OPTIONAL_HEADER.CheckSum
optional_header["Subsystem"] = pe.OPTIONAL_HEADER.Subsystem
optional_header["DllCharacteristics"] = pe.OPTIONAL_HEADER.DllCharacteristics
optional_header["SizeOfStackReserve"] = pe.OPTIONAL_HEADER.SizeOfStackReserve
optional_header["SizeOfStackCommit"] = pe.OPTIONAL_HEADER.SizeOfStackCommit
optional_header["SizeOfHeapReserve"] = pe.OPTIONAL_HEADER.SizeOfHeapReserve
optional_header["SizeOfHeapCommit"] = pe.OPTIONAL_HEADER.SizeOfHeapCommit
optional_header["LoaderFlags"] = pe.OPTIONAL_HEADER.LoaderFlags
optional_header["NumberOfRvaAndSizes"] = pe.OPTIONAL_HEADER.NumberOfRvaAndSizes
sections = []
for section in pe.sections:
sec = dict()
sec["name"] = str(section.Name).replace("\0", "")
sec["Misc_VirtualSize"] = section.Misc_VirtualSize
sec["VirtualAddress"] = section.VirtualAddress
sec["SizeOfRawData"] = section.SizeOfRawData
sec["PointerToRawData"] = section.PointerToRawData
sec["PointerToRelocations"] = section.PointerToRelocations
sec["PointerToLinenumbers"] = section.PointerToLinenumbers
sec["NumberOfRelocations"] = section.NumberOfRelocations
sec["NumberOfLinenumbers"] = section.NumberOfLinenumbers
sec["Characteristics"] = section.Characteristics
sections.append(sec)
imports = []
for entry in pe.DIRECTORY_ENTRY_IMPORT:
import_ = dict()
import_["name"] = entry.dll
import_["TimeDateStamp"] = entry.struct.TimeDateStamp
import_["ForwarderChain"] = entry.struct.ForwarderChain
entries = []
for imp in entry.imports:
impo = dict()
if not imp.import_by_ordinal:
impo["name"] = imp.name
else:
impo["name"] = None
entries.append(impo)
import_["entries"] = entries
imports.append(import_)
tls = dict()
if hasattr(pe, "DIRECTORY_ENTRY_TLS"):
tls["StartAddressOfRawData"] = pe.DIRECTORY_ENTRY_TLS.struct.StartAddressOfRawData
tls["EndAddressOfRawData"] = pe.DIRECTORY_ENTRY_TLS.struct.EndAddressOfRawData
tls["AddressOfIndex"] = pe.DIRECTORY_ENTRY_TLS.struct.AddressOfIndex
tls["AddressOfCallBacks"] = pe.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks
tls["SizeOfZeroFill"] = pe.DIRECTORY_ENTRY_TLS.struct.SizeOfZeroFill
tls["Characteristics"] = pe.DIRECTORY_ENTRY_TLS.struct.Characteristics
resources = dict()
if hasattr(pe, "DIRECTORY_ENTRY_RESOURCE"):
node = pe.DIRECTORY_ENTRY_RESOURCE
resources = generate_node_config(node)
binary["dos_header"] = dos_header
binary["header"] = header
binary["optional_header"] = optional_header
binary["sections"] = sections
binary["imports"] = imports
binary["tls"] = tls
binary["resources"] = resources
binary["filename"] = str(binary_path).split("/")[-1]
binary["hash"] = hashlib.md5(binary_path).hexdigest()
output = open(binary_path + ".yaml", "w")
yaml.dump(binary, stream=output)
output.close()
if __name__ == "__main__":
path_pe32_binaries = "./samples/PE/win32/"
path_pe64_binaries = "./samples/PE/win64/"
for binary in os.listdir(path_pe32_binaries):
if binary.endswith(".exe") or binary.endswith(".dll"):
print "[PE32] Dealing with:", binary
generate_config(path_pe32_binaries + binary)
for binary in os.listdir(path_pe64_binaries):
if binary.endswith(".exe") or binary.endswith(".dll"):
print "[PE64] Dealing with:", binary
generate_config(path_pe64_binaries + binary)

View File

@ -18,19 +18,16 @@ macro(ADD_ART_TEST name sources)
target_include_directories(${name} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${YAMLCPP_INCLUDE_DIRS}
${DIRENT_INCLUDE_DIR}
${CATCH_INCLUDE_DIR})
add_dependencies(${name} catch YAMLCPP)
add_dependencies(${name} catch)
if (WIN32)
add_dependencies(${name} dirent)
target_compile_options("${name}" PUBLIC ${LIEF_CRT})
endif()
target_link_libraries(${name} PUBLIC LIB_LIEF ${YAMLCPP_LIBRARY_RELEASE})
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
endmacro()

View File

@ -1,205 +0,0 @@
#
# Tests ELF
#
# ELF64
# =====
"test_ls":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_ls.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_ls.bin"
arguments : "--version"
regexp : "ls (GNU coreutils)"
"test_ld":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_ld.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_ld.bin"
arguments : "--version"
regexp : "ld (GNU coreutils)"
"test_gcc":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_gcc.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_gcc.bin"
arguments : "--version"
regexp : "(GCC)"
"test_hello_c":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_hello-c.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_hello-c.bin"
regexp : "Hello from"
"test_hello_cpp":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_hello-cpp.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_hello-cpp.bin"
regexp : "Hello from"
"test_nm":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_nm.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_nm.bin"
arguments : "--version"
regexp : "GNU nm (GNU Binutils)"
"test_openssl":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_openssl.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_binary_openssl.bin"
arguments : "version"
regexp : "OpenSSL"
#"test_static_binary":
# format: ELF
# type: binary
# config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/x86-64/binaries/static_binary.yaml"
# binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/x86-64/binaries/static_binary"
"test_libadd":
format: ELF
type: library
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_library_libadd.so.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_library_libadd.so"
"test_libtriton":
format: ELF
type: library
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_library_libtriton.so.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_library_libtriton.so"
"test_libm-2.22":
format: ELF
type: library
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_library_libm-2.22.so.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF64_x86-64_library_libm-2.22.so"
# ELF32
# =====
"test_ls_32":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF32_x86_binary_ls.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF32_x86_binary_ls.bin"
arguments : "--version"
regexp : "ls (GNU coreutils)"
"test_gcc_32":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF32_x86_binary_gcc.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF32_x86_binary_gcc.bin"
arguments : "--version"
regexp : "(GCC)"
# TODO: Fail
#"test_cmake_32":
# format: ELF
# type: binary
# config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/x86-32/binaries/cmake.yaml"
# binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/x86-32/binaries/cmake"
# Very slow  
#"test_clang-3.7_32":
# format: ELF
# type: binary
# config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/x86-32/binaries/clang-3.7.yaml"
# binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/x86-32/binaries/clang-3.7"
"test_bzip2_32":
format: ELF
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF32_x86_binary_bzip2.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/ELF/ELF32_x86_binary_bzip2.bin"
arguments : "--version"
regexp : "bzip2, a block-sorting file compressor."
#
# Tests PE
#
## PE32 ##
"test_cmd_x86":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_binary_cmd.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_binary_cmd.exe"
"test_winhello_mingw_x86":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_binary_winhello-mingw.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_binary_winhello-mingw.exe"
"test_regedit_x86":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_binary_regedit.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_binary_regedit.exe"
"test_msvcrt_x86":
format: PE
type: library
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_library_msvcrt.dll.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_library_msvcrt.dll"
"test_kernel32_x86":
format: PE
type: library
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_library_kernel32.dll.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE32_x86_library_kernel32.dll"
## PE64 ##
"test_cmd_x64":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_cmd.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_cmd.exe"
"test_notepad_x64":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_notepad.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_notepad.exe"
"test_wordpad_x64":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_wordpad.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_wordpad.exe"
"test_winhello64_mingw_x64":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_winhello64-mingw.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_winhello64-mingw.exe"
"test_KernelBase_x64":
format: PE
type: library
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_library_KernelBase.dll.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_library_KernelBase.dll"
"test_MFC_Application_x64":
format: PE
type: binary
config_file: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_mfc-application.exe.yaml"
binary_path: "@LIEF_SAMPLES_DIRECTORY@/PE/PE64_x86-64_binary_mfc-application.exe"
#
# Tests MachO
#

View File

@ -8,7 +8,7 @@ macro(ADD_DEX_TEST name sources)
set_property(TARGET ${name} PROPERTY INCLUDE_DIRECTORIES "")
if (MSVC)
target_compile_options(${name} PUBLIC /FIiso646.h)
target_compile_options(${name} PUBLIC /FIiso646.h)
set_property(TARGET ${name} PROPERTY LINK_FLAGS /NODEFAULTLIB:MSVCRT)
endif()
@ -17,18 +17,18 @@ macro(ADD_DEX_TEST name sources)
target_include_directories(${name} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${YAMLCPP_INCLUDE_DIRS}
${DIRENT_INCLUDE_DIR}
${CATCH_INCLUDE_DIR})
add_dependencies(${name} catch YAMLCPP)
add_dependencies(${name} catch)
if (WIN32)
add_dependencies(${name} dirent)
add_dependencies(${name} dirent)
target_compile_options("${name}" PUBLIC ${LIEF_CRT})
endif()
target_link_libraries(${name} PUBLIC LIB_LIEF ${YAMLCPP_LIBRARY_RELEASE})
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
target_link_libraries(${name} PUBLIC LIB_LIEF)
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
endmacro()
@ -37,7 +37,6 @@ endmacro()
# ============
if (PYTHON_TESTS_ENABLED)
# Unit tests
# ----------
ADD_PYTHON_TEST(UNITTEST_PYTHON_dex

View File

@ -1,60 +1,9 @@
cmake_minimum_required(VERSION 3.1)
include(ExternalProject)
macro(ADD_ELF_TEST name sources)
add_executable(${name} ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp)
set_property(TARGET ${name} PROPERTY INCLUDE_DIRECTORIES "")
if (MSVC)
target_compile_options(${name} PUBLIC /FIiso646.h)
set_property(TARGET ${name} PROPERTY LINK_FLAGS /NODEFAULTLIB:MSVCRT)
target_compile_options(${name} PUBLIC ${LIEF_CRT})
endif()
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON)
target_include_directories(${name} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${YAMLCPP_INCLUDE_DIRS}
${DIRENT_INCLUDE_DIR}
${CATCH_INCLUDE_DIR})
add_dependencies(${name} catch YAMLCPP)
if (WIN32)
add_dependencies(${name} dirent)
endif()
target_link_libraries(${name} PUBLIC LIB_LIEF ${YAMLCPP_LIBRARY_RELEASE})
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
endmacro()
# Targets
# =======
set(test_parser_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_parser.cpp)
set(test_equality_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_equality.cpp)
set(test_builder_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_builder.cpp)
set(test_modifier_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_modifier.cpp)
ADD_ELF_TEST(elf_test_parser ${test_parser_sources})
ADD_ELF_TEST(elf_test_equality ${test_equality_sources})
ADD_ELF_TEST(elf_test_builder ${test_builder_sources})
ADD_ELF_TEST(elf_test_modifier ${test_modifier_sources})
# Examples tests
# ==============
if (LIEF_EXAMPLES)
@ -195,6 +144,7 @@ if (PYTHON_TESTS_ENABLED)
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/test_notes.py")
ADD_PYTHON_TEST(ELF_PYTHON_bin2lib
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/test_bin2lib.py")
@ -207,6 +157,15 @@ if (PYTHON_TESTS_ENABLED)
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/remove_section.py")
ADD_PYTHON_TEST(ELF_PYTHON_parser
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/test_parser.py")
ADD_PYTHON_TEST(ELF_PYTHON_equality
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/test_equality.py")
# Examples
# --------
ADD_PYTHON_TEST(EXAMPLE_PYTHON_elf_reader_ls

View File

@ -1,205 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/ELF.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::ELF;
TEST_CASE("Test parse", "[elf][builder]")
{
using namespace Catch::Generators;
std::vector<std::string> elf_files = Test::get_elf_files();
// Get one
std::vector<std::string>::iterator elf_file = between(
std::begin(elf_files),
std::prev(std::end(elf_files)));
const std::string& elf_file_str = *elf_file;
if (elf_file_str.find("binary_tiny") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
if (elf_file_str.find("ELF64_x86-64_binary_rvs.bin") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
if (elf_file_str.find("ELF64_x86-64_binary_rvs.bin") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
if (elf_file_str.find("ELF32_x86_binary_clang-3.7.bin") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
if (elf_file_str.find("ELF64_x86-64_library_libtriton.so") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
INFO("Binary used: " << elf_file_str);
DYNSYM_COUNT_METHODS mtd = DYNSYM_COUNT_METHODS::COUNT_AUTO;
if (elf_file_str.find("ELF32_x86_binary_gcc.bin") != std::string::npos) {
mtd = DYNSYM_COUNT_METHODS::COUNT_SECTION;
}
std::unique_ptr<Binary> binary_original;
try {
binary_original = std::unique_ptr<Binary>{Parser::parse(elf_file_str, mtd)};
} catch (const LIEF::exception& e) {
WARN("Can't parse: '" << elf_file_str << "' (" << e.what() << ")");
return;
}
std::string output_name = binary_original->name() + "_built";
binary_original->write(output_name);
std::unique_ptr<Binary> binary_build{Parser::parse(output_name, mtd)};
SECTION("Header") {
REQUIRE(binary_original->header() == binary_build->header());
}
SECTION("Sections") {
it_sections sections_lhs = binary_original->sections();
it_sections sections_rhs = binary_build->sections();
REQUIRE(sections_lhs.size() == sections_rhs.size());
for (size_t i = 0; i < sections_lhs.size(); ++i) {
REQUIRE(sections_lhs[i].name() == sections_rhs[i].name());
if (sections_lhs[i].type() != ELF_SECTION_TYPES::SHT_NOBITS and
sections_lhs[i].type() != ELF_SECTION_TYPES::SHT_STRTAB) {
REQUIRE(sections_lhs[i].content() == sections_rhs[i].content());
}
REQUIRE(sections_lhs[i].flags() == sections_rhs[i].flags());
REQUIRE(sections_lhs[i].alignment() == sections_rhs[i].alignment());
REQUIRE(sections_lhs[i].information() == sections_rhs[i].information());
REQUIRE(sections_lhs[i].entry_size() == sections_rhs[i].entry_size());
REQUIRE(sections_lhs[i].link() == sections_rhs[i].link());
REQUIRE(sections_lhs[i].type() == sections_rhs[i].type());
}
}
SECTION("Segments") {
it_segments segment_lhs = binary_original->segments();
it_segments segment_rhs = binary_build->segments();
REQUIRE(segment_lhs.size() == segment_rhs.size());
for (size_t i = 0; i < segment_lhs.size(); ++i) {
REQUIRE(segment_lhs[i].type() == segment_rhs[i].type());
REQUIRE(segment_lhs[i].flags() == segment_rhs[i].flags());
REQUIRE(segment_lhs[i].file_offset() == segment_rhs[i].file_offset());
REQUIRE(segment_lhs[i].virtual_address() == segment_rhs[i].virtual_address());
REQUIRE(segment_lhs[i].physical_address() == segment_rhs[i].physical_address());
REQUIRE(segment_lhs[i].physical_size() == segment_rhs[i].physical_size());
REQUIRE(segment_lhs[i].virtual_size() == segment_rhs[i].virtual_size());
REQUIRE(segment_lhs[i].alignment() == segment_rhs[i].alignment());
}
}
SECTION("Dynamic symbols") {
it_symbols symbols_lhs = binary_original->dynamic_symbols();
it_symbols symbols_rhs = binary_build->dynamic_symbols();
REQUIRE(symbols_lhs.size() == symbols_rhs.size());
for (size_t i = 0; i < symbols_rhs.size(); ++i) {
REQUIRE(symbols_lhs[i] == symbols_rhs[i]);
}
}
SECTION("Static symbols") {
it_symbols symbols_lhs = binary_original->static_symbols();
it_symbols symbols_rhs = binary_build->static_symbols();
REQUIRE(symbols_lhs.size() == symbols_rhs.size());
for (size_t i = 0; i < symbols_rhs.size(); ++i) {
REQUIRE(symbols_lhs[i] == symbols_rhs[i]);
}
}
SECTION("Symbols version") {
it_symbols_version symbols_version_lhs = binary_original->symbols_version();
it_symbols_version symbols_version_rhs = binary_build->symbols_version();
REQUIRE(symbols_version_lhs.size() == symbols_version_rhs.size());
for (size_t i = 0; i < symbols_version_rhs.size(); ++i) {
REQUIRE(symbols_version_lhs[i] == symbols_version_rhs[i]);
}
}
SECTION("Symbols version definition") {
it_symbols_version_definition symbols_version_definition_lhs = binary_original->symbols_version_definition();
it_symbols_version_definition symbols_version_definition_rhs = binary_build->symbols_version_definition();
REQUIRE(symbols_version_definition_lhs.size() == symbols_version_definition_rhs.size());
for (size_t i = 0; i < symbols_version_definition_lhs.size(); ++i) {
REQUIRE(symbols_version_definition_lhs[i] == symbols_version_definition_rhs[i]);
}
}
SECTION("Symbols version requirement") {
it_symbols_version_requirement symbols_version_requirement_lhs = binary_original->symbols_version_requirement();
it_symbols_version_requirement symbols_version_requirement_rhs = binary_build->symbols_version_requirement();
REQUIRE(symbols_version_requirement_lhs.size() == symbols_version_requirement_rhs.size());
for (size_t i = 0; i < symbols_version_requirement_lhs.size(); ++i) {
REQUIRE(symbols_version_requirement_lhs[i] == symbols_version_requirement_lhs[i]);
}
}
SECTION("Dynamic relocations") {
it_dynamic_relocations dynamic_relocations_lhs = binary_original->dynamic_relocations();
it_dynamic_relocations dynamic_relocations_rhs = binary_build->dynamic_relocations();
REQUIRE(dynamic_relocations_lhs.size() == dynamic_relocations_rhs.size());
for (size_t i = 0; i < dynamic_relocations_lhs.size(); ++i) {
REQUIRE(dynamic_relocations_lhs[i] == dynamic_relocations_rhs[i]);
}
}
SECTION(".plt.got relocations") {
it_pltgot_relocations pltgot_relocations_lhs = binary_original->pltgot_relocations();
it_pltgot_relocations pltgot_relocations_rhs = binary_build->pltgot_relocations();
REQUIRE(pltgot_relocations_lhs.size() == pltgot_relocations_rhs.size());
for (size_t i = 0; i < pltgot_relocations_lhs.size(); ++i) {
REQUIRE(pltgot_relocations_lhs[i] == pltgot_relocations_rhs[i]);
}
}
}

56
tests/elf/test_builder.py Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env python
import unittest
import lief
import tempfile
import sys
import subprocess
import stat
import os
import logging
import random
import itertools
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.WARNING)
from unittest import TestCase
from utils import get_sample
class TestBuilder(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
def test_simple(self):
binall = lief.parse(get_sample('ELF/ELF32_x86_binary_all.bin'))
def test_sectionless(self):
binall = lief.parse(get_sample('ELF/ELF64_x86-64_binary_rvs.bin'))
def test_library(self):
binall = lief.parse(get_sample('ELF/ELF64_x86-64_library_libadd.so'))
def test_object(self):
binall = lief.parse(get_sample('ELF/ELF64_x86-64_object_builder.o'))
def test_android(self):
binall = lief.parse(get_sample('ELF/ELF64_AArch64_piebinary_ndkr16.bin'))
def test_corrupted(self):
binall = lief.parse(get_sample('ELF/ELF32_x86_library_libshellx.so'))
def test_gcc(self):
binall = lief.parse(get_sample('ELF/ELF32_x86_binary_gcc.bin'))
if __name__ == '__main__':
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)

View File

@ -1,209 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/exception.hpp>
#include <LIEF/ELF.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::ELF;
TEST_CASE("Test operator==", "[elf][internal]") {
using namespace Catch::Generators;
std::vector<std::string> elf_files = Test::get_elf_files();
// Get one
std::vector<std::string>::iterator elf_file = between(
std::begin(elf_files),
std::prev(std::end(elf_files)));
const std::string& elf_file_str = *elf_file;
if (elf_file_str.find("ELF32_x86_binary_tiny.bin") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
INFO("Binary used: " << *elf_file);
std::unique_ptr<const Binary> binary;
try {
binary = std::unique_ptr<const Binary>{Parser::parse(*elf_file)};
} catch (const LIEF::exception& e) {
WARN("Can't parse: '" << *elf_file << "' (" << e.what() << ")");
return;
}
SECTION("Header") {
const Header& header_lhs = binary->header();
Header header_rhs = header_lhs;
REQUIRE(header_lhs == header_rhs);
header_rhs.entrypoint(0xDEADBEEF);
REQUIRE(header_lhs != header_rhs);
}
SECTION("Section") {
for (const Section& section : binary->sections()) {
{
const Section& section_lhs = section;
const Section& section_rhs = section;
REQUIRE(section_lhs == section_rhs);
}
{
Section section_lhs = section;
const Section& section_rhs = section;
REQUIRE(section_lhs == section_rhs);
}
}
}
SECTION("Segments") {
for (const Segment& segment: binary->segments()) {
{
const Segment& segment_lhs = segment;
const Segment& segment_rhs = segment;
REQUIRE(segment_lhs == segment_rhs);
}
{
Segment segment_lhs = segment;
const Segment& segment_rhs = segment;
REQUIRE(segment_lhs == segment_rhs);
}
}
}
SECTION("Static Symbols") {
for (const Symbol& symbol: binary->static_symbols()) {
{
const Symbol& symbol_lhs = symbol;
const Symbol& symbol_rhs = symbol;
REQUIRE(symbol_lhs == symbol_rhs);
}
{
Symbol symbol_lhs = symbol;
const Symbol& symbol_rhs = symbol;
//CHECK(symbol_lhs == symbol_rhs);
}
}
}
SECTION("Dynamic Symbols") {
for (const Symbol& symbol: binary->dynamic_symbols()) {
{
const Symbol& symbol_lhs = symbol;
const Symbol& symbol_rhs = symbol;
REQUIRE(symbol_lhs == symbol_rhs);
}
{
Symbol symbol_lhs = symbol;
const Symbol& symbol_rhs = symbol;
//CHECK(symbol_lhs == symbol_rhs);
}
}
}
SECTION("Dynamic Relocations") {
for (const Relocation& relocation: binary->dynamic_relocations()) {
{
const Relocation& relocation_lhs = relocation;
const Relocation& relocation_rhs = relocation;
REQUIRE(relocation_lhs == relocation_rhs);
}
{
Relocation relocation_lhs = relocation;
const Relocation& relocation_rhs = relocation;
//CHECK(symbol_lhs == symbol_rhs);
}
}
}
SECTION(".plt.got Relocations") {
for (const Relocation& relocation: binary->pltgot_relocations()) {
{
const Relocation& relocation_lhs = relocation;
const Relocation& relocation_rhs = relocation;
REQUIRE(relocation_lhs == relocation_rhs);
}
{
Relocation relocation_lhs = relocation;
const Relocation& relocation_rhs = relocation;
//CHECK(symbol_lhs == symbol_rhs);
}
}
}
SECTION("Symbols version") {
for (const SymbolVersion& sv: binary->symbols_version()) {
{
const SymbolVersion& sv_lhs = sv;
const SymbolVersion& sv_rhs = sv;
REQUIRE(sv_lhs == sv_rhs);
}
{
SymbolVersion sv_lhs = sv;
const SymbolVersion& sv_rhs = sv;
//REQUIRE(sv_lhs == sv_rhs);
}
}
}
SECTION("Symbols version definition") {
for (const SymbolVersionDefinition& svd: binary->symbols_version_definition()) {
{
const SymbolVersionDefinition& svd_lhs = svd;
const SymbolVersionDefinition& svd_rhs = svd;
REQUIRE(svd_lhs == svd_rhs);
}
{
SymbolVersionDefinition svd_lhs = svd;
const SymbolVersionDefinition& svd_rhs = svd;
//CHECK(svd_lhs == svd_rhs);
}
}
}
SECTION("Symbols version requirement") {
for (const SymbolVersionRequirement& svr: binary->symbols_version_requirement()) {
{
const SymbolVersionRequirement& svr_lhs = svr;
const SymbolVersionRequirement& svr_rhs = svr;
REQUIRE(svr_lhs == svr_rhs);
}
{
SymbolVersionRequirement svr_lhs = svr;
const SymbolVersionRequirement& svr_rhs = svr;
//CHECK(svd_lhs == svd_rhs);
}
}
}
}

View File

@ -0,0 +1,98 @@
#!/usr/bin/env python
import unittest
import lief
import tempfile
import sys
import subprocess
import stat
import os
import logging
import random
import itertools
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.WARNING)
from unittest import TestCase
from utils import get_sample
class TestEquality64(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.input = lief.parse(get_sample("ELF/ELF64_x86-64_binary_all.bin"))
_, output = tempfile.mkstemp(prefix="all_bis")
self.input.write(output)
self.output = lief.parse(output)
def test_header(self):
self.assertEqual(self.input.header, self.output.header)
def test_sections(self):
for l, r in zip(self.input.sections, self.output.sections):
self.assertEqual(l, r)
def test_segments(self):
for l, r in zip(self.input.segments, self.output.segments):
self.assertEqual(l, r)
def test_relocations(self):
for l, r in zip(self.input.relocations, self.output.relocations):
self.assertEqual(l, r)
def test_symbols(self):
for l, r in zip(self.input.symbols, self.output.symbols):
self.assertEqual(l, r)
def test_dynamic_entries(self):
for l, r in zip(self.input.dynamic_entries, self.output.dynamic_entries):
self.assertEqual(l, r)
class TestEquality32(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.input = lief.parse(get_sample("ELF/ELF32_x86_binary_all.bin"))
_, output = tempfile.mkstemp(prefix="all_bis")
self.input.write(output)
self.output = lief.parse(output)
def test_header(self):
self.assertEqual(self.input.header, self.output.header)
def test_sections(self):
for l, r in zip(self.input.sections, self.output.sections):
self.assertEqual(l, r)
def test_segments(self):
for l, r in zip(self.input.segments, self.output.segments):
self.assertEqual(l, r)
def test_relocations(self):
for l, r in zip(self.input.relocations, self.output.relocations):
self.assertEqual(l, r)
def test_symbols(self):
for l, r in zip(self.input.symbols, self.output.symbols):
self.assertEqual(l, r)
def test_dynamic_entries(self):
for l, r in zip(self.input.dynamic_entries, self.output.dynamic_entries):
self.assertEqual(l, r)
if __name__ == '__main__':
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)

View File

@ -1,120 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/ELF.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::ELF;
TEST_CASE("Test remove dynamic symbol", "[elf][modifier][symbol][dynamic]")
{
using namespace Catch::Generators;
std::vector<std::string> elf_files = Test::get_elf_files();
// Get one
std::vector<std::string>::iterator elf_file = between(
std::begin(elf_files),
std::prev(std::end(elf_files)));
const std::string& elf_file_str = *elf_file;
//if (elf_file_str.find("systemd-resolve.bin") == std::string::npos) {
if (elf_file_str.find("binary_tiny") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
if (elf_file_str.find("ELF64_x86-64_binary_rvs.bin") != std::string::npos) {
INFO("Skip " << elf_file_str);
return;
}
INFO("Binary used: " << elf_file_str);
std::unique_ptr<Binary> binary = std::unique_ptr<Binary>{Parser::parse(elf_file_str)};
it_symbols dynamic_symbols = binary->dynamic_symbols();
auto&& it_symbol = std::find_if(
std::begin(dynamic_symbols),
std::end(dynamic_symbols),
[] (const Symbol& symbol) {
return symbol.name().length() > 2;
});
if (it_symbol == std::end(dynamic_symbols)) {
return;
}
auto&& it_symbol_bis = std::find_if(
std::begin(dynamic_symbols),
std::end(dynamic_symbols),
[&it_symbol] (const Symbol& symbol) {
return symbol.name().length() > 2 and *it_symbol != symbol;
});
if (it_symbol_bis == std::end(dynamic_symbols)) {
return;
}
const std::string symbol_removed_name = it_symbol->name();
const std::string symbol_bis_removed_name = it_symbol_bis->name();
INFO("Symbol that will be removed: " << symbol_removed_name << " and " << symbol_bis_removed_name);
Symbol* symbol = &(*it_symbol);
binary->remove_dynamic_symbol(symbol);
binary->remove_dynamic_symbol(symbol_bis_removed_name);
std::string output_name = binary->name() + "_test_remove_symbol";
binary->write(output_name);
std::unique_ptr<Binary> binary_updated = std::unique_ptr<Binary>{Parser::parse(output_name)};
dynamic_symbols = binary_updated->dynamic_symbols();
it_symbol = std::find_if(
std::begin(dynamic_symbols),
std::end(dynamic_symbols),
[&symbol_removed_name] (const Symbol& symbol) {
return symbol.name() == symbol_removed_name;
});
it_symbol_bis = std::find_if(
std::begin(dynamic_symbols),
std::end(dynamic_symbols),
[&symbol_bis_removed_name] (const Symbol& symbol) {
return symbol.name() == symbol_bis_removed_name;
});
REQUIRE(it_symbol == std::end(dynamic_symbols));
REQUIRE(it_symbol_bis == std::end(dynamic_symbols));
}

View File

@ -1,190 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/ELF.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::ELF;
TEST_CASE("Test parse", "[elf][parser]")
{
using namespace Catch::Generators;
// Get test cases
std::vector<std::string> elf_test_cases = Test::get_test_cases();
// Get one
std::vector<std::string>::iterator test_case = between(
std::begin(elf_test_cases),
std::prev(std::end(elf_test_cases)));
YAML::Node parameters = YAML::LoadFile(config[*test_case]["config_file"].as<std::string>());
DYNSYM_COUNT_METHODS mtd = DYNSYM_COUNT_METHODS::COUNT_AUTO;
if (*test_case == "test_gcc_32") {
mtd = DYNSYM_COUNT_METHODS::COUNT_SECTION;
}
// Parse binary
std::unique_ptr<const Binary> binary{Parser::parse(config[*test_case]["binary_path"].as<std::string>(), mtd)};
INFO("Binary used: " << binary->name());
// Raw data
std::ifstream binfile(config[*test_case]["binary_path"].as<std::string>(), std::ios::in | std::ios::binary);
REQUIRE(binfile);
std::vector<uint8_t> raw = {std::istreambuf_iterator<char>(binfile), std::istreambuf_iterator<char>()};
// Header
// ======
SECTION("Header") {
const Header& header = binary->header();
REQUIRE(header.numberof_sections() == parameters["Header"]["nbShdr"].as<unsigned int>());
REQUIRE(header.numberof_segments() == parameters["Header"]["nbPhdr"].as<unsigned int>());
REQUIRE(header.entrypoint() == parameters["Header"]["entryPoint"].as<unsigned long long>());
REQUIRE(header.program_headers_offset() == parameters["Header"]["offsetToPhdr"].as<unsigned long long>());
REQUIRE(header.section_headers_offset() == parameters["Header"]["offsetToShdr"].as<unsigned long long>());
}
// Sections
// ========
SECTION("Sections") {
REQUIRE(binary->sections().size() == parameters["Header"]["nbShdr"].as<unsigned int>());
if (parameters["Sections"]) {
it_const_sections sections = binary->sections();
for (size_t i = 0; i < parameters["Sections"].size(); ++i) {
const Section& section = sections[i];
//name[:17] because readelf provide only the first 16 char
REQUIRE(parameters["Sections"][i]["name"].as<std::string>() == section.name().substr(0,17));
REQUIRE(parameters["Sections"][i]["offset"].as<unsigned long long>() == section.file_offset());
REQUIRE(parameters["Sections"][i]["address"].as<unsigned long long>() == section.virtual_address());
REQUIRE(parameters["Sections"][i]["size"].as<unsigned long long>() == section.size());
REQUIRE(parameters["Sections"][i]["nb"].as<unsigned int>() == i);
if (parameters["Sections"][i]["size"].as<unsigned long long>() > 0 and
section.type() != LIEF::ELF::ELF_SECTION_TYPES::SHT_NOBITS) {
REQUIRE(
std::vector<uint8_t>(
raw.data() + parameters["Sections"][i]["offset"].as<unsigned long long>(),
raw.data() + parameters["Sections"][i]["offset"].as<unsigned long long>() + parameters["Sections"][i]["size"].as<unsigned long long>()) ==
section.content()
);
}
}
}
}
// Segments
// ========
SECTION("Segments") {
REQUIRE(binary->segments().size() == parameters["Header"]["nbPhdr"].as<unsigned int>());
if (parameters["Segments"]) {
it_const_segments segments = binary->segments();
for (size_t i = 0; i < parameters["Segments"].size(); ++i) {
const Segment& segment = segments[i];
REQUIRE(parameters["Segments"][i]["fSize"].as<unsigned long long>() == segment.physical_size());
REQUIRE(parameters["Segments"][i]["offset"].as<unsigned long long>() == segment.file_offset());
REQUIRE(parameters["Segments"][i]["pAddress"].as<unsigned long long>() == segment.physical_address());
REQUIRE(parameters["Segments"][i]["vAddress"].as<unsigned long long>() == segment.virtual_address());
REQUIRE(parameters["Segments"][i]["fSize"].as<unsigned long long>() == segment.physical_size());
REQUIRE(parameters["Segments"][i]["vSize"].as<unsigned long long>() == segment.virtual_size());
if (parameters["Segments"][i]["fSize"].as<unsigned long long>() > 0) {
REQUIRE(
std::vector<uint8_t>(
raw.data() + parameters["Segments"][i]["offset"].as<unsigned long long>(),
raw.data() + parameters["Segments"][i]["offset"].as<unsigned long long>() + parameters["Segments"][i]["fSize"].as<unsigned long long>()) ==
segment.content());
}
}
}
}
// Dynamic symbols
// ===============
SECTION("Dynamic Symbols") {
if (parameters["DynamicSymbols"]) {
// +1 for the null entry
REQUIRE(parameters["DynamicSymbols"].size() == binary->dynamic_symbols().size());
it_const_symbols dynamic_symbols = binary->dynamic_symbols();
for (size_t i = 0; i < parameters["DynamicSymbols"].size(); ++i) {
const Symbol& symbol = dynamic_symbols[i];
REQUIRE(parameters["DynamicSymbols"][i]["name"].as<std::string>() == symbol.name().substr(0, 25));
}
}
}
// Static symbols
// ===============
SECTION("Static Symbols") {
if (parameters["StaticSymbols"]) {
it_const_symbols static_symbols = binary->static_symbols();
for (size_t i = 0; i < parameters["StaticSymbols"].size(); ++i) {
const Symbol& symbol = static_symbols[parameters["StaticSymbols"][i]["num"].as<size_t>()];
REQUIRE(parameters["StaticSymbols"][i]["name"].as<std::string>() == symbol.name().substr(0, 25));
}
}
}
// Dynamic relocations
// ===================
SECTION("Dynamic relocations") {
if (parameters["DynamicReloc"]) {
REQUIRE(parameters["DynamicReloc"].size() == binary->dynamic_relocations().size());
it_const_dynamic_relocations relocations = binary->dynamic_relocations();
for (size_t i = 0; i < parameters["DynamicReloc"].size(); ++i) {
const Relocation& relocation = relocations[i];
REQUIRE(parameters["DynamicReloc"][i]["name"].as<std::string>() == relocation.symbol().name().substr(0, 22));
REQUIRE(parameters["DynamicReloc"][i]["offset"].as<uint64_t>() == relocation.address());
}
}
}
// .plt.got relocations
// ====================
SECTION(".plt.got relocations") {
if (parameters["PltGotReloc"]) {
REQUIRE(parameters["PltGotReloc"].size() == binary->pltgot_relocations().size());
it_const_pltgot_relocations relocations = binary->pltgot_relocations();
for (size_t i = 0; i < parameters["PltGotReloc"].size(); ++i) {
const Relocation& relocation = relocations[i];
if (parameters["PltGotReloc"][i]["name"].as<std::string>().size() > 0) {
REQUIRE(parameters["PltGotReloc"][i]["name"].as<std::string>() == relocation.symbol().name().substr(0, 22));
}
REQUIRE(parameters["PltGotReloc"][i]["offset"].as<uint64_t>() == relocation.address());
}
}
}
}

234
tests/elf/test_parser.py Normal file
View File

@ -0,0 +1,234 @@
#!/usr/bin/env python
import unittest
import lief
import tempfile
import sys
import subprocess
import stat
import os
import logging
import random
import itertools
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.WARNING)
from unittest import TestCase
from utils import get_sample
class TestSimple(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.binall = lief.parse(get_sample('ELF/ELF32_x86_binary_all.bin'))
def test_header(self):
self.assertEqual(self.binall.interpreter, "/lib/ld-linux.so.2")
self.assertEqual(self.binall.entrypoint, 0x774)
def test_sections(self):
self.assertEqual(len(self.binall.sections), 32)
self.assertTrue(self.binall.has_section(".tdata"))
text_section = self.binall.get_section(".text")
self.assertEqual(text_section.type, lief.ELF.SECTION_TYPES.PROGBITS)
self.assertEqual(text_section.offset, 0x6D0)
self.assertEqual(text_section.virtual_address, 0x6D0)
self.assertEqual(text_section.size, 0x271)
self.assertEqual(text_section.alignment, 16)
self.assertIn(lief.ELF.SECTION_FLAGS.ALLOC, text_section)
self.assertIn(lief.ELF.SECTION_FLAGS.EXECINSTR, text_section)
def test_segments(self):
segments = self.binall.segments
self.assertEqual(len(segments), 10)
LOAD_0 = segments[2]
LOAD_1 = segments[3]
self.assertEqual(LOAD_0.type, lief.ELF.SEGMENT_TYPES.LOAD)
self.assertEqual(LOAD_0.file_offset, 0)
self.assertEqual(LOAD_0.virtual_address, 0)
self.assertEqual(LOAD_0.physical_size, 0x00b34)
self.assertEqual(LOAD_0.virtual_size, 0x00b34)
self.assertEqual(LOAD_0.flags, lief.ELF.SEGMENT_FLAGS.R | lief.ELF.SEGMENT_FLAGS.X)
self.assertEqual(LOAD_1.type, lief.ELF.SEGMENT_TYPES.LOAD)
self.assertEqual(LOAD_1.file_offset, 0x000ed8)
self.assertEqual(LOAD_1.virtual_address, 0x00001ed8)
self.assertEqual(LOAD_1.physical_address, 0x00001ed8)
self.assertEqual(LOAD_1.physical_size, 0x00148)
self.assertEqual(LOAD_1.virtual_size, 0x0014c)
self.assertEqual(LOAD_1.flags, lief.ELF.SEGMENT_FLAGS.R | lief.ELF.SEGMENT_FLAGS.W)
def test_dynamic(self):
entries = self.binall.dynamic_entries
self.assertEqual(len(entries), 32)
self.assertEqual(entries[0].name, "libc.so.6")
self.assertEqual(entries[3].array, [2208, 1782])
self.assertEqual(self.binall[lief.ELF.DYNAMIC_TAGS.FLAGS_1].value, 0x8000000)
def test_relocations(self):
dynamic_relocations = self.binall.dynamic_relocations
pltgot_relocations = self.binall.pltgot_relocations
self.assertEqual(len(dynamic_relocations), 10)
self.assertEqual(len(pltgot_relocations), 3)
self.assertEqual(dynamic_relocations[0].address, 0x00001edc)
self.assertEqual(dynamic_relocations[8].symbol.name, "__gmon_start__")
self.assertEqual(dynamic_relocations[9].address, 0x00001ffc)
self.assertEqual(pltgot_relocations[1].address, 0x00002010)
self.assertEqual(pltgot_relocations[1].symbol.name, "puts")
self.assertEqual(pltgot_relocations[1].info, 4)
def test_symbols(self):
dynamic_symbols = self.binall.dynamic_symbols
static_symbols = self.binall.static_symbols
self.assertEqual(len(dynamic_symbols), 27)
self.assertEqual(len(static_symbols), 78)
first = self.binall.get_dynamic_symbol("first")
self.assertEqual(first.value, 0x000008a9)
self.assertEqual(first.symbol_version.value, 0x8002)
self.assertEqual(first.symbol_version.symbol_version_auxiliary.name, "LIBSIMPLE_1.0")
dtor = self.binall.get_static_symbol("__cxa_finalize@@GLIBC_2.1.3")
self.assertEqual(dtor.value, 00000000)
symbol_version_definition = self.binall.symbols_version_definition
symbols_version_requirement = self.binall.symbols_version_requirement
symbols_version = self.binall.symbols_version
self.assertEqual(len(symbol_version_definition), 2)
self.assertEqual(len(symbols_version_requirement), 1)
self.assertEqual(len(symbols_version), 27)
self.assertEqual(symbol_version_definition[0].hash, 0x63ca0e)
self.assertEqual(symbol_version_definition[0].version, 1)
self.assertEqual(symbol_version_definition[0].flags, 1)
self.assertEqual(symbol_version_definition[0].auxiliary_symbols[0].name, "all-32.bin")
self.assertEqual(symbol_version_definition[1].auxiliary_symbols[0].name, "LIBSIMPLE_1.0")
self.assertEqual(symbols_version_requirement[0].name, "libc.so.6")
self.assertEqual(symbols_version_requirement[0].version, 1)
self.assertEqual(symbols_version[0].value, 0)
def test_notes(self):
notes = self.binall.notes
self.assertEqual(len(notes), 2)
self.assertEqual(notes[0].abi, lief.ELF.NOTE_ABIS.LINUX)
self.assertEqual(notes[0].description, [0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0])
self.assertEqual(notes[0].name, "GNU")
self.assertEqual(notes[0].type, lief.ELF.NOTE_TYPES.ABI_TAG)
self.assertEqual(notes[0].version, [3, 2, 0])
class TestSectionless(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.sectionless = lief.ELF.parse(get_sample('ELF/ELF64_x86-64_binary_rvs.bin'), lief.ELF.DYNSYM_COUNT_METHODS.HASH)
def test_symbols(self):
symbols = self.sectionless.dynamic_symbols
self.assertEqual(len(symbols), 10)
self.assertEqual(symbols[2].name, "_IO_putc")
def test_relocations(self):
relocations = self.sectionless.relocations
self.assertEqual(len(relocations), 10)
self.assertEqual(relocations[0].symbol.name, "__gmon_start__")
class TestObject(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.obj = lief.parse(get_sample('ELF/ELF64_x86-64_object_builder.o'))
def test_relocations(self):
pass
class TestCorrupted(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.corrupted = lief.parse(get_sample('ELF/ELF32_x86_library_libshellx.so'))
def test_symbols(self):
symbols = self.corrupted.dynamic_symbols
self.assertEqual(len(symbols), 48)
self.assertEqual(symbols[2].name, "__cxa_atexit")
def test_relocations(self):
relocations = self.corrupted.relocations
self.assertEqual(len(relocations), 47)
self.assertEqual(relocations[10].symbol.name, "strlen")
class TestGcc(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
def test_symbol_count(self):
gcc1 = lief.ELF.parse(get_sample('ELF/ELF32_x86_binary_gcc.bin'), lief.ELF.DYNSYM_COUNT_METHODS.HASH)
gcc2 = lief.ELF.parse(get_sample('ELF/ELF32_x86_binary_gcc.bin'), lief.ELF.DYNSYM_COUNT_METHODS.SECTION)
gcc3 = lief.ELF.parse(get_sample('ELF/ELF32_x86_binary_gcc.bin'), lief.ELF.DYNSYM_COUNT_METHODS.RELOCATIONS)
self.assertEqual(len(gcc1.symbols), 158)
self.assertEqual(len(gcc2.symbols), 158)
self.assertEqual(len(gcc3.symbols), 158)
class TestTiny(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.tiny01 = lief.parse(get_sample('ELF/ELF32_x86_binary_tiny01.bin'))
def test_segment(self):
self.assertEqual(len(self.tiny01.segments), 1)
segment = self.tiny01.segments[0]
self.assertEqual(segment.type, lief.ELF.SEGMENT_TYPES.LOAD)
self.assertEqual(segment.file_offset, 0)
self.assertEqual(segment.virtual_address, 0x8048000)
self.assertEqual(segment.physical_size, 0x5a)
self.assertEqual(segment.virtual_size, 0x5a)
self.assertEqual(segment.flags, lief.ELF.SEGMENT_FLAGS.R | lief.ELF.SEGMENT_FLAGS.X)
if __name__ == '__main__':
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)

View File

@ -1,89 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <dirent.h>
#include <iostream>
#include <yaml-cpp/yaml.h>
#include "utils.hpp"
extern const YAML::Node config;
namespace LIEF {
namespace ELF {
namespace Test {
std::vector<std::string> get_test_cases(void) {
std::vector<std::string> elf_samples;
for (auto it = std::begin(config) ;it != std::end(config); ++it) {
std::string key = it->first.as<std::string>();
if (config[key]["format"].as<std::string>() == "ELF") {
elf_samples.push_back(key);
}
}
return elf_samples;
}
std::vector<std::string> get_binary_test_cases(void) {
std::vector<std::string> elf_samples;
for (auto it = std::begin(config) ;it != std::end(config); ++it) {
std::string key = it->first.as<std::string>();
if (config[key]["format"].as<std::string>() == "ELF" && config[key]["type"].as<std::string>() == "binary") {
elf_samples.push_back(key);
}
}
return elf_samples;
}
std::vector<std::string> get_library_test_cases(void) {
std::vector<std::string> elf_samples;
for (auto it = std::begin(config) ;it != std::end(config); ++it) {
std::string key = it->first.as<std::string>();
if (config[key]["format"].as<std::string>() == "ELF" && config[key]["type"].as<std::string>() == "library") {
elf_samples.push_back(key);
}
}
return elf_samples;
}
std::vector<std::string> get_elf_files(void) {
auto endswith = [] (const std::string& string, const std::string& end) {
size_t pos = string.rfind(end);
return pos != std::string::npos and pos == (string.length() - end.length());
};
std::vector<std::string> filespath;
DIR *dir;
struct dirent *ent;
std::string samples_path = PATH_TO_SAMPLES;
samples_path += "/ELF";
if ((dir = opendir(samples_path.c_str())) != NULL) {
while ((ent = readdir (dir)) != NULL) {
const std::string name = ent->d_name;
if (endswith(name, ".bin") or endswith(name, ".so")) {
filespath.emplace_back(samples_path + "/" + name);
}
}
closedir (dir);
} else {
std::cerr << "Can't open '" << samples_path << "'." << std::endl;
}
return filespath;
}
}
}
}

View File

@ -1,32 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_ELF_TEST_UTILS_H_
#define LIEF_ELF_TEST_UTILS_H_
#include <vector>
#include <string>
namespace LIEF {
namespace ELF {
namespace Test {
std::vector<std::string> get_test_cases(void);
std::vector<std::string> get_binary_test_cases(void);
std::vector<std::string> get_library_test_cases(void);
std::vector<std::string> get_elf_files(void);
}
}
}
#endif

View File

@ -17,18 +17,17 @@ macro(ADD_OAT_TEST name sources)
target_include_directories(${name} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${YAMLCPP_INCLUDE_DIRS}
${DIRENT_INCLUDE_DIR}
${CATCH_INCLUDE_DIR})
add_dependencies(${name} catch YAMLCPP)
add_dependencies(${name} catch)
if (WIN32)
add_dependencies(${name} dirent)
target_compile_options("${name}" PUBLIC ${LIEF_CRT})
endif()
target_link_libraries(${name} PUBLIC LIB_LIEF ${YAMLCPP_LIBRARY_RELEASE})
target_link_libraries(${name} PUBLIC LIB_LIEF)
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
endmacro()

View File

@ -1,63 +1,6 @@
cmake_minimum_required(VERSION 3.1)
include(ExternalProject)
macro(ADD_PE_TEST name sources)
add_executable(${name} ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp)
set_property(TARGET ${name} PROPERTY INCLUDE_DIRECTORIES "")
if (MSVC)
target_compile_options(${name} PUBLIC /FIiso646.h)
set_property(TARGET ${name} PROPERTY LINK_FLAGS /NODEFAULTLIB:MSVCRT)
endif()
set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON)
target_include_directories(${name} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${DIRENT_INCLUDE_DIR}
${YAMLCPP_INCLUDE_DIRS}
${CATCH_INCLUDE_DIR})
add_dependencies(${name} catch YAMLCPP)
if (WIN32)
add_dependencies(${name} dirent)
target_compile_options("${name}" PUBLIC ${LIEF_CRT})
endif()
target_link_libraries(${name} PUBLIC LIB_LIEF ${YAMLCPP_LIBRARY_RELEASE})
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
endmacro()
# Targets
# =======
set(test_parser_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_parser.cpp)
set(test_equality_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_equality.cpp)
set(test_builder_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_builder.cpp)
set(test_binary_sources
${CMAKE_CURRENT_SOURCE_DIR}/test_binary.cpp)
ADD_PE_TEST(pe_test_parser ${test_parser_sources})
ADD_PE_TEST(pe_test_equality ${test_equality_sources})
ADD_PE_TEST(pe_test_builder ${test_builder_sources})
ADD_PE_TEST(pe_test_binary ${test_binary_sources})
# Examples tests
# ==============
if (LIEF_EXAMPLES)

View File

@ -1,112 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/PE.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::PE;
TEST_CASE("Test parse", "[pe][parser]")
{
using namespace Catch::Generators;
std::vector<std::string> pe_files = Test::get_pe_files();
// Get one
std::vector<std::string>::iterator pe_file = between(
std::begin(pe_files),
std::prev(std::end(pe_files)));
const std::string& pe_file_str = *pe_file;
if (pe_file_str.find("winenotepad.exe") != std::string::npos) {
return;
}
if (pe_file_str.find("PE32_x86_binary_winhello-mingw.exe") != std::string::npos) {
return;
}
if (pe_file_str.find("PE32_x86_binary_KMSpico_setup_MALWARE.exe") != std::string::npos) {
return;
}
INFO("Binary used: " << pe_file_str);
std::unique_ptr<Binary> binary_original;
try {
binary_original = std::unique_ptr<Binary>{Parser::parse(pe_file_str)};
} catch (const LIEF::exception& e) {
WARN("Can't parse: '" << pe_file_str << "' (" << e.what() << ")");
return;
}
std::string output_name = binary_original->name() + "_built_binary";
Builder builder{binary_original.get()};
builder.
build_imports(true).
patch_imports(false).
build_relocations(false).
build_tls(false).
build_resources(false);
try {
builder.build();
} catch (const LIEF::exception& e) {
FAIL("Can't build: '" << pe_file_str << "' (" << e.what() << ")");
return;
}
builder.write(output_name);
std::unique_ptr<Binary> binary_built{Parser::parse(output_name)};
binary_original = std::unique_ptr<Binary>{Parser::parse(pe_file_str)};
SECTION("Imports") {
if (not binary_original->has_imports()) {
return;
}
it_imports imports_lhs = binary_original->imports();
it_imports imports_rhs = binary_built->imports();
for (size_t i = 0; i < imports_lhs.size(); ++i) {
it_import_entries entries_lhs = imports_lhs[i].entries();
it_import_entries entries_rhs = imports_rhs[i].entries();
for (size_t j = 0; j < entries_lhs.size(); ++j) {
if (not entries_lhs[j].is_ordinal()) {
INFO("Library: " << imports_lhs[i].name() << ". Function: " << entries_lhs[j].name());
uint64_t address = binary_original->predict_function_rva(imports_lhs[i].name(), entries_lhs[j].name());
if (address > 0) {
CHECK(address == entries_rhs[j].iat_address());
}
}
}
}
}
}

View File

@ -1,235 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/PE.hpp>
#include <LIEF/PE/hash.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::PE;
TEST_CASE("Test parse", "[pe][builder]")
{
using namespace Catch::Generators;
std::vector<std::string> pe_files = Test::get_pe_files();
// Get one
std::vector<std::string>::iterator pe_file = between(
std::begin(pe_files),
std::prev(std::end(pe_files)));
const std::string& pe_file_str = *pe_file;
if (pe_file_str.find("winenotepad.exe") != std::string::npos) {
return;
}
if (pe_file_str.find("PE32_x86_binary_winhello-mingw.exe") != std::string::npos) {
return;
}
if (pe_file_str.find("PE32_x86_binary_KMSpico_setup_MALWARE.exe") != std::string::npos) {
return;
}
INFO("Binary used: " << pe_file_str);
std::unique_ptr<Binary> binary_original;
try {
binary_original = std::unique_ptr<Binary>{Parser::parse(pe_file_str)};
} catch (const LIEF::exception& e) {
WARN("Can't parse: '" << pe_file_str << "' (" << e.what() << ")");
return;
}
std::string output_name = binary_original->name() + "_built";
Builder builder{binary_original.get()};
builder.
build_imports(true).
patch_imports(true).
build_relocations(true).
build_tls(true).
build_resources(true);
try {
builder.build();
} catch (const LIEF::exception& e) {
FAIL("Can't build: '" << pe_file_str << "' (" << e.what() << ")");
return;
}
builder.write(output_name);
INFO("Output: " << output_name);
binary_original.reset(Parser::parse(pe_file_str).release());
std::unique_ptr<Binary> binary_built{Parser::parse(output_name)};
SECTION("Checks functions") {
//REQUIRE(binary_original->get_virtual_size() == binary_original->optional_header().sizeof_image());
//REQUIRE(binary_original->get_sizeof_headers() == binary_original->optional_header().sizeof_headers());
//REQUIRE(binary_built->get_virtual_size() == binary_built->optional_header().sizeof_image());
//REQUIRE(binary_built->get_sizeof_headers() == binary_built->optional_header().sizeof_headers());
}
SECTION("Dos Header") {
REQUIRE(binary_original->dos_header() == binary_built->dos_header());
}
SECTION("Header") {
const Header& header_lhs = binary_original->header();
const Header& header_rhs = binary_built->header();
REQUIRE(header_lhs.signature() == header_rhs.signature());
REQUIRE(header_lhs.machine() == header_rhs.machine());
REQUIRE(header_lhs.time_date_stamp() == header_rhs.time_date_stamp());
REQUIRE(header_lhs.characteristics() == header_rhs.characteristics());
}
SECTION("Optional Header") {
const OptionalHeader& header_lhs = binary_original->optional_header();
const OptionalHeader& header_rhs = binary_built->optional_header();
REQUIRE(header_lhs.magic() == header_rhs.magic());
REQUIRE(header_lhs.major_linker_version() == header_rhs.major_linker_version());
REQUIRE(header_lhs.minor_linker_version() == header_rhs.minor_linker_version());
REQUIRE(header_lhs.addressof_entrypoint() == header_rhs.addressof_entrypoint());
REQUIRE(header_lhs.baseof_code() == header_rhs.baseof_code());
REQUIRE(header_lhs.imagebase() == header_rhs.imagebase());
REQUIRE(header_lhs.section_alignment() == header_rhs.section_alignment());
REQUIRE(header_lhs.file_alignment() == header_rhs.file_alignment());
REQUIRE(header_lhs.major_operating_system_version() == header_rhs.major_operating_system_version());
REQUIRE(header_lhs.minor_operating_system_version() == header_rhs.minor_operating_system_version());
REQUIRE(header_lhs.major_image_version() == header_rhs.major_image_version());
REQUIRE(header_lhs.minor_image_version() == header_rhs.minor_image_version());
REQUIRE(header_lhs.major_subsystem_version() == header_rhs.major_subsystem_version());
REQUIRE(header_lhs.minor_subsystem_version() == header_rhs.minor_subsystem_version());
REQUIRE(header_lhs.win32_version_value() == header_rhs.win32_version_value());
REQUIRE(header_lhs.subsystem() == header_rhs.subsystem());
REQUIRE(header_lhs.dll_characteristics() == header_rhs.dll_characteristics());
REQUIRE(header_lhs.loader_flags() == header_rhs.loader_flags());
REQUIRE(header_lhs.numberof_rva_and_size() == header_rhs.numberof_rva_and_size());
}
SECTION("Section") {
for (const Section& section_lhs : binary_original->sections()) {
INFO("Section " << section_lhs.name());
const Section& section_rhs = binary_built->get_section(section_lhs.name());
INFO("RHS" << section_rhs);
INFO("LHS" << section_lhs);
REQUIRE(section_lhs.name() == section_rhs.name());
REQUIRE(section_lhs.virtual_size() == section_rhs.virtual_size());
REQUIRE(section_lhs.virtual_address() == section_rhs.virtual_address());
REQUIRE(section_lhs.size() == section_rhs.size());
REQUIRE(section_lhs.offset() == section_rhs.offset());
REQUIRE(section_lhs.pointerto_relocation() == section_rhs.pointerto_relocation());
REQUIRE(section_lhs.content().size() == section_rhs.content().size());
//REQUIRE(LIEF::Hash::hash(section_lhs.content()) == LIEF::Hash::hash(section_rhs.content()));
}
}
SECTION("TLS") {
const TLS& tls_lhs = binary_original->tls();
const TLS& tls_rhs = binary_built->tls();
REQUIRE(tls_lhs.callbacks() == tls_rhs.callbacks());
REQUIRE(tls_lhs.addressof_raw_data() == tls_rhs.addressof_raw_data());
REQUIRE(tls_lhs.addressof_index() == tls_rhs.addressof_index());
REQUIRE(tls_lhs.addressof_callbacks() == tls_rhs.addressof_callbacks());
REQUIRE(tls_lhs.sizeof_zero_fill() == tls_rhs.sizeof_zero_fill());
REQUIRE(tls_lhs.characteristics() == tls_rhs.characteristics());
REQUIRE(tls_lhs.data_template() == tls_rhs.data_template());
}
SECTION("Debug") {
REQUIRE(binary_original->debug() == binary_built->debug());
}
SECTION("Resources") {
if (not binary_original->has_resources()) {
return;
}
const ResourceNode& root_lhs = binary_original->resources();
const ResourceNode& root_rhs = binary_built->resources();
INFO("LHS: " << binary_original->resources_manager());
INFO("RHS: " << binary_built->resources_manager());
//REQUIRE(root_lhs == root_rhs);
}
SECTION("Relocations") {
if (not binary_original->has_relocations()) {
return;
}
it_relocations relocations_lhs = binary_original->relocations();
it_relocations relocations_rhs = binary_built->relocations();
REQUIRE(relocations_lhs.size() == relocations_rhs.size());
for (size_t i = 0; i < relocations_lhs.size(); ++i) {
REQUIRE(relocations_lhs[i] == relocations_rhs[i]);
}
}
SECTION("Imports") {
if (not binary_original->has_imports()) {
return;
}
it_imports imports_lhs = binary_original->imports();
it_imports imports_rhs = binary_built->imports();
REQUIRE(imports_lhs.size() == imports_rhs.size());
for (size_t i = 0; i < imports_lhs.size(); ++i) {
REQUIRE(imports_lhs[i].name() == imports_rhs[i].name());
REQUIRE(imports_lhs[i].forwarder_chain() == imports_rhs[i].forwarder_chain());
REQUIRE(imports_lhs[i].timedatestamp() == imports_rhs[i].timedatestamp());
it_import_entries entries_lhs = imports_lhs[i].entries();
it_import_entries entries_rhs = imports_rhs[i].entries();
REQUIRE(entries_lhs.size() == entries_rhs.size());
for (size_t j = 0; j < entries_lhs.size(); ++j) {
REQUIRE(entries_lhs[j].is_ordinal() == entries_rhs[j].is_ordinal());
if (entries_lhs[j].is_ordinal()) {
REQUIRE(entries_lhs[j].ordinal() == entries_rhs[j].ordinal());
} else {
REQUIRE(entries_lhs[j].hint() == entries_rhs[j].hint());
REQUIRE(entries_lhs[j].name() == entries_rhs[j].name());
}
}
}
}
}

View File

@ -1,148 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/exception.hpp>
#include <LIEF/PE.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::PE;
TEST_CASE("Test operator== and operator!=", "[pe][internal]") {
using namespace Catch::Generators;
std::vector<std::string> pe_files = Test::get_pe_files();
// Get one
std::vector<std::string>::iterator pe_file = between(
std::begin(pe_files),
std::prev(std::end(pe_files)));
INFO("Binary used: " << *pe_file);
std::unique_ptr<const Binary> binary_lhs;
std::unique_ptr<const Binary> binary_rhs;
try {
binary_lhs = std::unique_ptr<const Binary>{Parser::parse(*pe_file)};
binary_rhs = std::unique_ptr<const Binary>{Parser::parse(*pe_file)};
} catch (const LIEF::exception& e) {
WARN("Can't parse: '" << *pe_file << "' (" << e.what() << ")");
return;
}
SECTION("DosHeader") {
const DosHeader& dos_header_lhs = binary_lhs->dos_header();
DosHeader dos_header_rhs = dos_header_lhs;
REQUIRE(dos_header_lhs == dos_header_rhs);
dos_header_rhs.file_size_in_pages(123);
REQUIRE(dos_header_lhs != dos_header_rhs);
}
SECTION("Header") {
const Header& header_lhs = binary_lhs->header();
Header header_rhs = header_lhs;
REQUIRE(header_lhs == header_rhs);
header_rhs.sizeof_optional_header(456);
REQUIRE(header_lhs != header_rhs);
}
SECTION("OptionalHeader") {
const OptionalHeader& optional_header_lhs = binary_lhs->optional_header();
OptionalHeader optional_header_rhs = optional_header_lhs;
REQUIRE(optional_header_lhs == optional_header_rhs);
optional_header_rhs.addressof_entrypoint(0xDEADBEEF);
REQUIRE(optional_header_lhs != optional_header_rhs);
}
SECTION("Sections") {
for (const Section& section_lhs : binary_lhs->sections()) {
Section section_rhs = section_lhs;
REQUIRE(section_lhs == section_rhs);
section_rhs.name("toto");
REQUIRE(section_lhs != section_rhs);
}
}
SECTION("Data Directories") {
for (size_t i = 0; i < binary_lhs->data_directories().size(); ++i) {
REQUIRE(binary_lhs->data_directories()[i] == binary_rhs->data_directories()[i]);
}
}
SECTION("Imports") {
if (not binary_lhs->has_imports()) {
return;
}
for (const Import& import_lhs : binary_lhs->imports()) {
const Import& import_rhs = import_lhs;
REQUIRE(import_lhs == import_rhs);
}
}
SECTION("Relocations") {
if (not binary_lhs->has_relocations()) {
return;
}
for (const Relocation& relocation_lhs : binary_lhs->relocations()) {
Relocation relocation_rhs = relocation_lhs;
REQUIRE(relocation_lhs == relocation_rhs);
relocation_rhs.virtual_address(123);
REQUIRE(relocation_lhs != relocation_rhs);
}
}
SECTION("Exports") {
if (not binary_lhs->has_exports()) {
return;
}
const Export& export_lhs = binary_lhs->get_export();
const Export& export_rhs = binary_rhs->get_export();
REQUIRE(export_lhs == export_rhs);
}
SECTION("TLS") {
if (not binary_lhs->has_tls()) {
return;
}
const TLS& tls_lhs = binary_lhs->tls();
const TLS& tls_rhs = binary_rhs->tls();
REQUIRE(tls_lhs == tls_rhs);
}
}

View File

@ -1,350 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <yaml-cpp/yaml.h>
#include <LIEF/PE.hpp>
#include "utils.hpp"
extern const YAML::Node config = YAML::LoadFile(std::string(PATH_TO_CONFIG) + "/config.yaml");
using namespace LIEF::PE;
TEST_CASE("Test parse", "[pe][parser]")
{
using namespace Catch::Generators;
// Get test cases
std::vector<std::string> pe_test_cases = Test::get_test_cases();
// Get one
std::vector<std::string>::iterator test_case = between(
std::begin(pe_test_cases),
std::prev(std::end(pe_test_cases)));
YAML::Node parameters = YAML::LoadFile(config[*test_case]["config_file"].as<std::string>());
// Parse binary
std::unique_ptr<const Binary> binary{Parser::parse(config[*test_case]["binary_path"].as<std::string>())};
// Raw data
std::ifstream binfile(config[*test_case]["binary_path"].as<std::string>(), std::ios::in | std::ios::binary);
REQUIRE(binfile);
std::vector<uint8_t> raw = {std::istreambuf_iterator<char>(binfile), std::istreambuf_iterator<char>()};
// Dos Header
// ==========
SECTION("Dos Header") {
REQUIRE(binary->dos_header().magic() == parameters["dos_header"]["e_magic"].as<unsigned int>());
}
// Header
// ======
SECTION("Header") {
const Header& header = binary->header();
REQUIRE(
static_cast<uint32_t>(header.machine()) ==
parameters["header"]["Machine"].as<uint32_t>());
REQUIRE(
static_cast<uint16_t>(header.numberof_sections()) ==
parameters["header"]["NumberOfSections"].as<uint16_t>());
REQUIRE(
static_cast<uint32_t>(header.time_date_stamp()) ==
parameters["header"]["TimeDateStamp"].as<uint32_t>());
REQUIRE(
static_cast<uint32_t>(header.pointerto_symbol_table()) ==
parameters["header"]["PointerToSymbolTable"].as<uint32_t>());
REQUIRE(
static_cast<uint32_t>(header.numberof_symbols()) ==
parameters["header"]["NumberOfSymbols"].as<uint32_t>());
REQUIRE(
static_cast<uint16_t>(header.sizeof_optional_header()) ==
parameters["header"]["SizeOfOptionalHeader"].as<uint16_t>());
REQUIRE(
static_cast<uint16_t>(header.characteristics()) ==
parameters["header"]["Characteristics"].as<uint16_t>());
}
// Optional Header
// ===============
SECTION("Optional Header") {
const OptionalHeader& optional_header = binary->optional_header();
REQUIRE(
static_cast<uint32_t>(optional_header.magic()) ==
parameters["optional_header"]["Magic"].as<uint32_t>());
REQUIRE(
optional_header.major_linker_version() ==
parameters["optional_header"]["MajorLinkerVersion"].as<uint32_t>());
REQUIRE(
optional_header.minor_linker_version() ==
parameters["optional_header"]["MinorLinkerVersion"].as<uint32_t>());
REQUIRE(
optional_header.sizeof_code() ==
parameters["optional_header"]["SizeOfCode"].as<uint32_t>());
REQUIRE(
optional_header.sizeof_initialized_data() ==
parameters["optional_header"]["SizeOfInitializedData"].as<uint32_t>());
REQUIRE(
optional_header.sizeof_uninitialized_data() ==
parameters["optional_header"]["SizeOfUninitializedData"].as<uint32_t>());
REQUIRE(
optional_header.addressof_entrypoint() ==
parameters["optional_header"]["AddressOfEntryPoint"].as<uint32_t>());
REQUIRE(
optional_header.baseof_code() ==
parameters["optional_header"]["BaseOfCode"].as<uint32_t>());
if (binary->type() == LIEF::PE::PE_TYPE::PE32) {
REQUIRE(
optional_header.baseof_data() ==
parameters["optional_header"]["BaseOfData"].as<uint32_t>());
}
REQUIRE(
optional_header.imagebase() ==
parameters["optional_header"]["ImageBase"].as<uint64_t>());
REQUIRE(
optional_header.section_alignment() ==
parameters["optional_header"]["SectionAlignment"].as<uint32_t>());
REQUIRE(
optional_header.file_alignment() ==
parameters["optional_header"]["FileAlignment"].as<uint32_t>());
REQUIRE(
optional_header.major_operating_system_version() ==
parameters["optional_header"]["MajorOperatingSystemVersion"].as<uint32_t>());
REQUIRE(
optional_header.minor_operating_system_version() ==
parameters["optional_header"]["MinorOperatingSystemVersion"].as<uint32_t>());
REQUIRE(
optional_header.major_image_version() ==
parameters["optional_header"]["MajorImageVersion"].as<uint32_t>());
REQUIRE(
optional_header.minor_image_version() ==
parameters["optional_header"]["MinorImageVersion"].as<uint32_t>());
REQUIRE(
optional_header.major_subsystem_version() ==
parameters["optional_header"]["MajorSubsystemVersion"].as<uint32_t>());
REQUIRE(
optional_header.minor_subsystem_version() ==
parameters["optional_header"]["MinorSubsystemVersion"].as<uint32_t>());
REQUIRE(
optional_header.win32_version_value() ==
parameters["optional_header"]["Reserved1"].as<uint32_t>());
REQUIRE(
optional_header.sizeof_image() ==
parameters["optional_header"]["SizeOfImage"].as<uint32_t>());
REQUIRE(
optional_header.sizeof_headers() ==
parameters["optional_header"]["SizeOfHeaders"].as<uint32_t>());
REQUIRE(
optional_header.checksum() ==
parameters["optional_header"]["CheckSum"].as<uint32_t>());
REQUIRE(
static_cast<uint32_t>(optional_header.subsystem()) ==
parameters["optional_header"]["Subsystem"].as<uint32_t>());
REQUIRE(
optional_header.dll_characteristics() ==
parameters["optional_header"]["DllCharacteristics"].as<uint32_t>());
REQUIRE(
optional_header.sizeof_stack_reserve() ==
parameters["optional_header"]["SizeOfStackReserve"].as<uint64_t>());
REQUIRE(
optional_header.sizeof_stack_commit() ==
parameters["optional_header"]["SizeOfStackCommit"].as<uint64_t>());
REQUIRE(
optional_header.sizeof_heap_reserve() ==
parameters["optional_header"]["SizeOfHeapReserve"].as<uint64_t>());
REQUIRE(
optional_header.sizeof_heap_commit() ==
parameters["optional_header"]["SizeOfHeapCommit"].as<uint64_t>());
REQUIRE(
optional_header.loader_flags() ==
parameters["optional_header"]["LoaderFlags"].as<uint32_t>());
REQUIRE(
optional_header.numberof_rva_and_size() ==
parameters["optional_header"]["NumberOfRvaAndSizes"].as<uint32_t>());
}
// Sections
// ========
SECTION("Section") {
it_const_sections sections = binary->sections();
REQUIRE(
sections.size() ==
parameters["header"]["NumberOfSections"].as<uint16_t>());
if(parameters["sections"]) {
for (size_t i = 0; i < parameters["sections"].size(); ++i) {
const Section& section = sections[i];
REQUIRE(
parameters["sections"][i]["name"].as<std::string>() ==
section.name());
REQUIRE(
parameters["sections"][i]["Misc_VirtualSize"].as<uint32_t>() ==
section.virtual_size());
REQUIRE(
parameters["sections"][i]["VirtualAddress"].as<uint32_t>() ==
section.virtual_address());
REQUIRE(
parameters["sections"][i]["SizeOfRawData"].as<uint32_t>() ==
section.sizeof_raw_data());
REQUIRE(
parameters["sections"][i]["PointerToRawData"].as<uint32_t>() ==
section.pointerto_raw_data());
REQUIRE(
parameters["sections"][i]["PointerToRelocations"].as<uint32_t>() ==
section.pointerto_relocation());
REQUIRE(
parameters["sections"][i]["PointerToLinenumbers"].as<uint32_t>() ==
section.pointerto_line_numbers());
REQUIRE(
parameters["sections"][i]["NumberOfRelocations"].as<uint32_t>() ==
section.numberof_relocations());
REQUIRE(
parameters["sections"][i]["NumberOfLinenumbers"].as<uint32_t>() ==
section.numberof_line_numbers());
REQUIRE(
parameters["sections"][i]["Characteristics"].as<uint32_t>() ==
section.characteristics());
}
}
}
// Imports
// =======
SECTION("Imports") {
if (not binary->has_imports()) {
return;
}
it_const_imports imports = binary->imports();
REQUIRE(
imports.size() ==
parameters["imports"].size());
for (size_t i = 0; i < parameters["imports"].size(); ++i) {
const Import& import = imports[i];
it_const_import_entries entries = import.entries();
REQUIRE(
parameters["imports"][i]["name"].as<std::string>() ==
import.name());
REQUIRE(
parameters["imports"][i]["entries"].size() ==
entries.size());
for (size_t j = 0; j < parameters["imports"][i]["entries"].size(); ++j) {
const ImportEntry& entry = entries[j];
if (not parameters["imports"][i]["entries"][j]["name"].IsNull()) {
REQUIRE(
parameters["imports"][i]["entries"][j]["name"].as<std::string>() ==
entry.name());
}
}
}
}
// TLS
// ===
SECTION("TLS") {
if(not binary->has_tls() or not parameters["tls"]) {
return;
}
const TLS& tls = binary->tls();
REQUIRE(
parameters["tls"]["StartAddressOfRawData"].as<uint64_t>() ==
tls.addressof_raw_data().first);
REQUIRE(
parameters["tls"]["EndAddressOfRawData"].as<uint64_t>() ==
tls.addressof_raw_data().second);
REQUIRE(
parameters["tls"]["AddressOfIndex"].as<uint64_t>() ==
tls.addressof_index());
REQUIRE(
parameters["tls"]["AddressOfCallBacks"].as<uint64_t>() ==
tls.addressof_callbacks());
REQUIRE(
parameters["tls"]["SizeOfZeroFill"].as<uint64_t>() ==
tls.sizeof_zero_fill());
REQUIRE(
parameters["tls"]["Characteristics"].as<uint64_t>() ==
tls.characteristics());
}
}

155
tests/pe/test_parser.py Normal file
View File

@ -0,0 +1,155 @@
#!/usr/bin/env python
import unittest
import lief
import tempfile
import sys
import subprocess
import stat
import os
import logging
import random
import itertools
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.WARNING)
from unittest import TestCase
from utils import get_sample
class TestSimple(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
self.winhello64 = lief.parse(get_sample('PE/PE64_x86-64_binary_winhello64-mingw.exe'))
self.atapi = lief.parse(get_sample('PE/PE64_x86-64_atapi.sys'))
def test_dos_header(self):
pass
#self.assertEqual(self.binall.interpreter, "/lib/ld-linux.so.2")
#self.assertEqual(self.binall.entrypoint, 0x774)
def test_header(self):
pass
def test_optional_header(self):
pass
def test_data_directories(self):
pass
def test_sections(self):
sections = self.winhello64.sections
self.assertEqual(len(sections), 17)
section = sections[4]
self.assertEqual(section.name, ".xdata")
self.assertEqual(section.offset, 0x3200)
self.assertEqual(section.size, 0x400)
self.assertEqual(section.virtual_address, 0x6000)
self.assertEqual(section.virtual_size, 0x204)
self.assertEqual(section.characteristics, 0x40300040)
def test_tls(self):
self.assertTrue(self.winhello64.has_tls)
tls = self.winhello64.tls
self.assertEqual(tls.addressof_callbacks, 0x409040)
self.assertEqual(tls.callbacks, [0x4019c0, 0x401990])
self.assertEqual(tls.addressof_index, 0x4075fc)
self.assertEqual(tls.sizeof_zero_fill, 0)
self.assertEqual(tls.characteristics, 0)
self.assertEqual(tls.addressof_raw_data, (0x40a000, 0x40a060))
self.assertEqual(tls.section.name, ".tls")
def test_imports(self):
imports = self.winhello64.imports
self.assertEqual(len(imports), 2)
kernel32 = imports[0]
self.assertEqual(kernel32.name, "KERNEL32.dll")
self.assertEqual(kernel32.import_address_table_rva, 0x81fc)
self.assertEqual(kernel32.import_lookup_table_rva, 0x803C)
self.assertEqual(len(kernel32.entries), 25)
entry_12 = kernel32.entries[12]
self.assertEqual(entry_12.name, "LeaveCriticalSection")
self.assertEqual(entry_12.data, 0x84ba)
self.assertEqual(entry_12.hint, 0x34b)
self.assertEqual(entry_12.iat_value, 0x84ba)
self.assertEqual(entry_12.iat_address, 0x825c)
msvcrt = imports[1]
self.assertEqual(msvcrt.name, "msvcrt.dll")
self.assertEqual(msvcrt.import_address_table_rva, 0x82cc)
self.assertEqual(msvcrt.import_lookup_table_rva, 0x810c)
self.assertEqual(len(msvcrt.entries), 29)
entry_0 = msvcrt.entries[0]
self.assertEqual(entry_0.name, "__C_specific_handler")
self.assertEqual(entry_0.data, 0x85ca )
self.assertEqual(entry_0.hint, 55)
self.assertEqual(entry_0.iat_value, 0x85ca )
self.assertEqual(entry_0.iat_address, 0x82cc)
def test_rich_header(self):
rheader = self.atapi.rich_header
self.assertEqual(rheader.key, 0xa476a6e3)
entries = rheader.entries
self.assertEqual(len(entries), 8)
entry_4 = entries[4]
self.assertEqual(entry_4.id, 0x95)
self.assertEqual(entry_4.build_id, 0x7809)
self.assertEqual(entry_4.count, 1)
def test_resources(self):
pass
def test_relocations(self):
pass
def test_symbols(self):
symbols = self.winhello64.symbols
self.assertEqual(len(symbols), 1097)
symbol = symbols[1]
self.assertEqual(symbol.name, "__mingw_invalidParameterHandler")
self.assertEqual(symbol.value, 0)
self.assertEqual(symbol.section_number, 1)
self.assertEqual(symbol.type, 32)
def test_exports(self):
pass
class TestPacker(TestCase):
def test_upx(self):
pass
class TestCorrupted(TestCase):
def test_weird(self):
pass
if __name__ == '__main__':
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)

View File

@ -1,89 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <dirent.h>
#include <iostream>
#include <yaml-cpp/yaml.h>
#include "utils.hpp"
extern const YAML::Node config;
namespace LIEF {
namespace PE {
namespace Test {
std::vector<std::string> get_test_cases(void) {
std::vector<std::string> pe_samples;
for (auto it = std::begin(config) ;it != std::end(config); ++it) {
std::string key = it->first.as<std::string>();
if (config[key]["format"].as<std::string>() == "PE") {
pe_samples.push_back(key);
}
}
return pe_samples;
}
std::vector<std::string> get_binary_test_cases(void) {
std::vector<std::string> pe_samples;
for (auto it = std::begin(config) ;it != std::end(config); ++it) {
std::string key = it->first.as<std::string>();
if (config[key]["format"].as<std::string>() == "PE" && config[key]["type"].as<std::string>() == "binary") {
pe_samples.push_back(key);
}
}
return pe_samples;
}
std::vector<std::string> get_library_test_cases(void) {
std::vector<std::string> pe_samples;
for (auto it = std::begin(config) ;it != std::end(config); ++it) {
std::string key = it->first.as<std::string>();
if (config[key]["format"].as<std::string>() == "PE" && config[key]["type"].as<std::string>() == "library") {
pe_samples.push_back(key);
}
}
return pe_samples;
}
std::vector<std::string> get_pe_files(void) {
auto endswith = [] (const std::string& string, const std::string& end) {
size_t pos = string.rfind(end);
return pos != std::string::npos and pos == (string.length() - end.length());
};
std::vector<std::string> filespath;
DIR *dir;
struct dirent *ent;
std::string samples_path = PATH_TO_SAMPLES;
samples_path += "/PE";
if ((dir = opendir(samples_path.c_str())) != NULL) {
while ((ent = readdir (dir)) != NULL) {
const std::string name = ent->d_name;
if (endswith(name, ".exe") or endswith(name, ".dll")) {
filespath.emplace_back(samples_path + "/" + name);
}
}
closedir (dir);
} else {
std::cerr << "Can't open '" << samples_path << "'." << std::endl;
}
return filespath;
}
}
}
}

View File

@ -1,32 +0,0 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_TEST_UTILS_H_
#define LIEF_PE_TEST_UTILS_H_
#include <vector>
#include <string>
namespace LIEF {
namespace PE {
namespace Test {
std::vector<std::string> get_test_cases(void);
std::vector<std::string> get_binary_test_cases(void);
std::vector<std::string> get_library_test_cases(void);
std::vector<std::string> get_pe_files(void);
}
}
}
#endif

Binary file not shown.

BIN
third-party/Catch2-2.2.3.zip vendored Normal file

Binary file not shown.