Example #1
0
def test_stub_procedure_args():
    # stub procedures should have the right number of arguments

    lib.set_prototype(
        "____a_random_stdcall_function__",
        SimTypeFunction(
            [
                SimTypeInt(signed=True),
                SimTypeInt(signed=True),
                SimTypeInt(signed=False)
            ],
            SimTypePointer(SimTypeChar(), offset=0),
            arg_names=["_random_arg_0", "_random_arg_1", "_random_arg_2"]))
    stub = lib.get_stub('____a_random_stdcall_function__', archinfo.ArchX86())
    stub.cc = SimCCStdcall(archinfo.ArchX86())
    lib._apply_metadata(stub, archinfo.ArchX86())
    assert len(stub.cc.args) == 3
    assert all(isinstance(arg, SimStackArg) for arg in stub.cc.args)

    proj = angr.Project(os.path.join(binaries_base, "i386", "all"),
                        auto_load_libs=False)
    state = proj.factory.blank_state()

    initial_sp = state.regs.sp
    stub.state = state
    stub.successors = SimSuccessors(0, state)
    stub.ret(0)

    succ = stub.successors.all_successors[0]
    assert state.solver.eval_one(succ.regs.sp - initial_sp) == 0x10
Example #2
0
def _hook_all_aux(proj):
    sim_procs = [x for x in globals().values() if inspect.isclass(x) and issubclass(x, angr.SimProcedure)]

    for sp in sim_procs:
        if issubclass(sp, StdcallSimProcedure):
            proj.hook_symbol(sp.__name__, sp(cc=SimCCStdcall(proj.arch)))
        else:
            # use default cc for the arch (for x86 it's Cdecl)
            proj.hook_symbol(sp.__name__, sp())
Example #3
0
def find_ioctls(filename, dispatch_device_control, address_size=8):
    """Symbolically explore the dispatch function to find supported IOCTLs.

    We want to symbolically explore the function until we enter a state
    where the IOCTL is constrained to a single value. Return a map of IOCTL
    codes to a list of addresses where the handling code starts.
    """
    proj = angr.Project(filename, auto_load_libs=False)

    # Create a call state with a symbolic IRP
    sirp = SymbolicIrp(address_size * 8)
    siosl = SymbolicDeviceIoControlIoStackLocation(address_size * 8)
    sirp.current_stack_location = PointerWrapper(siosl.pack())
    irp = sirp.pack()

    if address_size == 4:
        cc = SimCCStdcall(proj.arch)
    else:
        cc = SimCCMicrosoftAMD64(proj.arch)
    state = proj.factory.call_state(dispatch_device_control,
                                    claripy.BVS("DeviceObject", 64),
                                    irp,
                                    cc=cc,
                                    ret_addr=0xdeadbeef)

    def ioctl_constrained(st):
        """Return true if the IOCTL code is constrained to a single value."""
        try:
            st.solver.eval_one(siosl.io_control_code)
            return True
        except angr.SimValueError:
            return False

    # Run until all states finish
    simgr = proj.factory.simgr(state)
    while len(simgr.active) > 0:
        simgr.explore(find=ioctl_constrained, avoid=0xdeadbeef)
    #print(simgr)

    # Return a map of IOCTL codes to a list of handler addresses
    ioctls = collections.defaultdict(list)
    for s in simgr.found:
        # For some reason, the memory_endness for x64 symbolic variables isn't getting
        # set correctly. Account for little-endian manually.
        if address_size == 4:
            code = s.solver.eval_one(siosl.io_control_code)
            start = s.solver.eval_one(s.regs.eip)
        else:
            code = swap32(s.solver.eval_one(siosl.io_control_code))
            start = s.solver.eval_one(s.regs.rip)
        ioctls[code].append(start)

    return ioctls
Example #4
0
def setup(proj, aux_hooks=False, unhook=[], cdecl_stub=[], stdcall_stub=[]):
    if aux_hooks:
        _hook_all_aux(proj)

    for sym in unhook:
        proj.unhook_symbol(sym)

    for sym in cdecl_stub:
        proj.hook_symbol(sym, ReturnUnconstrained(cc=SimCCCdecl(proj.arch), is_stub=True))

    for sym in stdcall_stub:
        proj.hook_symbol(sym, ReturnUnconstrained(cc=SimCCStdcall(proj.arch), is_stub=True))
Example #5
0
def hook_all(proj):
    sim_procs = [
        x for x in win32_patches.__dict__.values()
        if inspect.isclass(x) and issubclass(x, angr.SimProcedure)
    ]

    for sp in sim_procs:
        if issubclass(sp, StdcallSimProcedure):
            proj.hook_symbol(sp.__name__, sp(cc=SimCCStdcall(proj.arch)))
        else:
            # use default cc for the arch (for x86 it's Cdecl)
            proj.hook_symbol(sp.__name__, sp())

    rdtsc_monkey_patch()
Example #6
0
 def create_cc(self, arch: Arch) -> Optional[SimCC]:
     if not isinstance(arch, ArchX86):
         # Use default calling convention unless arch is x86
         return None
     if self.cc_str in {
             "__stdcall",
             "__fastcall",
             "__thiscall",
             "__vectorcall",
             "X86StdCall",
     }:
         # Callee cleanup
         return SimCCStdcall(arch)
     return None
Example #7
0
@pytest.mark.parametrize("type_str,expected", [("SOCKET", True),
                                               (None, False)])
def test_has_complete_typing(type_str, expected):
    s = Parameter("s", type_str, "in")
    name = Parameter("name", "const sockaddr *", "in")
    namelen = Parameter("namelen", "int", "in")
    func_model = FunctionModel("connect", [s, name, namelen], "__stdcall")
    assert func_model.has_complete_typing == expected


@pytest.mark.parametrize(
    "arch,cc,cc_str",
    [
        (archinfo.ArchAMD64, None, "__stdcall"),
        (archinfo.ArchAMD64, None, "__cdecl"),
        (archinfo.ArchX86, SimCCStdcall(archinfo.ArchX86()), "__stdcall"),
        (archinfo.ArchX86, None, "__cdecl"),
        (archinfo.ArchARM, None, "__stdcall"),
        (archinfo.ArchARMEL, None, "__stdcall"),
        (archinfo.ArchARMHF, None, "__stdcall"),
        (archinfo.ArchARMCortexM, None, "__stdcall"),
        (archinfo.ArchAArch64, None, "__stdcall"),
        (archinfo.ArchPPC32, None, "__stdcall"),
        (archinfo.ArchPPC64, None, "__stdcall"),
        (archinfo.ArchMIPS32, None, "__stdcall"),
        (archinfo.ArchMIPS64, None, "__stdcall"),
        (archinfo.ArchSoot, None, "__stdcall"),
        (archinfo.ArchS390X, None, "__stdcall"),
    ],
)
def test_create_cc(arch, cc, cc_str):
Example #8
0
 def __init__(self, project: angr.Project):
     super().__init__(
         project=project,
         num_args=0,
         cc=SimCCStdcall(project.arch),
     )
Example #9
0
def find_sim_procedure(
    name: str,
    proj: angr.Project,
    export_manager: ExportManager,
    return_unconstrained: bool = True,
) -> Optional[SimProcedure]:
    """
    Find the appropriate SimProcedure for the given procedure name and project
    """
    arch = proj.arch

    # Use custom dynamic procedures
    # TODO: Add linux dynamic loading functions
    if name in custom_dynamic_procedures:
        cc = None
        if isinstance(arch, ArchX86):
            cc = SimCCStdcall(arch)
        if name == "GetProcAddress":
            return custom_dynamic_procedures["GetProcAddress"](proj,
                                                               export_manager,
                                                               cc)
        return custom_dynamic_procedures[name](proj, cc=cc)

    blacklist = {
        "_error",
    }
    if name in blacklist:
        # Don't hook function
        return

    # Search in cyfi's SimProcedures
    for lib, procs in cyfi_procedures.items():
        if name in procs:
            sim_proc = procs[name](proj)
            log.log(5, f"Found {sim_proc} in {lib} (cyfi)")
            return sim_proc

    # Search in angr's SimProcedures
    # TODO: Optionally search a single library
    for lib in angr.SIM_LIBRARIES:
        sim_lib = angr.SIM_LIBRARIES[lib]
        if type(sim_lib) == SimSyscallLibrary:
            if sim_lib.has_implementation(name, arch):
                sim_proc = sim_lib.get(name, arch)
                log.log(5, f"Found {sim_proc} in {lib} (angr)")
                return sim_proc
        else:
            if sim_lib.has_implementation(name):
                sim_proc = sim_lib.get(name, arch)
                log.log(5, f"Found {sim_proc} in {lib} (angr)")
                return sim_proc

    # Search for function model
    if export_manager.model_handler:
        try:
            sim_proc = export_manager.model_handler.create_procedure(
                name, proj)
            log.log(5, f"Found {sim_proc} in models")
            return sim_proc
        except ValueError:
            pass

    if return_unconstrained:
        # Not found anywhere. Return unconstrained value.
        sim_proc = ReturnUnconstrainedLog(proj, display_name=name)
        return sim_proc

    return