Created
June 10, 2017 19:43
-
-
Save learn-more/96ef9669076b7e652d23325df4837882 to your computer and use it in GitHub Desktop.
Analyze ReactOS binaries from a build dir
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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