Skip to content

Commit

Permalink
deprecate rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyle-Kyle committed Jan 30, 2024
1 parent 8ce4b72 commit 4e5d478
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 26 deletions.
11 changes: 5 additions & 6 deletions angrop/chain_builder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ChainBuilder:
This class provides functions to generate common ropchains based on existing gadgets.
"""

def __init__(self, project, gadgets, duplicates, reg_list, base_pointer, badbytes, roparg_filler, rebase=True):
def __init__(self, project, gadgets, duplicates, reg_list, base_pointer, badbytes, roparg_filler):
"""
Initializes the chain builder.
Expand All @@ -43,7 +43,6 @@ def __init__(self, project, gadgets, duplicates, reg_list, base_pointer, badbyte
self._base_pointer = base_pointer
self.badbytes = badbytes
self._roparg_filler = roparg_filler
self._rebase = rebase

self._syscall_instruction = None
if self.project.arch.linux_name == "x86_64":
Expand All @@ -67,9 +66,9 @@ def __init__(self, project, gadgets, duplicates, reg_list, base_pointer, badbyte
self._filtered_reg_gadgets = None

self._reg_setter = RegSetter(project, gadgets, reg_list=reg_list, badbytes=badbytes,
rebase=self._rebase, filler=self._roparg_filler)
filler=self._roparg_filler)
self._mem_writer = MemWriter(project, self._reg_setter, base_pointer, gadgets, badbytes=badbytes,
rebase=self._rebase, filler=self._roparg_filler)
filler=self._roparg_filler)

def _contain_badbyte(self, ptr):
"""
Expand Down Expand Up @@ -148,7 +147,7 @@ def _func_call(self, func_gadget, cc, args, extra_regs=None, modifiable_memory_r
# invoke the function
chain.add_gadget(func_gadget)
for _ in range(func_gadget.stack_change//arch_bytes-1):
chain.add_value(self._get_fill_val(), needs_rebase=False)
chain.add_value(self._get_fill_val())

# we are done here if there is no stack arguments
if not stack_arguments:
Expand Down Expand Up @@ -184,7 +183,7 @@ def _func_call(self, func_gadget, cc, args, extra_regs=None, modifiable_memory_r
chain.add_gadget(stack_cleaner)
stack_arguments += [self._get_fill_val()]*(stack_cleaner.stack_change//arch_bytes - len(stack_arguments)-1)
for arg in stack_arguments:
chain.add_value(arg, needs_rebase=False)
chain.add_value(arg)

return chain

Expand Down
7 changes: 3 additions & 4 deletions angrop/chain_builder/mem_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ class MemWriter:
using various techniques
TODO: add a testcase for add_mem
"""
def __init__(self, project, reg_setter, base_pointer, gadgets, badbytes=None, rebase=False, filler=None):
def __init__(self, project, reg_setter, base_pointer, gadgets, badbytes=None, filler=None):
self.project = project
self.badbytes = badbytes

self._reg_setter = reg_setter
self._base_pointer = base_pointer
self._rebase = rebase
self._mem_write_gadgets = self._get_all_mem_write_gadgets(gadgets)
self._mem_change_gadgets = self._get_all_mem_change_gadgets(gadgets)
self._test_symbolic_state = rop_utils.make_symbolic_state(self.project, self._reg_setter._reg_set)
Expand Down Expand Up @@ -399,7 +398,7 @@ def _write_to_mem_with_gadget(self, gadget, addr_val, data, use_partial_controll

bytes_per_pop = self.project.arch.bytes
for _ in range(gadget.stack_change // bytes_per_pop - 1):
chain.add_value(self._get_fill_val(), needs_rebase=False)
chain.add_value(self._get_fill_val())

# verify the write actually works
state = chain.exec()
Expand Down Expand Up @@ -478,7 +477,7 @@ def _change_mem_with_gadget(self, gadget, addr, data_size, final_val=None, diffe

bytes_per_pop = self.project.arch.bytes
for _ in range(gadget.stack_change // bytes_per_pop - 1):
chain.add_value(self._get_fill_val(), needs_rebase=False)
chain.add_value(self._get_fill_val())
return chain

def _get_fill_val(self):
Expand Down
5 changes: 2 additions & 3 deletions angrop/chain_builder/reg_setter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ class RegSetter:
"""
TODO: get rid of Salls's code
"""
def __init__(self, project, gadgets, reg_list=None, badbytes=None, rebase=False, filler=None):
def __init__(self, project, gadgets, reg_list=None, badbytes=None, filler=None):
self.project = project
self._reg_set = set(reg_list)
self._badbytes = badbytes
self._rebase = rebase

self._reg_setting_gadgets = self._filter_gadgets(gadgets)
self._roparg_filler = filler
Expand Down Expand Up @@ -355,7 +354,7 @@ def _build_reg_setting_chain(self, gadgets, modifiable_memory_range, register_di
continue
var = var_dict[var_name]
break
chain.add_value(var, needs_rebase=False)
chain.add_value(var)

if len(gadgets) > 0:
raise RopException("Didnt find all gadget addresses, something must've broke")
Expand Down
10 changes: 5 additions & 5 deletions angrop/rop.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,14 @@ class ROP(Analysis):
"""

def __init__(self, only_check_near_rets=True, max_block_size=None, max_sym_mem_access=None,
fast_mode=None, rebase=True, is_thumb=False, kernel_mode=False):
fast_mode=None, rebase=None, is_thumb=False, kernel_mode=False):
"""
Initializes the rop gadget finder
:param only_check_near_rets: If true we skip blocks that are not near rets
:param max_block_size: limits the size of blocks considered, longer blocks are less likely to be good rop
gadgets so we limit the size we consider
:param fast_mode: if set to True sets options to run fast, if set to False sets options to find more gadgets
if set to None makes a decision based on the size of the binary
:param rebase: if set to True, angrop will try to rebase the gadgets with its best effort
if set to False, angrop will use the memory mapping in angr in the ropchain
:param is_thumb: execute ROP chain in thumb mode. Only makes difference on ARM architecture.
angrop does not switch mode within a rop chain
:return:
Expand All @@ -72,7 +70,6 @@ def __init__(self, only_check_near_rets=True, max_block_size=None, max_sym_mem_a
self.arch = get_arch(self.project, kernel_mode=kernel_mode)
self.kernel_mode = kernel_mode
self._only_check_near_rets = only_check_near_rets
self._rebase = rebase

# override parameters
if max_block_size:
Expand Down Expand Up @@ -103,6 +100,9 @@ def __init__(self, only_check_near_rets=True, max_block_size=None, max_sym_mem_a
# chain builder
self._chain_builder = None

if rebase is not None:
l.warning("rebase is deprecated in angrop!")

# silence annoying loggers
logging.getLogger('angr.engines.vex.ccall').setLevel(logging.CRITICAL)
logging.getLogger('angr.engines.vex.expressions.ccall').setLevel(logging.CRITICAL)
Expand Down Expand Up @@ -283,7 +283,7 @@ def chain_builder(self):
l.warning("check your badbytes and make sure find_gadgets() or load_gadgets() was called.")
self._chain_builder = chain_builder.ChainBuilder(self.project, self.gadgets, self._duplicates,
self.arch.reg_list, self.arch.base_pointer, self.badbytes,
self.roparg_filler, rebase=self._rebase)
self.roparg_filler)
return self._chain_builder

def _block_has_ip_relative(self, addr, bl):
Expand Down
11 changes: 5 additions & 6 deletions angrop/rop_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class RopChain:
"""
def __init__(self, project, rop, state=None, badbytes=None):
"""
rebase=False will force everything to use the addresses in angr
"""
self._p = project
self._pie = self._p.loader.main_object.pic
Expand All @@ -35,7 +34,7 @@ def __add__(self, other):
result.payload_len = self.payload_len + other.payload_len
return result

def add_value(self, value, needs_rebase=False):
def add_value(self, value):
if type(value) is not RopValue:
value = RopValue(value, self._p)
value.rebase_analysis(chain=self)
Expand Down Expand Up @@ -104,8 +103,8 @@ def payload_str(self, constraints=None, base_addr=None):
base_addr = self._p.loader.main_object.mapped_base
test_state = self._blank_state.copy()
concrete_vals = self._concretize_chain_values(constraints)
for value, needs_rebase in reversed(concrete_vals):
if needs_rebase:
for value, rebased in reversed(concrete_vals):
if rebased:
test_state.stack_push(value - self._p.loader.main_object.mapped_base + base_addr)
else:
test_state.stack_push(value)
Expand Down Expand Up @@ -145,7 +144,7 @@ def payload_code(self, constraints=None, print_instructions=True):

gadget_dict = {g.addr:g for g in self._gadgets}
concrete_vals = self._concretize_chain_values(constraints)
for value, needs_rebase in concrete_vals:
for value, rebased in concrete_vals:

instruction_code = ""
if print_instructions:
Expand All @@ -155,7 +154,7 @@ def payload_code(self, constraints=None, print_instructions=True):
if asmstring != "":
instruction_code = "\t# " + asmstring

if needs_rebase:
if rebased:
value -= self._p.loader.main_object.mapped_base
payload += "chain += " + pack_rebase % value + instruction_code
else:
Expand Down
14 changes: 14 additions & 0 deletions tests/test_chainbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ def test_ropvalue():
chain = rop.write_to_mem(value, b"/bin/sh\x00")
assert sum(not x._rebase for x in chain._values) == 2 # 2 values

#def test_reg_move():
# cache_path = os.path.join(CACHE_DIR, "bronze_ropchain")
# proj = angr.Project(os.path.join(BIN_DIR, "tests", "i386", "bronze_ropchain"), auto_load_libs=False)
# rop = proj.analyses.ROP()
#
# if os.path.exists(cache_path):
# rop.load_gadgets(cache_path)
# else:
# rop.find_gadgets()
# rop.save_gadgets(cache_path)
#
# chain = rop.set_regs(eax="ecx")
# import IPython; IPython.embed()

def run_all():
functions = globals()
all_functions = {x:y for x, y in functions.items() if x.startswith('test_')}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_gadgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
def get_rop(path):
cache_path = os.path.join(CACHE_DIR, os.path.basename(path))
proj = angr.Project(path, auto_load_libs=False)
rop = proj.analyses.ROP(rebase=False)
rop = proj.analyses.ROP()
if os.path.exists(cache_path):
rop.load_gadgets(cache_path)
else:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_ropchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_chain_exec():
# build a ROP chain using the gadget
chain = angrop.rop_chain.RopChain(proj, rop.chain_builder)
chain.add_gadget(gadget)
chain.add_value(0x41414141, needs_rebase=False)
chain.add_value(0x41414141)

# make sure the execution succeeds
state = chain.exec()
Expand Down

0 comments on commit 4e5d478

Please sign in to comment.