def main(args): enable_trace = args.output != 'off' # Listify extra modules. if args.extra_modules is None: extra_modules = [] ql = Qiling(extra_modules + [args.target], ".", # rootfs console=True if enable_trace else False, stdout=1 if enable_trace else None, stderr=1 if enable_trace else None, output=args.output, profile="smm/smm.ini") ql.os.after_module_execution_callbacks = [] ql.os.notify_after_module_execution = after_module_execution_callback # Load NVRAM environment. if args.nvram_file: with open(args.nvram_file, 'rb') as f: ql.env = pickle.load(f) # The last loaded image is the main module we're interested in fuzzing pe = pefile.PE(args.target, fast_load=True) image_base = ql.loader.images[-1].base entry_point = image_base + pe.OPTIONAL_HEADER.AddressOfEntryPoint # Not passing the fuzzing mode argument results in a dry run, without AFL's involvement. if args.mode: # We want AFL's forkserver to spawn new copies starting from the main module's entrypoint. ql.hook_address(callback=start_afl, address=entry_point, user_data=args) if args.taint: taint.tracker.enable(ql, args.taint) # Init SMM related protocols smm.init(ql, args.mode == 'swsmi') # Run custom initialization script. if args.load_package: mod = importlib.import_module(args.load_package) if hasattr(mod, 'run'): mod.run(ql) # Enable sanitizers. if args.sanitize: for name in args.sanitize: sanitizers.get(name)(ql).enable() # okay, ready to roll. try: ql.run(end=args.end, timeout=args.timeout) except Exception as ex: # Probable Unicorn memory error. Treat as crash. verbose_abort(ql) os._exit(0) # that's a looot faster than tidying up.
def main(target_binary, nvram_file, var_name, input_file, output, end, timeout, sanitize, track_uninitialized, extra_modules): enable_trace = output != 'off' # Listify extra modules. if extra_modules is None: extra_modules = [] ql = Qiling( extra_modules + [target_binary], ".", # rootfs console=True if enable_trace else False, stdout=1 if enable_trace else None, stderr=1 if enable_trace else None, output=output) # Load NVRAM environment. with open(nvram_file, 'rb') as f: ql.env = pickle.load(f) # The last loaded image is the main module we're interested in fuzzing pe = pefile.PE(target_binary, fast_load=True) image_base = ql.loader.images[-1].base entry_point = image_base + pe.OPTIONAL_HEADER.AddressOfEntryPoint # We want AFL's forkserver to spawn new copies starting from the main module's entrypoint. ql.hook_address(callback=start_afl, address=entry_point, user_data=(input_file, var_name, sanitize)) if sanitize: enable_sanitized_heap(ql) enable_sanitized_CopyMem(ql) enable_sanitized_SetMem(ql) if track_uninitialized: enable_uninitialized_memory_tracker(ql) # okay, ready to roll. try: ql.run(end=end, timeout=timeout) except Exception as ex: # Probable Unicorn memory error. Treat as crash. verbose_abort(ql) os._exit(0) # that's a looot faster than tidying up.
def test_uninitialized_memory_tracker(): enable_trace = True ql = Qiling( ['./bin/UninitializedMemoryTrackerTest.efi'], ".", # rootfs console=True if enable_trace else False, stdout=1 if enable_trace else None, stderr=1 if enable_trace else None, output='debug') # NVRAM environment. ql.env = {'foo': b'\xde\xad\xbe\xef'} def validate_taint_set_variable(ql, address, params): assert params['VariableName'] == 'bar' and params['DataSize'] == 0x14 begin = params['Data'] end = params['Data'] + params['DataSize'] tainted_bytes = ql.tainters['uninitialized'].get_taint_range( begin, end) assert tainted_bytes == [ True, True, True, True, True, True, False, False, False, False, True, True, True, True, True, True, True, False, True, True ] # Un-taint to avoid crashing the process. ql.tainters['uninitialized'].set_taint_range(begin, end, False) return (address, params) # Hook SetVariable() to check the taint on the buffer. set_variable_spy = mockito.spy(validate_taint_set_variable) ql.set_api("SetVariable", set_variable_spy, QL_INTERCEPT.ENTER) # okay, ready to roll. enable_uninitialized_memory_tracker(ql) ql.run() # Make sure that SetVariable() was intercepted once. mockito.verify(set_variable_spy, times=1).__call__(*mockito.ARGS)