Skip to content

Instantly share code, notes, and snippets.

@learn-more
Created June 10, 2017 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save learn-more/96ef9669076b7e652d23325df4837882 to your computer and use it in GitHub Desktop.
Save learn-more/96ef9669076b7e652d23325df4837882 to your computer and use it in GitHub Desktop.
Analyze ReactOS binaries from a build dir
import sys
import os
import re
import pefile
CMAKE_PREFIX = '# Install script for directory: '
MANIFEST_DIR = pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE']
IMPORT_DIR = pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']
MANIFEST_ID = pefile.RESOURCE_TYPE['RT_MANIFEST']
INCLUDE_FILES = ('.exe', '.dll', '.acm', '.ax', '.cpl', '.drv', '.ocx')
def check_manifest(filename, peobj):
if peobj.is_exe():
if not hasattr(peobj, 'DIRECTORY_ENTRY_RESOURCE'):
peobj.parse_data_directories(directories=[MANIFEST_DIR])
if not hasattr(peobj, 'DIRECTORY_ENTRY_RESOURCE'):
return
res_entries = peobj.DIRECTORY_ENTRY_RESOURCE.entries
manifests = [entry for entry in res_entries if entry.id == MANIFEST_ID]
for entry in manifests:
for manifest in entry.directory.entries:
container = manifest.directory.entries[0].data
data = peobj.get_data(container.struct.OffsetToData, container.struct.Size)
if data.lower().find('Microsoft.Windows.Common-Controls'.lower()):
if not hasattr(peobj, 'DIRECTORY_ENTRY_IMPORT'):
peobj.parse_data_directories(directories=[IMPORT_DIR])
for import_entry in peobj.DIRECTORY_ENTRY_IMPORT:
if import_entry.dll.lower() == 'comctl32.dll':
return
print 'Missing import:', filename
def check_baseaddress(filename, peobj):
if not peobj.is_exe() and peobj.OPTIONAL_HEADER.ImageBase == 0x10000000:
print 'Missing base address:', filename
def analyze(filename):
if filename.lower().endswith(('.lnk', '.iso')):
return
try:
peobj = pefile.PE(filename, fast_load=True)
except pefile.PEFormatError:
# Not a PE file
return
check_manifest(filename, peobj)
check_baseaddress(filename, peobj)
def run_dir(target):
target_files = []
source_dir = None
for line in open(os.path.join(target, 'cmake_install.cmake'), 'r'):
if line.startswith(CMAKE_PREFIX):
source_dir = line[len(CMAKE_PREFIX):].strip()
break
if not source_dir:
print 'Unable to find source dir'
return
for lst in ['bootcd.lst', 'hybridcd.lst', 'livecd.lst', 'bootcdregtest.lst']:
for line in open(os.path.join(target, 'boot', lst), 'r'):
result = re.match(r'.*=(.*)', line)
if result:
target_files.append(os.path.normpath(result.group(1)))
# read cab contents
dyn_file = os.path.join(target, 'boot', 'bootdata', 'packages', 'reactos.dff.dyn')
for line in open(dyn_file, 'r'):
result = re.match(r'"(.*)" \d+', line)
if result:
target_files.append(os.path.normpath(os.path.join(source_dir, result.group(1))))
target_files = list(set(target_files))
# for root, dirs, files in os.walk(target, topdown=True):
# dirs[:] = [d for d in dirs if d not in ['CMakeFiles', 'host-tools']]
# for curfile in files:
# lower = curfile.lower()
# if lower.endswith(INCLUDE_FILES):
# target_files.append(os.path.join(root, curfile))
for curfile in target_files:
analyze(curfile)
print 'Done'
def main(dirs):
for curdir in dirs:
run_dir(curdir)
if __name__ == '__main__':
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment