diff options
Diffstat (limited to 'focaccia')
| -rw-r--r-- | focaccia/arch/x86.py | 75 | ||||
| -rw-r--r-- | focaccia/lldb_target.py | 33 | ||||
| -rw-r--r-- | focaccia/symbolic.py | 12 |
3 files changed, 97 insertions, 23 deletions
diff --git a/focaccia/arch/x86.py b/focaccia/arch/x86.py index 95e1a82..ebe74dd 100644 --- a/focaccia/arch/x86.py +++ b/focaccia/arch/x86.py @@ -61,30 +61,65 @@ def decompose_rflags(rflags: int) -> dict[str, int]: """ return { # FLAGS - 'CF': rflags & 0x0001, - # 0x0002 reserved - 'PF': rflags & 0x0004, - # 0x0008 reserved - 'AF': rflags & 0x0010, - # 0x0020 reserved - 'ZF': rflags & 0x0040, - 'SF': rflags & 0x0080, - 'TF': rflags & 0x0100, - 'IF': rflags & 0x0200, - 'DF': rflags & 0x0400, - 'OF': rflags & 0x0800, - 'IOPL': rflags & 0x3000, - 'NT': rflags & 0x4000, + 'CF': (rflags & 0x0001) != 0, + # 0x0002 reserved + 'PF': (rflags & 0x0004) != 0, + # 0x0008 reserved + 'AF': (rflags & 0x0010) != 0, + # 0x0020 reserved + 'ZF': (rflags & 0x0040) != 0, + 'SF': (rflags & 0x0080) != 0, + 'TF': (rflags & 0x0100) != 0, + 'IF': (rflags & 0x0200) != 0, + 'DF': (rflags & 0x0400) != 0, + 'OF': (rflags & 0x0800) != 0, + 'IOPL': (rflags & 0x3000) != 0, + 'NT': (rflags & 0x4000) != 0, # EFLAGS - 'RF': rflags & 0x00010000, - 'VM': rflags & 0x00020000, - 'AC': rflags & 0x00040000, - 'VIF': rflags & 0x00080000, - 'VIP': rflags & 0x00100000, - 'ID': rflags & 0x00200000, + 'RF': (rflags & 0x00010000) != 0, + 'VM': (rflags & 0x00020000) != 0, + 'AC': (rflags & 0x00040000) != 0, + 'VIF': (rflags & 0x00080000) != 0, + 'VIP': (rflags & 0x00100000) != 0, + 'ID': (rflags & 0x00200000) != 0, } +def compose_rflags(rflags: dict[str, int]) -> int: + """Compose separate flags into RFLAGS register's value. + + Uses flag name abbreviation conventions from + `https://en.wikipedia.org/wiki/FLAGS_register`. + + :param rflags: A dictionary mapping Miasm's flag names to their alues. + :return: The RFLAGS register value. + """ + return ( + # FLAGS + (0x0001 if rflags['CF'] else 0) | + # 0x0002 reserved + (0x0004 if rflags['PF'] else 0) | + # 0x0008 reserved + (0x0010 if rflags['AF'] else 0) | + # 0x0020 reserved + (0x0040 if rflags['ZF'] else 0) | + (0x0080 if rflags['SF'] else 0) | + (0x0100 if rflags['TF'] else 0) | + (0x0200 if rflags['IF'] else 0) | + (0x0400 if rflags['DF'] else 0) | + (0x0800 if rflags['OF'] else 0) | + (0x3000 if rflags['IOPL'] else 0) | + (0x4000 if rflags['NT'] else 0) | + + # EFLAGS + (0x00010000 if rflags['RF'] else 0) | + (0x00020000 if rflags['VM'] else 0) | + (0x00040000 if rflags['AC'] else 0) | + (0x00080000 if rflags['VIF'] else 0) | + (0x00100000 if rflags['VIP'] else 0) | + (0x00200000 if rflags['ID'] else 0) + ) + class ArchX86(Arch): def __init__(self): super().__init__(archname, regnames) diff --git a/focaccia/lldb_target.py b/focaccia/lldb_target.py index 444ab36..05ab66d 100644 --- a/focaccia/lldb_target.py +++ b/focaccia/lldb_target.py @@ -26,6 +26,9 @@ class ConcreteRegisterError(Exception): class ConcreteMemoryError(Exception): pass +class ConcreteSectionError(Exception): + pass + class LLDBConcreteTarget: def __init__(self, executable: str, argv: list[str] = []): """Construct an LLDB concrete target. Stop at entry. @@ -74,6 +77,14 @@ class LLDBConcreteTarget: """Step forward by a single instruction.""" thread: lldb.SBThread = self.process.GetThreadAtIndex(0) thread.StepInstruction(False) + + def run_until(self, address: int) -> None: + """Continue execution until the address is arrived, ignores other breakpoints""" + bp = self.target.BreakpointCreateByAddress(address) + while self.read_register("pc") != address: + self.target.run() + self.target.BreakpointDelete(bp.GetID()) + def record_snapshot(self) -> ProgramState: """Record the concrete target's state in a ProgramState object.""" @@ -208,3 +219,25 @@ class LLDBConcreteTarget: command = f'breakpoint delete {addr}' result = lldb.SBCommandReturnObject() self.interpreter.HandleCommand(command, result) + + def get_basic_block(self, addr: int) -> [lldb.SBInstruction]: + """Returns a basic block pointed by addr + a code section is considered a basic block only if + the last instruction is a brach, e.g. JUMP, CALL, RET + """ + block = [] + while not self.target.ReadInstructions(lldb.SBAddress(addr, self.target), 1)[0].is_branch: + block.append(self.target.ReadInstructions(lldb.SBAddress(addr, self.target), 1)[0]) + addr += self.target.ReadInstructions(lldb.SBAddress(addr, self.target), 1)[0].size + block.append(self.target.ReadInstructions(lldb.SBAddress(addr, self.target), 1)[0]) + + return block + + def get_symbol(self, addr: int) -> lldb.SBSymbol: + """Returns the symbol that belongs to the addr""" + for s in self.target.module.symbols: + if (s.GetType() == lldb.eSymbolTypeCode + and s.GetStartAddress().GetLoadAddress(self.target) <= addr + and addr < s.GetEndAddress().GetLoadAddress(self.target)): + return s + raise ConcreteSectionError(f'Error getting the symbol to which address {hex(addr)} belongs to') diff --git a/focaccia/symbolic.py b/focaccia/symbolic.py index 7ab0d84..50108d4 100644 --- a/focaccia/symbolic.py +++ b/focaccia/symbolic.py @@ -195,8 +195,10 @@ class SymbolicTransform: def resolve_register(self, regname: str) -> int | None: accessed_regs.add(regname) return None - def resolve_memory(self, addr: int, size: int): assert(False) - def resolve_location(self, _): assert(False) + def resolve_memory(self, addr: int, size: int): + pass + def resolve_location(self, _): + assert(False) state = ConcreteStateWrapper() for expr in self.changed_regs.values(): @@ -421,7 +423,11 @@ def _run_block(pc: int, conc_state: MiasmConcreteState, ctx: DisassemblyContext) # Execute each instruction in the current basic block and record the # resulting change in program state. for assignblk in irblock: - modified = engine.eval_assignblk(assignblk) + # A clean engine for the single-instruction diff, otherwise + # it concatenates the current instruction to the previous ones in + # the block. + _engine = SymbolicExecutionEngine(ctx.lifter) + modified = _engine.eval_assignblk(assignblk) symb_trace.append((assignblk.instr.offset, modified)) # Run a single instruction |