about summary refs log tree commit diff stats
path: root/focaccia
diff options
context:
space:
mode:
Diffstat (limited to 'focaccia')
-rw-r--r--focaccia/arch/x86.py75
-rw-r--r--focaccia/lldb_target.py33
-rw-r--r--focaccia/symbolic.py12
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