はじめに
CTFでreversingをしばらく休んでいた後久しぶりにangrを使おうと思ったら……どうやって書くか忘れていました!
angrをスッと出せるように自分用メモです
参考
公式のサンプル
分かりやすいように少し改変
import angr
project = angr.Project("./chall", auto_load_libs=False)
@project.hook(0x400844) # 目標
def print_flag(state):
print("FLAG SHOULD BE:", state.posix.dumps(0))
project.terminate_execution()
project.execute()
ちゃんと書く
Ghidraで見て,"Correct!" "Incorrect."とでも表示されるような場合.
import angr
proj = angr.Project("chall", auto_load_libs=False)
print("ARCH", proj.arch)
print("EntryPoint", proj.entry)
print("FileName", proj.filename)
state = proj.factory.entry_state()
# state = proj.factory.entry_state(args=["./chall", argv])
simgr = proj.factory.simgr(state)
simgr.active
print(proj.loader)
print(proj.loader.min_addr)
simgr.explore(find=(0x400000 + 0x1234), avoid=(0x400000 + 0x1256))
simgr.found[0].posix.dumps(0)
avoidにはリストを指定することも可能
細かい指定など
コマンドライン引数で指定
コマンドライン引数でFLAGを入力するような場合,BVSで入力ビット数を指定した変数を用意し,argsに追加する.
import claripy
argv1 = claripy.BVS("argv1", input_size * 8)
state = proj.factory.entry_state(args=["./chall", argv1], add_options={angr.options.LAZY_SOLVES})
文字列を制限
add_constraintsで条件を追加できる.
.chop(8)
は1バイトずつ,の意.
# not null
for byte in argv1.chop(8):
state.add_constraints(byte != '\x00')
# format is FLAG{...}
state.add_constraints(argv1.chop(8)[0] == 'F')
state.add_constraints(argv1.chop(8)[1] == 'L')
state.add_constraints(argv1.chop(8)[2] == 'A')
state.add_constraints(argv1.chop(8)[3] == 'G')
state.add_constraints(argv1.chop(8)[4] == '{')
標準入力
flag = claripy.BVS('flag', flag_size*8)
state = proj.factory.blank_state(addr=START, stdin=flag)
手動でメモリに変数を設定
state.memory.store(address, state.solver.BVV("ans", 32*8))
さいご
ここのコード見て勉強すれば大体のangrの使い方が分かります