Skip to content

Commit

Permalink
Add control flow redirect mechanism for routine hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
cnheitman committed Nov 11, 2024
1 parent 07fd1a5 commit 20e0bca
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 7 deletions.
3 changes: 3 additions & 0 deletions tritondse/process_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ def __init__(self, endianness: Endian = Endian.LITTLE, time_inc_coefficient: flo
# The memory mapping of the program ({vaddr_s : vaddr_e})
self.__program_segments_mapping = {}

# Address to return to from a routine hook.
self.rtn_redirect_addr = None

@property
def threads(self) -> List[ThreadContext]:
"""
Expand Down
8 changes: 7 additions & 1 deletion tritondse/routines.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ def rtn_libc_start_main(se: 'SymbolicExecutor', pstate: 'ProcessState'):
# WARNING: Dirty trick to make sure to jump on main after
# the emulation of that stub
if pstate.architecture == Architecture.AARCH64:
pstate.cpu.x30 = main
pass
elif pstate.architecture == Architecture.ARM32:
pass
elif pstate.architecture in [Architecture.X86_64, Architecture.X86]:
# Push the return value to jump into the main() function
pstate.push_stack_value(main)
Expand Down Expand Up @@ -224,6 +226,10 @@ def rtn_libc_start_main(se: 'SymbolicExecutor', pstate: 'ProcessState'):
pstate.write_argument_value(1 + 1, b_argv)
else:
pstate.write_argument_value(1, b_argv)

# Return to the main function.
pstate.rtn_redirect_addr = main

return None


Expand Down
23 changes: 17 additions & 6 deletions tritondse/symbolic_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from tritondse.thread_context import ThreadContext
from tritondse.exception import AbortExecutionException, SkipInstructionException, StopExplorationException, ProbeException
from tritondse.memory import MemoryAccessViolation, Perm
from tritondse.thread_context import ThreadState
import tritondse.logging

logger = tritondse.logging.get("executor")
Expand Down Expand Up @@ -492,14 +493,24 @@ def _routines_handler(self, instruction: Instruction):
self.pstate.current_thread.count = self.config.thread_scheduling+1
return

if self.pstate.architecture == Architecture.AARCH64:
# If an return address was set, return to that address.
if self.pstate.rtn_redirect_addr != None:
# Get the return address
ret_addr = self.pstate.read_register('x30')
elif self.pstate.architecture in [Architecture.X86, Architecture.X86_64]:
# Get the return address and restore RSP (simulate RET)
ret_addr = self.pstate.pop_stack_value()
ret_addr = self.pstate.rtn_redirect_addr
# Clear rtn_redirect_addr.
self.pstate.rtn_redirect_addr = None
else:
raise Exception("Architecture not supported")
if self.pstate.architecture == Architecture.AARCH64:
# Get the return address.
ret_addr = self.pstate.read_register('x30')
elif self.pstate.architecture == Architecture.ARM32:
# Get the return address.
ret_addr = self.pstate.read_register('r14')
elif self.pstate.architecture in [Architecture.X86, Architecture.X86_64]:
# Get the return address and restore RSP (simulate RET).
ret_addr = self.pstate.pop_stack_value()
else:
raise Exception("Architecture not supported")

# Hijack RIP to skip the call
self.pstate.cpu.program_counter = ret_addr
Expand Down

0 comments on commit 20e0bca

Please sign in to comment.