import angr
import simuvex
import binascii
angr.path_group.l.setLevel('ERROR') # Can set to 'DEBUG' for more verbose output
stdin1 = None
def printf_hook(state):
# print 'printf' # Uncomment this if you want to see if/when this gets called.
state.regs.eax = 0 # 0 actually means 0 characters were printed, but the value isn't checked, so...
def scanf_hook(state):
# print 'scanf' # Uncomment this if you want to see if/when this gets called.
# print hex(state.se.any_int(state.regs.esp) + 0x4) # Printing the address of the arg on the stack...
# Store a "pointer" to the symbolic string on the stack,
# in the location of the 'target' variable for the real scanf.
# i.e. if the code was `scanf("%s", &str)`, we're putting the `stdin`
# symbolic string on the stack where &str would have been.
state.memory.store(state.se.any_int(state.regs.esp) + 4, stdin1)
p = angr.Project('medium.exe', load_options={'auto_load_libs':False})
# Hooks for calls to printf and scanf.
# If you don't hook these, Angr gets
# unhappy -- so, better to avoid letting
# it branch into these symbolically by
# hooking.
p.hook(0x4010B7, scanf_hook, length=5)
p.hook(0x4010A6, printf_hook, length=5)
#initial_state = p.factory.blank_state(addr=0x00401090, remove_options={simuvex.s_options.LAZY_SOLVES})
initial_state = p.factory.blank_state(addr=0x00401090) # Will still quickly solve without LAZY_SOLVES disabled.
#initial_state = p.factory.blank_state(addr=0x004010BF, remove_options={simuvex.s_options.LAZY_SOLVES})
#initial_state.regs.esp = 0xF0000000 # Don't actually need to set these, but can be useful for troubleshooting
#initial_state.regs.ebp = 0xE0000000
# Create a symbolic string. 8 bits & 50 to make a
# 50-char symbolic string.
stdin1 = initial_state.se.BVS("stdin1", 8 * 50)
initial_path = p.factory.path(initial_state)
path_group = p.factory.path_group(initial_state)
# `find` is the address of `printf("You got it!\n")`
# `avoid` is the address of the instructions immediately
# after the printf branch, which would indicate a wrong password.
path_group.explore(find=(0x401189,), avoid=(0x401196,))
found = path_group.found[0]
#print found.state.regs.ip # Print EIP.
print found.state.se.any_str(stdin1)