Skip to content

Instantly share code, notes, and snippets.

@psifertex
Created May 19, 2020 01:53
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 psifertex/afe7f72820211d3f92919bc200978038 to your computer and use it in GitHub Desktop.
Save psifertex/afe7f72820211d3f92919bc200978038 to your computer and use it in GitHub Desktop.
scan for getenv and dlopen calls
# 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