mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-04-26 20:34:32 +00:00
WIP
This commit is contained in:
parent
9142c2bfb3
commit
4b649ad231
@ -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
|
||||
# ==============
|
||||
|
@ -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()
|
@ -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()
|
@ -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
|
@ -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)
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
#
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
56
tests/elf/test_builder.py
Normal 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)
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
98
tests/elf/test_equality.py
Normal file
98
tests/elf/test_equality.py
Normal 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)
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
234
tests/elf/test_parser.py
Normal 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)
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -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
155
tests/pe/test_parser.py
Normal 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)
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
BIN
third-party/Catch-1.10.0.zip
vendored
BIN
third-party/Catch-1.10.0.zip
vendored
Binary file not shown.
BIN
third-party/Catch2-2.2.3.zip
vendored
Normal file
BIN
third-party/Catch2-2.2.3.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user