Merge pull request #1 from zeronounours/master

Make extraction of offsets compatible with Linux
This commit is contained in:
Qazeer
2021-12-08 14:52:44 +01:00
committed by GitHub
2 changed files with 33 additions and 25 deletions
+33 -24
View File
@@ -1,13 +1,13 @@
import argparse
import csv
import os
import sys
from requests import get
from gzip import decompress
from json import loads, dumps
from subprocess import run
import subprocess
import win32api
from concurrent.futures import ThreadPoolExecutor
import threading
CSVLock = threading.Lock()
@@ -16,6 +16,13 @@ machineType = dict(x86=332, x64=34404)
knownImageVersions = dict(ntoskrnl=list(), wdigest=list())
extensions_by_mode = dict(ntoskrnl="exe", wdigest="dll")
def run(args, **kargs):
"""Wrap subprocess.run to works on Windows and Linux"""
# Windows needs shell to be True, to locate binary automatically
# On Linux, shell needs to be False to manage lists in args
shell = sys.platform in ["win32"]
return subprocess.run(args, shell=shell, **kargs)
def downloadSpecificFile(entry, pe_basename, pe_ext, knownPEVersions, output_folder):
pe_name = f'{pe_basename}.{pe_ext}'
@@ -97,17 +104,21 @@ def get_field_offset(symbols_info, field_name):
return 0
def get_file_version(path):
info = win32api.GetFileVersionInfo(path, '\\')
ms = info['FileVersionMS']
ls = info['FileVersionLS']
return (win32api.HIWORD(ms), win32api.LOWORD(ms),
win32api.HIWORD(ls), win32api.LOWORD(ls))
# dump version number using r2
r = run(["r2", "-c", "iV", "-qq", path], capture_output=True)
for line in r.stdout.decode().splitlines():
line = line.strip()
if line.startswith("FileVersion:"):
return [int(frag) for frag in line.split(" ")[-1].split(".")]
print(f'[!] ERROR : failed to extract version from {path}.')
exit(1)
def extractOffsets(input_file, output_file, mode):
if os.path.isfile(input_file):
try:
# check image type (ntoskrnl, wdigest, etc.)
r = run(["r2", "-c", "iE", "-qq", input_file], shell=True, capture_output=True)
r = run(["r2", "-c", "iE", "-qq", input_file], capture_output=True)
for line in r.stdout.decode().splitlines():
if "ntoskrnl.exe" in line:
imageType = "ntoskrnl"
@@ -123,17 +134,6 @@ def extractOffsets(input_file, output_file, mode):
if mode != imageType:
print(f"[*] Skipping {input_file} since we are in {mode} mode")
return
# dump version number
"""
r = run(["r2", "-c", "iV", "-qq", input_file], shell=True, capture_output=True)
for line in r.stdout.decode().splitlines():
line = line.strip()
if line.startswith("FileVersion:"):
full_version = [int(frag) for frag in line.split(" ")[-1].split(".")]
break
else:
assert(False)
"""
if os.path.sep not in input_file:
input_file = "." + os.path.sep + input_file
full_version = get_file_version(input_file)
@@ -149,9 +149,9 @@ def extractOffsets(input_file, output_file, mode):
print(f'[*] Processing {imageType} version {imageVersion} (file: {input_file})')
# download the PDB if needed
r = run(["r2", "-c", "idpd", "-qq", input_file], shell=True, capture_output=True)
r = run(["r2", "-c", "idpd", "-qq", input_file], capture_output=True)
# dump all symbols
r = run(["r2", "-c", "idpi", "-qq", '-B', '0', input_file], shell=True, capture_output=True)
r = run(["r2", "-c", "idpi", "-qq", '-B', '0', input_file], capture_output=True)
all_symbols_info = [line.strip() for line in r.stdout.decode().splitlines()]
if imageType == "ntoskrnl":
@@ -231,12 +231,21 @@ if __name__ == '__main__':
exit(1)
# check R2 version
output = run(["r2", "-V"], shell=True, capture_output=True).stdout.decode()
output = run(["r2", "-V"], capture_output=True).stdout.decode()
ma,me,mi = map(int, output.splitlines()[0].split(" ")[0].split("."))
if (ma, me, mi) < (5,4,3):
print("WARNING : This script has been tested with radare2 5.4.3 (works) and 4.3.1 (does NOT work)")
if (ma, me, mi) < (5,0,0):
print("WARNING : This script has been tested with radare2 5.0.0 (works) and 4.3.1 (does NOT work)")
print(f"You have version {ma}.{me}.{mi}, if is does not work correctly, meaning most of the offsets are not found (i.e. 0), check radare2's 'idpi' command output and modify get_symbol_offset() & get_field_offset() to parse symbols correctly")
input("Press enter to continue")
if sys.platform in ["linux"]:
# check that cabextract is insalled
try:
run(["cabextract", "-v"], check=True, capture_output=True)
except (subprocess.CalledProcessError, FileNotFoundError):
print('[!] ERROR : On Linux systems, radare2 needs cabextract to be installed to work with PDB.')
exit(1)
if "R2_CURL" not in os.environ:
print("WARNING : On Linux systems, radare2 may have trouble to download PDB files. If offsets are reported as 0, export R2_CURL=1 prior to running the script.")
# If the output file exists, load the already analyzed image versions.
-1
View File
@@ -1,2 +1 @@
requests
pywin32