Created
May 19, 2020 01:53
-
-
Save psifertex/afe7f72820211d3f92919bc200978038 to your computer and use it in GitHub Desktop.
scan for getenv and dlopen calls
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
# Quick and dirty BN script for part of the whooo-r-u challenge during DEFCON Quals 2020. | |
# Used to identify likely environment variables and library names that were | |
# fed to other fuzzing sripts for SUID abuse | |
from binaryninja import * | |
import os | |
from pprint import pprint | |
import json | |
libname = "getenv" #re-ran the script with different arguments, not elegant, but it's CTF and both take a string in the first parameter... | |
libname = "dlopen" | |
def find_mlil_calls_to_targets(mlil_func, interesting_targets): | |
for insn in mlil_func.instructions: | |
if insn.operation != MediumLevelILOperation.MLIL_CALL: | |
continue | |
target = insn.dest.value | |
if target.type not in [ RegisterValueType.ConstantPointerValue, RegisterValueType.ConstantValue, RegisterValueType.ImportedAddressValue ]: | |
continue | |
if target.value not in interesting_targets: | |
continue | |
yield insn | |
return | |
ignore=[] | |
with open("skipped.log", "r") as f: | |
for line in f.read().split("\n"): | |
(fn, reason) = line.split(",") | |
if reason == " noresults": | |
ignore.append(fn) | |
skipped = open("skipped.log", "a") | |
parsed = open("results.log", "a") | |
for subdir, dirs, files in os.walk('/noback/dump/files'): | |
for filename in files: | |
filepath = subdir + os.sep + filename | |
if filepath in ignore: | |
continue | |
'''#Used this to scan for small files first to validate the concept | |
if os.stat(filepath).st_size > 2**17: | |
skipped.write(filepath + ", size\n") | |
skipped.flush() | |
continue''' | |
print("Parsing: %s" % filepath) | |
bv = BinaryViewType.get_view_of_file(filepath) | |
syms = list(filter(lambda sym: libname in sym.name, bv.get_symbols())) | |
targets = set(map(lambda sym: sym.address, syms)) | |
calling_funcs = set() | |
for target in targets: | |
for xref in bv.get_code_refs(target): | |
calling_funcs.add(xref.function) | |
envs = [] | |
for caller in calling_funcs: | |
mlil = caller.medium_level_il | |
for i in find_mlil_calls_to_targets(mlil, targets): | |
if len(i.params) >= 1 and hasattr(i.params[0], "value") and hasattr(i.params[0].value, "type") and (i.params[0].value.type == RegisterValueType.ConstantPointerValue or i.params[0].value.type == RegisterValueType.ConstantValue): | |
try: | |
address = i.params[0].constant | |
except: | |
address = i.params[0].value.value | |
if address != 0: | |
string = bv.get_ascii_string_at(address) | |
if string != None: | |
envs.append(string.value) | |
output = { 'filename' : filepath[18:], 'dlopen': list(set(envs)) } | |
bv.file.close() | |
if len(envs) > 0: | |
results.write(json.dumps(output) + "\n") | |
results.flush() #used to better monitor during execution | |
print(json.dumps(output)) | |
else: | |
skipped.write(filepath + ", noresults\n") | |
skipped.flush() #used to better monitor during execution |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment