angr Template
What is it
This template finds the flag character by character automatically. It works if the flag is passed to a series of functions for validation check. For example, the program contains hundreds of functions that check whether the password that the user gives is valid or not.
This template can be used to solve:
Google CTF 2020 "beginner"
BambooFox CTF 2021 "Flag Checker Revenge"
DiceCTF 2021 "babymix"
... and many others
How to Use
Examine the binary manual and guess the flag length. Usually the clue would be the
strlenfunction call or the upper bound of someforloop.Upon success or failure, the binary may execute the
call putsinstruction and prints a string. Find the address ofcall putsfor the successful cases and the address ofcall putsfor failed cases. They should be filled in as thefind_addrandavoid_addrrespectively.Run the script and wait patiently. It usually takes 5+ mins to complete.
Template
Change the lines containing < and >:
#!/usr/bin/env python3
import angr
import claripy
FLAG_LEN = <len>
STDIN_FD = 0
base_addr = 0x100000 # To match addresses to Ghidra
proj = angr.Project("<binary_name>", main_opts={'base_addr': base_addr})
flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(FLAG_LEN)]
flag = claripy.Concat( *flag_chars + [claripy.BVV(b'\n')]) # Add \n for scanf() to accept the input
state = proj.factory.full_init_state(
args=['<bin>'],
add_options=angr.options.unicorn,
stdin=flag,
)
# Add constraints that all characters are printable
for k in flag_chars:
state.solver.add(k >= ord('!'))
state.solver.add(k <= ord('~'))
simgr = proj.factory.simulation_manager(state)
find_addr = <success_address> # The address of "call puts" for SUCCESS
avoid_addr = <failure_address> # The address of "call puts" for FAILURE
simgr.explore(find=find_addr, avoid=avoid_addr)
if (len(simgr.found) > 0):
for found in simgr.found:
print(found.posix.dumps(STDIN_FD))Reference
Last updated
Was this helpful?
