10 Angr SimProcedures¶
This is going to be a short one. The only thing new with this one is the introduction of SimProcedures which takes a lot of the manual work out of hooking a function. So instead of defining the start address and the skip length, then building the stack and registers back up, we simply define a SimProcedures to take care of it for us.
So, with that said, here is the solution.
import angr
import claripy
import sys
import pwn
def main():
path_to_binary = "./10_angr_simprocedures"
project = angr.Project(path_to_binary)
initial_state = project.factory.entry_state(
add_options={
angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS,
},
)
class ReplacementCheckEquals(angr.SimProcedure):
def run(self, to_check, length):
user_input_buffer_address = to_check
user_input_buffer_length = length
user_input_string = self.state.memory.load(
user_input_buffer_address, user_input_buffer_length
)
check_against_string = "ORSDDWXHZURJRBDH".encode()
return claripy.If(
user_input_string == check_against_string,
claripy.BVV(1, 32),
claripy.BVV(0, 32),
)
check_equals_symbol = "check_equals_ORSDDWXHZURJRBDH"
project.hook_symbol(check_equals_symbol, ReplacementCheckEquals())
simulation = project.factory.simgr(initial_state)
simulation.explore(find=is_successful, avoid=should_abort)
if simulation.found:
solution_state = simulation.found[0]
solution = solution_state.posix.dumps(sys.stdin.fileno()).decode()
run_binary(solution, path_to_binary)
else:
raise Exception("Could not find the solution")
def run_binary(solution, path_to_binary):
if type(solution) == str:
solution = bytes(solution, "utf-8")
print(f"[+] Solution found: {solution.decode()}")
print(" [|] Running binary")
elf = pwn.ELF(path_to_binary, checksec=False)
pty = pwn.process.PTY
io = elf.process(stdin=pty, stdout=pty, level="warn")
io.recvuntil(b":")
io.sendline(solution)
output = io.recvline().decode().splitlines()[0].strip()
print(f" [+] Output: {output}")
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return b"Good Job." in stdout_output
def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return b"Try again." in stdout_output
if __name__ == "__main__":
main()