Skip to content

Commit

Permalink
Stub by address, not by function name
Browse files Browse the repository at this point in the history
  • Loading branch information
erdnaxe authored and yhql committed Oct 24, 2023
1 parent 96e7534 commit 02f944c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 11 deletions.
40 changes: 31 additions & 9 deletions rainbow/rainbow.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,24 @@ def hook_prolog(self, name, fn):
"""
if not self.allow_stubs:
raise ValueError("Cannot use stubs, allow_stubs is False.")
if name not in self.functions.keys():
raise IndexError(f"'{name}' could not be found.")

def to_hook(x):
if fn is not None:
fn(x)
return False

self.stubbed_functions[name] = to_hook
if isinstance(name, str):
# Stub all function addresses matching this name
addrs = [a for a, n in self.function_names.items() if n == name]
if not addrs:
raise IndexError(f"'{name}' could not be found.")
for addr in addrs:
self.stubbed_functions[addr] = to_hook
elif isinstance(name, int):
# Name is an address
self.stubbed_functions[name] = to_hook
else:
raise TypeError("name should be function name or address")

def hook_bypass(self, name, fn=None):
"""
Expand All @@ -435,15 +444,24 @@ def hook_bypass(self, name, fn=None):
"""
if not self.allow_stubs:
raise ValueError("Cannot use stubs, allow_stubs is False.")
if name not in self.functions.keys():
raise IndexError(f"'{name}' could not be found.")

def to_hook(x):
if fn is not None:
fn(x)
return True

self.stubbed_functions[name] = to_hook
if isinstance(name, str):
# Stub all function addresses matching this name
addrs = [a for a, n in self.function_names.items() if n == name]
if not addrs:
raise IndexError(f"'{name}' could not be found.")
for addr in addrs:
self.stubbed_functions[addr] = to_hook
elif isinstance(name, int):
# Name is an address
self.stubbed_functions[name] = to_hook
else:
raise TypeError("name should be function name or address")

def remove_hook(self, name):
"""Remove the hook."""
Expand All @@ -463,16 +481,20 @@ def _block_hook(self, _uci, address: int, _size, _):
address+function is redefined in the user's python script and if so,
calls that instead.
"""
# Print function calls
if address in self.function_names and (self.allow_stubs or self.print_config & Print.Functions):
# Handle the function call printing
f = self.function_names[address]
if self.print_config & Print.Functions:
print(f"{color('MAGENTA', f)}(...) @ 0x{address:x}")

# Handle the stubs
if f in self.stubbed_functions:
r = self.stubbed_functions[f](self)
# If stub is enabled and set at this address, run it
if self.allow_stubs:
stub_func = self.stubbed_functions.get(address)
if stub_func is not None:
r = stub_func(self)
if r:
# If stub returns True, then make the function return early
self.return_force()

def _mem_hook(self, uci, access, address, size, value, _):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ def test_remove_hooks():
emu.setup()

emu.hook_bypass("strtol")
assert "strtol" in emu.stubbed_functions
assert 0x202fa0 in emu.stubbed_functions
emu.remove_hooks()
assert "strtol" not in emu.stubbed_functions
assert 0x202fa0 not in emu.stubbed_functions

0 comments on commit 02f944c

Please sign in to comment.