Beispiel #1
0
def json_to_simval(d: Dict[str, Any]) -> SV.SimValue:
    id = d["i"]

    # SimValue (generic, covers all cases with jsonval implementation)
    if id == "x":
        return SSV.SimSymbolicValue(0, defined=False)

    # SimByteValue
    elif id == "b":
        if "d" in d:
            data = d["d"]
            v: int = data.get("v", 0)
            defined: bool = data.get("d", True)
            return SV.SimByteValue(v, defined)
        else:
            return SV.SimByteValue(0)

    # SimDoubleWordValue
    elif id == "d":
        if "d" in d:
            data = d["d"]
            v = data.get("v", 0)
            defined = data.get("d", True)
            b1defined: bool = data.get("db1", True)
            b2defined: bool = data.get("db2", True)
            b3defined: bool = data.get("db3", True)
            b4defined: bool = data.get("db4", True)
            return SV.SimDoubleWordValue(v,
                                         defined=defined,
                                         b1defined=b1defined,
                                         b2defined=b2defined,
                                         b3defined=b3defined,
                                         b4defined=b4defined)
        else:
            return SV.SimDoubleWordValue(0)

    # SimGlobalAddress
    elif id == "sga":
        data = d["d"]
        modulename: str = data.get("m", "?")
        offset = cast(SV.SimDoubleWordValue, json_to_simval(data["o"]))
        return SSV.SimGlobalAddress(modulename, offset)

    # SimReturnAddress
    elif id == "sra":
        data = d["d"]
        modulename = data.get("m", "?")
        functionaddr: str = data["f"]
        offset = cast(SV.SimDoubleWordValue, json_to_simval(data["o"]))
        return SSV.SimReturnAddress(modulename, functionaddr, offset)

    # SimMemoryByteLink
    elif id == "bl":
        data = d["d"]
        linkedto = cast(SSV.SimSymbolicValue, json_to_simval(data["l"]))
        position: int = cast(int, data["p"])
        return SimMemoryByteLink(linkedto, position)

    else:
        raise UF.CHBError("No deserialization implemented yet for id = " + id)
Beispiel #2
0
 def resolve_import_symbol(self, importsym: str) -> SSV.SimGlobalAddress:
     for dynlib in self.dynlibs:
         if dynlib.is_exported(importsym):
             faddr = dynlib.export_address(importsym)
             return SSV.mk_global_address(faddr, dynlib.name)
     else:
         return SSV.mk_undefined_global_address(self.modulename)
    def do_initialization(self, simstate: "SimulationState") -> None:
        simstate.registers["sp"] = SSV.SimStackAddress(SV.simZero)
        simstate.registers["zero"] = SV.simZero
        for reg in [
                "ra", "gp", "fp", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
                "s7"
        ]:
            simstate.registers[reg] = SSV.SimSymbol(reg + "_in")
        simstate.registers["t9"] = SSV.mk_global_address(
            int(simstate.startaddr, 16), modulename=simstate.modulename)

        if len(self.cmdlineargs) > 0:
            self.initialize_cmdline_arguments(simstate)
 def mk_address(self, offset: int) -> SSV.SimAddress:
     addr = cast(SV.SimDoubleWordValue, SV.mk_simvalue(offset, size=4))
     if self.name.startswith("global"):
         names = self.name.split(":")
         if len(names) == 2:
             image = names[1]
         else:
             image = "mainx"
         return SSV.SimGlobalAddress(image, addr)
     elif self.name == "stack":
         return SSV.SimStackAddress(addr)
     else:
         return SSV.SimBaseAddress(self.name, addr)
Beispiel #5
0
 def get(self,
         iaddr: str,
         address: SSV.SimAddress,
         size: int) -> SV.SimValue:
     try:
         for base in self.baseoffsets:
             if (
                     address.offsetvalue >= base
                     and address.offsetvalue < base + self.buffersize):
                 address = address.add_offset(-base)
                 try:
                     memval = SimMemory.get(self, iaddr, address, size)
                 except SU.CHBSimError:
                     memval = SV.mk_simvalue(0, size=size)
                 return memval
         else:
             raise SU.CHBSimError(
                 self.simstate,
                 iaddr,
                 "invalid shared memory address: " + str(address))
     except SU.CHBSimError as e:
         print("Error in shared memory: " + str(e))
         name = (self.name
                 + '['
                 + str(address.offsetvalue)
                 + ']'
                 + ' (value not retrieved: '
                 + str(e)
                 + ')')
         return SSV.SimSymbol(name)
Beispiel #6
0
    def simulate(self, iaddr: str, simstate: "SimulationState") -> str:
        dstop = self.dst_operand
        srcop = self.src_operand
        srcval = simstate.rhs(iaddr, srcop)

        result: SV.SimValue
        if srcval.is_undefined:
            result = SV.simUndefinedDW

        if srcval.is_global_address:
            val = cast(SV.SimDoubleWordValue,
                       SV.mk_simvalue(srcval.literal_value))
            srcval = cast(SSV.SimGlobalAddress, srcval)
            name = srcval.modulename
            resultval = val.swap_bytes_within_halfwords()
            result = SSV.mk_global_address(resultval.literal_value, name)

        elif srcval.is_literal:
            val = cast(SV.SimDoubleWordValue, srcval)
            result = val.swap_bytes_within_halfwords()

        else:
            raise SU.CHBSimError(
                simstate, iaddr, "wsbh: operand not recognized: " +
                str(srcop) + ": " + str(srcval))

        lhs = simstate.set(iaddr, dstop, result)
        simstate.increment_programcounter()
        return SU.simassign(iaddr,
                            simstate,
                            lhs,
                            result,
                            intermediates=str(srcval))
Beispiel #7
0
 def simulate(self, iaddr: str, simstate: "SimulationState") -> str:
     tgtaddr = self.target.absolute_address_value
     tgt = simstate.resolve_literal_address(iaddr, tgtaddr)
     simstate.increment_programcounter()
     simra = SSV.pc_to_return_address(
         simstate.programcounter.add_offset(4), simstate.function_address)
     simstate.registers["ra"] = simra
     simstate.simprogramcounter.set_delayed_programcounter(tgt)
     return SU.simcall(iaddr, simstate, tgt, simra)
Beispiel #8
0
 def rhs_symbol(self, iaddr: str, sym: SSV.SimSymbol, offset: int,
                opsize: int) -> SV.SimValue:
     base = sym.name
     if base.startswith("/stderr"):
         return sym
     if base not in self.basemem:
         self.basemem[base] = SimBaseMemory(self, base)
         self.add_logmsg(iaddr, "Initialize base memory for " + base)
     addr: SSV.SimAddress = SSV.mk_base_address(base, offset=offset)
     return self.memval(iaddr, addr, opsize)
 def get(self, iaddr: str, address: SSV.SimAddress,
         size: int) -> SV.SimValue:
     try:
         memval = SimMemory.get(self, iaddr, address, size)
     except SU.CHBSimError as e:
         print("Error in basemem: " + str(e))
         name = (self.name + '[' + str(address.offsetvalue) + ']' +
                 ' (value not retrieved: ' + str(e) + ')')
         return SSV.SimSymbol(name)
     else:
         return memval
Beispiel #10
0
def simulate_arm_function(xname: str, app: "ARMAccess", asm: "ARMAssembly",
                          faddr: str) -> NoReturn:
    base = app.header.image_base
    mainparticipant = SimModule("app", app, base, app.max_address)
    simstate = SimulationState(
        faddr, mainparticipant,
        ARMSimProgramCounter(SSV.mk_global_address(int(faddr, 16), xname)))
    currentinstr = asm.instructions[faddr]
    print(str(currentinstr))

    exit(0)
def sim_openfile(filename: str, mode: str) -> SSV.SimSymbolicFilePointer:
    print("Open file " + filename)
    if SSV.SimSymbolicFilePointer.has_openfile(filename):
        return SSV.SimSymbolicFilePointer.openfile(filename)

    if filename.startswith("/"):
        simfilename = os.path.join("simdisk", filename[1:])
        simpathname = os.path.dirname(simfilename)
        if not os.path.exists(simpathname):
            print("make dir: " + simpathname + " (" + simfilename + ")")
            os.makedirs(simpathname)
        print("Open " + simfilename + " with mode " + mode)
        fp = open(simfilename, mode)
        symfp = SSV.mk_filepointer(filename, simfilename, fp)
        SSV.SimSymbolicFilePointer.add_openfile(filename, symfp)
        return symfp
    else:
        return SSV.mk_filepointer(filename,
                                  simfilename,
                                  filename,
                                  defined=False)
Beispiel #12
0
 def __init__(self,
              startaddr: str,
              mainx: X86SimModule,
              simprogramcounter: SimProgramCounter,
              x86fn: "X86Function",
              simsupport: SimSupport = SimSupport(),
              dynlibs: Sequence[X86SimModule] = [],
              bigendian: bool = False) -> None:
     SimulationState.__init__(self,
                              startaddr,
                              mainx,
                              simprogramcounter,
                              simsupport=simsupport,
                              dynlibs=dynlibs,
                              bigendian=bigendian)
     self._x86fn = x86fn
     self.uninitializedregion: Optional[Tuple[SSV.SimGlobalAddress,
                                              SSV.SimGlobalAddress]] = None
     self.flags: Dict[str, SV.SimBoolValue] = {}  # flagname -> SimBoolValue
     self.registers: Dict[str, SV.SimValue] = {}
     self._globalmem = SimGlobalMemory(self)
     self.stackmem = SimStackMemory(self)
     self.fnlog: Dict[str, List[str]] = {}  # iaddr -> msg list
     self.registers['esp'] = SSV.mk_stack_address(0)
     self.registers['ebp'] = SSV.mk_symbol('ebp-in')
     self.registers['eax'] = SSV.mk_symbol('eax-in')
     self.registers['ecx'] = SSV.mk_symbol('ecx-in')
     self.stackmem.set("0", SSV.mk_stack_address(0),
                       SSV.SimSymbolicReturnAddress())
     self.flags['DF'] = SV.simflagclr  # direction forward
     self.flags['CF'] = SV.simflagclr  # no carry
     self.flags['PF'] = SV.simflagclr  # even parity
     self.flags['ZF'] = SV.simflagclr  # no zero result
     self.flags['SF'] = SV.simflagclr  # unsigned result
     self.flags['OF'] = SV.simflagclr  # no overflow occurred
    def simulate(self, iaddr: str, simstate: "SimulationState") -> str:
        dstop = self.dst_operand
        srcop = self.src_operand
        srcval = simstate.rhs(iaddr, srcop)
        immval = self.imm_operand.to_signed_int()
        imm = SV.mk_simvalue(immval)

        def do_assign(result: SV.SimValue) -> str:
            lhs = simstate.set(iaddr, dstop, result)
            simstate.increment_programcounter()
            return SU.simassign(iaddr, simstate, lhs, result,
                                "val(" + str(srcop) + ") = " + str(srcval))

        if srcval.is_undefined:
            return do_assign(SV.simUndefinedDW)

        if srcval.is_symbol:
            expr = str(srcval) + ' + ' + str(immval)
            raise SU.CHBSymbolicExpression(simstate, iaddr, dstop, expr)

        elif srcval.is_address:
            srcval = cast(SSV.SimAddress, srcval)
            return do_assign(srcval.add_offset(immval))

        elif srcval.is_literal:
            return do_assign(SV.mk_simvalue(srcval.literal_value + immval))

        elif srcval.is_string_address:
            srcval = cast(SSV.SimStringAddress, srcval)
            if immval == len(srcval.stringval):
                result = SSV.mk_string_address('')
            else:
                result = SSV.mk_string_address(srcval.stringval[immval:])
            return do_assign(result)

        else:
            return do_assign(SV.simUndefinedDW)
    def simulate(self, iaddr: str, simstate: "SimulationState") -> str:
        tgtop = self.tgt_operand
        tgtval = simstate.rhs(iaddr, tgtop)
        simra = SSV.pc_to_return_address(simstate.programcounter.add_offset(8),
                                         simstate.function_address)
        simstate.increment_programcounter()
        simstate.registers['ra'] = simra

        if tgtval.is_undefined:
            raise SU.CHBSimError(
                simstate, iaddr,
                "jalr: target address is undefined: " + str(tgtop))

        tgtaddr: Union[SSV.SimGlobalAddress, SSV.SimDynamicLinkSymbol]
        if tgtval.is_address:
            tgtval = cast(SSV.SimAddress, tgtval)
            if tgtval.is_global_address:
                tgtaddr = cast(SSV.SimGlobalAddress, tgtval)
            else:
                raise SU.CHBSimError(
                    simstate, iaddr,
                    "target address is not global: " + str(tgtval))

        # check if literal could be an address
        elif tgtval.is_literal:
            tgtaddr = simstate.resolve_literal_address(iaddr,
                                                       tgtval.literal_value)
            if tgtaddr.is_undefined:
                raise SU.CHBSimError(
                    simstate, iaddr,
                    "jalr: target address cannot be resolved: " + str(tgtval))

        elif tgtval.is_dynamic_link_symbol:
            tgtaddr = cast(SSV.SimDynamicLinkSymbol, tgtval)

        elif tgtval.is_symbolic:
            raise SU.CHBSimError(
                simstate, iaddr,
                ("symbolic target address not recognized: " + str(tgtval)))
        else:
            raise SU.CHBSimCallTargetUnknownError(simstate, iaddr, tgtval,
                                                  'target = ' + str(tgtval))

        simstate.simprogramcounter.set_delayed_programcounter(tgtaddr)
        return SU.simcall(iaddr, simstate, tgtaddr, simra)
Beispiel #15
0
    def resolve_literal_address(self, iaddr: str,
                                addrvalue: int) -> SSV.SimGlobalAddress:
        addr = self.modulestates[self.modulename].resolve_literal_address(
            iaddr, addrvalue)
        if addr.is_defined:
            return addr
        # elif addrvalue == 2:
        #    return SFU.sim_openfile("sim_stderr", "w")

        else:
            for shmid in self.sharedmem:
                if self.sharedmem[shmid].has_address(addrvalue):
                    addr = SSV.mk_global_address(addrvalue,
                                                 "shared:" + str(shmid))
                    return addr
            else:
                raise SU.CHBSimError(
                    self, iaddr, ("Unable to resolve address: " +
                                  hex(addrvalue) + " in " + self.modulename))
    def initialize_cmdline_arguments(self,
                                     simstate: "SimulationState") -> None:
        simstate.registers["a0"] = SV.mk_simvalue(len(self.cmdlineargs))
        simstate.registers["a1"] = SSV.mk_stack_address(16)

        aoffset = 100  # offset of information block on the initial process stack
        for (i, arg) in enumerate(self.cmdlineargs):
            argptr = SSV.mk_stack_address((i * 4) + 16)
            argvalptr = SSV.mk_stack_address(aoffset)
            simstate.set_memval(simstate.startaddr, argptr, argvalptr)
            for c in arg:
                addr = SSV.mk_stack_address(aoffset)
                cval = SV.mk_simcharvalue(c)
                simstate.set_memval(simstate.startaddr, addr, cval)
                aoffset += 1
            addr = SSV.mk_stack_address(aoffset)
            simstate.set_memval(simstate.startaddr, addr, SV.simZerobyte)
            aoffset += 1

        # null-terminate the list of arguments
        argptr = SSV.mk_stack_address((len(self.cmdlineargs) * 4) + 16)
        simstate.set_memval(simstate.startaddr, argptr, SV.simZero)
Beispiel #17
0
 def set_uninitialized_region(self, low: str, high: str) -> None:
     self.uninitializedregion = (SSV.mk_global_address(
         int(low, 16), self.modulename),
                                 SSV.mk_global_address(
                                     int(high, 16), self.modulename))
def simulate_mips_function(
        xname: str,
        app: "MIPSAccess",
        asm: "MIPSAssembly",
        faddr: str,
        stepcount: int = 100,
        libs: Dict[str, Tuple["MIPSAccess", "MIPSAssembly"]] = {},
        support: Optional[str] = None,
        stub_imports: List[str] = [],
        mainargs: List[str] = [],
        optargaddrstr: Optional[str] = None,
        optargstatestr: Optional[str] = None,
        patched_globals: Dict[str, str] = {},
        envptr_addr: Optional[str] = None) -> NoReturn:

    bigendian = app.header.is_big_endian
    print("big endian " if bigendian else "little endian")

    stubs: Dict[str, "MIPSimStub"] = stubbed_libc_functions()
    for stubimport in stub_imports:
        importedstubs = importlib.import_module(stubimport)
        print("\nImported user stubs: " + importedstubs.__name__)
        for d in dir(importedstubs):
            if d.endswith("stubs"):
                userstubs: Dict[str, "MIPSimStub"] = getattr(importedstubs, d)()
                stubs.update(userstubs)

    print(
        "Main module "
        + xname
        + ": "
        + app.header.image_base
        + " - "
        + app.max_address)
    mainmodule = SimModule(xname, app, app.header.image_base, app.max_address)

    dynlibs: List[SimModule] = []
    dynasms: Dict[str, "MIPSAssembly"] = {}
    for (libname, (libapp, libasm)) in libs.items():
        print(
            "Lib module "
            + libname
            + ": "
            + libapp.header.image_base
            + " - "
            + app.max_address)
        dynlibs.append(SimModule(
            libname, libapp, libapp.header.image_base, libapp.max_address))
        dynasms[libname] = libasm

    if envptr_addr is not None:
        environmentptr_address: Optional[SSV.SimGlobalAddress] = SSV.mk_global_address(
            int(envptr_addr, 16), modulename=mainmodule.name)
    else:
        environmentptr_address = None

    optargaddr: SV.SimValue = SV.simZero
    optargstate: SV.SimValue = SV.simZero
    if optargaddrstr:
        optargaddr = SSV.mk_global_address(int(optargaddrstr, 16), xname)
    if optargstatestr:
        optargstate = SSV.mk_global_address(int(optargstatestr, 16), xname)

    def default_simsupport() -> SimSupport:
        return SimSupport(
            stepcount=stepcount,
            optargaddr=optargaddr,
            optargstate=optargstate,
            patched_globals=patched_globals,
            environmentptr_address=environmentptr_address)

    if support:
        importedmodule = importlib.import_module(support)
        print('\nCustom Import: ' + importedmodule.__name__)
        for d in dir(importedmodule):
            print("Module: " + d)
            if importedmodule.__name__.endswith(d):
                print("found module: " + d)
                simsupport = getattr(importedmodule, d)(
                    stepcount=stepcount,
                    optargaddr=optargaddr,
                    optargstate=optargstate,
                    patched_globals=patched_globals,
                    environmentptr_address=environmentptr_address)
                break
        else:
            simsupport = default_simsupport()
    else:
        simsupport = default_simsupport()

    programcounter = MIPSimProgramCounter(
        SSV.mk_global_address(int(faddr, 16), xname))

    initializer = MIPSimInitializer(mainargs)

    simstate = SimulationState(
        faddr,
        mainmodule,
        programcounter,
        siminitializer=initializer,
        dynlibs=dynlibs,
        simsupport=simsupport,
        stubs=stubs,
        bigendian=bigendian)
    currentinstr = asm.instructions[faddr]
    blocktrace: List[Tuple[str, str]] = []
    for i in range(0, simsupport.stepcount):
        try:
            action = currentinstr.simulate(simstate)
            simstate.trace.add(
                str(i).rjust(5) + "  " + str(currentinstr).ljust(48) + str(action))
            simstate.trace.include_delayed()
            if action == "return":
                print("=" * 80)
                print("Simulation ended normally: returning from starting function")
                print("=" * 80)
                print("\nSimulation trace:")
                print("-" * 80)
                print(str(simstate.trace))
                print("\nSimulation state:")
                print("-" * 80)
                print(str(simstate))
                exit(0)

        except SU.CHBSimCallTargetUnknownError as e:
            simstate.trace.add(
                str(i).rjust(5)
                + "**"
                + str(currentinstr).ljust(48)
                + str(e.calltgt))
            pc = simstate.programcounter
            if pc.is_global_address:
                addr = pc.to_hex()
                if addr in asm.instructions:
                    currentinstr = asm.instructions[addr]

        except SU.CHBSimSystemCallException as e:
            syscall = SC.get_mips_linux_syscall(e.syscallindex)
            if syscall in simstate.stubs:
                stub = cast(MIPSimStub, simstate.stubs[syscall])

                # in MIPS register $a3 will be set to 0 or 1 to indicate success
                # ref: https://www.linux-mips.org/wiki/Syscall
                simstate.set_register(e.iaddr, "a3", SV.simZero)

                msg = stub.simulate(e.iaddr, simstate)
                simstate.trace.add(
                    " ".ljust(15) + "syscall:" + syscall + ": " + msg)
                simstate.increment_programcounter()
            else:
                print(str(simstate.trace))
                print(str(simstate))
                print("No stub for syscall: " + syscall)
                exit(1)

        except SU.CHBSimBranchUnknownError as e:
            simstate.trace.add(
                str(i).rjust(5)
                + "**"
                + str(currentinstr).ljust(48)
                + str(e.truetgt)
                + " ("
                + e.msg
                + ")")
            if simstate.simsupport.branch_decision(e.iaddr, simstate):
                simstate.simprogramcounter.set_delayed_programcounter(e.truetgt)
            else:
                simstate.simprogramcounter.set_delayed_programcounter(e.falsetgt)

        except SU.CHBSymbolicExpression as e:
            print(
                "Symbolic expression: "
                + str(e)
                + "; "
                + str(currentinstr).ljust(48))
            print("=" * 80)
            print("")
            print(str(simstate.trace))
            print(str(simstate))
            exit(1)

        except SU.CHBSimExitException as e:
            print("=" * 80)
            print(
                "System exit at address "
                + e.iaddr
                + " with exit value "
                + e.exitvalue)
            print("=" * 80)
            print("\n")
            print(str(simstate.trace))
            print(str(simstate))
            exit(1)

        except SU.CHBSimError as e:
            print("*" * 80)
            print("Error: " + str(e))
            print("*" * 80)
            print("\nSimulation trace")
            print("-" * 80)
            print(str(simstate.trace))
            print("\nSimulation state")
            print("-" * 80)
            print(str(simstate))

            exit(1)

        except Exception as e:
            print("*" * 80)
            print("Exception: " + str(e))
            print("Current instruction: " + str(currentinstr))
            print("*" * 80)
            print("")
            print(str(simstate.trace))
            print(str(simstate))
            exit(1)

        pc = simstate.programcounter
        addr = pc.to_hex()

        try:
            if pc.modulename == xname:
                if addr in asm.instructions:
                    currentinstr = asm.instructions[addr]
                else:
                    raise UF.CHBError(
                        "No instruction found at " + addr + " in " + xname)
            else:
                libasm = dynasms[pc.modulename]
                if addr in libasm.instructions:
                    currentinstr = libasm.instructions[addr]
                else:
                    raise UF.CHBError(
                        "No instruction found at " + addr + " in " + pc.modulename)
        except UF.CHBError as e:
            print("*" * 80)
            print("Exception in fetching next instruction: " + str(e))
            print("*" * 80)
            print("")
            print(str(simstate.trace))
            print(str(simstate))
            exit(1)

    print("\n\nSimulation trace")
    print(str(simstate.trace))

    with open("simstackmemory.json", "w") as fp:
        json.dump(simstate.stackmem.jsonval(), fp, indent=3)

    print("\n\nSimulation state")
    print("=" * 80)
    print(str(simstate))
    exit(0)
    def sharedmem_shmat(self, iaddr: str, simstate: "SimulationState",
                        shmid: int, shmaddr: SSV.SimGlobalAddress,
                        shmflg: int) -> SSV.SimGlobalAddress:
        """void *shmat(int shmid, const void *shmaddr, int shmflg);"""

        return SSV.mk_undefined_global_address("shared:" + str(shmid))
Beispiel #20
0
 def initialize(self, iaddr: str):
     addr = SSV.mk_global_address(0, "shared")
     for i in range(0, self.buffersize):
         SimMemory.set(self, iaddr, addr.add_offset(i), SV.simZerobyte)
Beispiel #21
0
 def resolve_literal_address(self, iaddr: str,
                             addrvalue: int) -> SSV.SimGlobalAddress:
     if self.module.has_address(addrvalue):
         return SSV.mk_global_address(addrvalue, modulename=self.modulename)
     else:
         return SSV.mk_undefined_global_address(self.modulename)
 def simulate(self, iaddr: str, simstate: "SimulationState") -> str:
     tgt = SSV.mk_global_address(self.target.absolute_address_value,
                                 modulename=simstate.modulename)
     simstate.increment_programcounter()
     simstate.simprogramcounter.set_delayed_programcounter(tgt)
     return "goto " + str(tgt)