Mas0n
to be reverse engineer🐧
翻车鱼

Angr_CTF学习笔记

最近做了一遍angr_CTF的例题,收获还是挺大的,先看目录下的PPT,了解符号执行的原理和过程

而后可以使用angr解决例题,学会如何使用angr

我并不是刚刚知道有angr,之所以拖到现在学习,是我一直想不通:

符号执行在什么情况下适用?

这里,我写一些我个人的看法与见解,供同样有这个问题的师傅参考

首先是文件大小,文件越大,符号执行越复杂,分支越多。当然,文件小,不代表分支少。

如果分支太多,且约束条件太少,那么angr可能并不适用。

加粗字体为判断条件

Introduction – angr Documentation

参考文档

由于angr版本迭代,在练习过程中,一些API发生了更改,下面是一些纠正后的解题脚本

00_angr_find

import angr
import sys

# ! ELF 符号执行的二进制文件
elfPath = "/home/kali/Desktop/angr_ctf-master/dist/00_angr_find"
# ? 创建一个Angr工程,用于加载ELF
pjt = angr.Project(elfPath)
# * 指定angr入口地址 
initState = pjt.factory.entry_state()
# ! 创建模拟管理器
simulation = pjt.factory.simgr(initState)
# ? 指定正确路径地址
simulation.explore(find=0x08048678, avoid=0x08048666)
# * 判断是否寻找到
if simulation.found:
    relState = simulation.found[0]
    print("Solved: ", relState.posix.dumps(sys.stdin.fileno()))
else:
    print("no solve result")

01_angr_avoid

import angr
import sys
# ! ELF 符号执行的二进制文件
path = "/home/kali/Desktop/angr_ctf-master/dist/01_angr_avoid"
# ? 创建一个Angr工程,用于加载ELF
project = angr.Project(path)
# * 指定angr入口状态 
state = project.factory.entry_state()
# ! 创建模拟管理器
simulation = project.factory.simgr(state)
# ? 指定正确路径地址
simulation.explore(find=0x080485E0, avoid=0x080485A8)
# * 判断是否寻找到
if simulation.found:
    relState = simulation.found[0]
    print("Solved: ", relState.posix.dumps(sys.stdin.fileno()))
else:
    print("no found")

02_angr_find_condition

import angr
import sys
path = "/home/kali/Desktop/angr_ctf-master/dist/02_angr_find_condition"

project = angr.Project(path)
entryState = project.factory.entry_state()
simulation = project.factory.simgr(entryState)

# ! explore 所有state,dump出所有stdout缓冲区的value (格式化输出),判断是否存在字段,响应~
def findfunc(state:angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def avoidfunc(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

simulation.explore(find=findfunc, avoid=avoidfunc)

if simulation.found:
    relstate = simulation.found[0]
    print(relstate.posix.dumps(sys.stdin.fileno()))
else:
    print("not found")

03_angr_symbolic_registers

import angr
import sys
path = "/home/kali/Desktop/angr_ctf-master/dist/02_angr_find_condition"

project = angr.Project(path)
entryState = project.factory.entry_state()
simulation = project.factory.simgr(entryState)

# ! explore 所有state,dump出所有stdout缓冲区的value (格式化输出),判断是否存在字段,响应~
def findfunc(state:angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def avoidfunc(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

simulation.explore(find=findfunc, avoid=avoidfunc)

if simulation.found:
    relstate = simulation.found[0]
    print(relstate.posix.dumps(sys.stdin.fileno()))
else:
    print("not found")

04_angr_symbolic_stack

import angr
import sys
import claripy

path = "/home/kali/Desktop/angr_ctf-master/dist/04_angr_symbolic_stack"

project = angr.Project(path)

blankState = project.factory.blank_state(addr=0x08048697)
# ! 创建符号变量 arg1 arg2
arg1 = claripy.BVS("arg1", 32)
arg2 = claripy.BVS("arg2", 32)
# ! 设置ebp为当前esp (由于跳过了scanf函数的缘故,需要模拟前面执行: push ebp esp)
blankState.regs.ebp = blankState.regs.esp
# ! 入栈的都是地址~ 8个字节
blankState.regs.esp -= 8
# ! 入栈顺序~
blankState.stack_push(arg1)
blankState.stack_push(arg2)

simulation = project.factory.simgr(blankState)
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

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
    relState = simulation.found[0]
    value1 = relState.solver.eval(arg1)
    value2 = relState.solver.eval(arg2)
    print("solved: ", "%u" % value1, "%u" % value2)
else:
    print("not found")

05_angr_symbolic_memory

import claripy
import angr 
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/05_angr_symbolic_memory"
project = angr.Project(path)

state = project.factory.blank_state(addr=0x08048601)
# angr.SimState.memory.store()
# ! 8 (bytes) * 8 (bits)
input1 = claripy.BVS("input1", 64)
input2 = claripy.BVS("input2", 64)
input3 = claripy.BVS("input3", 64)
input4 = claripy.BVS("input4", 64)
state.memory.store(0x0A1BA1C0, input1)
state.memory.store(0x0A1BA1C8, input2)
state.memory.store(0x0A1BA1D0, input3)
state.memory.store(0x0A1BA1D8, input4)

simulation = project.factory.simgr(state)

def is_successful(state: angr.SimState):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return b'Good Job.' in stdout_output

def should_abort(state: angr.SimState):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return b'Try again.' in stdout_output

simulation.explore(find=is_successful, avoid=should_abort)

if simulation.found:
    relState = simulation.found[0]
    value1 = relState.solver.eval(input1, cast_to=bytes).decode('utf-8')
    value2 = relState.solver.eval(input2, cast_to=bytes).decode('utf-8')
    value3 = relState.solver.eval(input3, cast_to=bytes).decode('utf-8')
    value4 = relState.solver.eval(input4, cast_to=bytes).decode('utf-8')
    print("solved: ", value1, value2, value3, value4)
else:
    print("not found")

06_angr_symbolic_dynamic_memory

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/06_angr_symbolic_dynamic_memory"

project = angr.Project(path)
state = project.factory.blank_state(addr=0x08048699)

arg1 = claripy.BVS("arg1", 64)
arg2 = claripy.BVS("arg2", 64)

randAdrr1 = state.regs.esp-0x100
randAdrr2 = state.regs.esp-0x188

state.memory.store(0x0ABCC8A4, randAdrr1, endness=project.arch.memory_endness)
state.memory.store(0x0ABCC8AC, randAdrr2, endness=project.arch.memory_endness)
state.memory.store(randAdrr1, arg1)
state.memory.store(randAdrr2, arg2)

simulation = project.factory.simgr(state)

def isSuccessful(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def isAvoid(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

simulation.explore(find=isSuccessful, avoid=isAvoid)

if simulation.found:
    relState = simulation.found[0]
    value1 = relState.solver.eval(arg1, cast_to=bytes).decode('utf-8')
    value2 = relState.solver.eval(arg2, cast_to=bytes).decode('utf-8')
    print("solved: ", value1, value2)
else:
    print("not found")

07_angr_symbolic_file

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/07_angr_symbolic_file"
project = angr.Project(path)
# ! 此题多解 可以使用simSymbolcMemory模拟文件系统

def isSuccessful(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def isAvoid(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

# ! 方案1
# state = project.factory.blank_state(addr=0x0804893C)
# arg1 = claripy.BVS("arg1", 64)
# state.memory.store(0x0804A0A0, arg1)
# ! 方案2
state = project.factory.blank_state(addr=0x080488ED)
arg1 = claripy.BVS("arg1", 64)
filename = "OJKSQYDP.txt"
file = angr.SimFile(filename, content=arg1,size=40*8)
file.set_state(state)
state.fs.insert(filename, file)
assert state.fs.get(filename) is file

# * go
simulation = project.factory.simgr(state)
simulation.explore(find=isSuccessful, avoid=isAvoid)

if simulation.found:
    relState = simulation.found[0]
    value1 = relState.solver.eval(arg1, cast_to=bytes).decode('utf-8') 
    print("solved: ", value1)
else:
    print("not found")

08_angr_constraints

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/08_angr_constraints"
project = angr.Project(path)

state = project.factory.blank_state(addr=0x08048625)

arg = claripy.BVS("arg", 16*8)

state.memory.store(0x0804A050, arg)

simulation = project.factory.simgr(state)

simulation.explore(find=0x08048673)
if simulation.found:
    relState = simulation.found[0]
    # ! 添加约束条件 简化规则,不然复杂度太大 
    bitvector = relState.memory.load(0x0804A050, 16)
    key = claripy.BVV("AUPDNNPROEZRJWKB".encode("utf-8"), 16*8)
    relState.add_constraints(bitvector == key)
    arg = relState.solver.eval(arg, cast_to=bytes).decode('utf-8')
    print("solved: ", arg)
else:
    print("not found")

09_angr_hooks

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/08_angr_constraints"
project = angr.Project(path)

state = project.factory.blank_state(addr=0x08048625)

arg = claripy.BVS("arg", 16*8)

state.memory.store(0x0804A050, arg)

simulation = project.factory.simgr(state)

simulation.explore(find=0x08048673)
if simulation.found:
    relState = simulation.found[0]
    # ! 添加约束条件 简化规则,不然复杂度太大 
    bitvector = relState.memory.load(0x0804A050, 16)
    key = claripy.BVV("AUPDNNPROEZRJWKB".encode("utf-8"), 16*8)
    relState.add_constraints(bitvector == key)
    arg = relState.solver.eval(arg, cast_to=bytes).decode('utf-8')
    print("solved: ", arg)
else:
    print("not found")

10_angr_simprocedures

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/10_angr_simprocedures"
project = angr.Project(path)

class replaceHook(angr.SimProcedure):
    def run(self, a1: int, a2: int):
        stateVector = self.state.memory.load(a1, 16)
        equalsVector = claripy.BVV("ORSDDWXHZURJRBDH".encode('utf-8'), size=16*8)
        return claripy.If(equalsVector == stateVector, claripy.BVV(1, 32), claripy.BVV(0, 32))

project.hook_symbol("check_equals_ORSDDWXHZURJRBDH", replaceHook())

def isSuccessful(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def isAvoid(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

state = project.factory.entry_state()
simulation = project.factory.simgr(state)

simulation.explore(find=isSuccessful, avoid=isAvoid)

if simulation.found:
    relState = simulation.found[0]
    value = relState.posix.dumps(sys.stdin.fileno()).decode('utf-8')
    print("solved: ", value)
else:
    print("not found")

11_angr_sim_scanf

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/11_angr_sim_scanf"
project = angr.Project(path)

state = project.factory.entry_state()

# ! SimProcedure 替代 scanf, 这里不能使用blank_state指定入口状态
class replaceHook(angr.SimProcedure):
    def run(self, format, arg1, arg2):
        # ! unsigned int 8 bits * 4 bytes
        param1 = claripy.BVS("arg1", 32)
        param2 = claripy.BVS("arg2", 32)
        self.state.memory.store(arg1, param1, endness=project.arch.memory_endness)
        self.state.memory.store(arg2, param2, endness=project.arch.memory_endness)

        self.state.globals["params"] = (param1, param2)

project.hook_symbol("__isoc99_scanf", replaceHook())

simulation = project.factory.simgr(state)

def isSuccessful(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def isAvoid(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

simulation.explore(find=isSuccessful, avoid=isAvoid)
if simulation.found:
    relState = simulation.found[0]
    value1 = relState.solver.eval(relState.globals["params"][0])
    value2 = relState.solver.eval(relState.globals["params"][1])
    print("solved: ", value1, value2)
else:
    print("not found")

12_angr_veritesting

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/12_angr_veritesting"
project = angr.Project(path)

state = project.factory.entry_state()

simulation = project.factory.simgr(state, veritesting=True)

def isSuccessful(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def isAvoid(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

simulation.explore(find=isSuccessful, avoid=isAvoid)
if simulation.found:
    relState = simulation.found[0]
    value1 = relState.posix.dumps(sys.stdin.fileno()).decode('utf-8')
    print("solved: ", value1)
else:
    print("not found")

13_angr_static_binary

import angr
import claripy
import sys

path = "/home/kali/Desktop/angr_ctf-master/dist/13_angr_static_binary"
project = angr.Project(path)

state = project.factory.entry_state()
# ? https://github.com/angr/angr/tree/master/angr/procedures/libc
project.hook(0x0804ED40, angr.SIM_PROCEDURES['libc']['printf']())
project.hook(0x0804ED80, angr.SIM_PROCEDURES['libc']['scanf']())
project.hook(0x0804F350, angr.SIM_PROCEDURES['libc']['puts']())
project.hook(0x08048D10, angr.SIM_PROCEDURES["glibc"]["__libc_start_main"]())
project.hook(0x08048280, angr.SIM_PROCEDURES["libc"]["strcmp"]())

simulation = project.factory.simgr(state)

def isSuccessful(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Good Job." in value

def isAvoid(state: angr.SimState):
    value = state.posix.dumps(sys.stdout.fileno())
    return b"Try again." in value

simulation.explore(find=isSuccessful, avoid=isAvoid)
if simulation.found:
    relState = simulation.found[0]
    value1 = relState.posix.dumps(sys.stdin.fileno()).decode('utf-8')
    print("solved: ", value1)
else:
    print("not found")

14_angr_shared_library

import angr
import claripy

# ! 载入动态链接库 
path = "/home/kali/Desktop/angr_ctf-master/dist/lib14_angr_shared_library.so"
# ! 随机基址
baseAddr = 0x4000000
project = angr.Project(path, load_options= {
    "main_opts": {
        "base_addr": baseAddr
    },
})
# ! 随机地址 置参数(符号向量)
strPointer = claripy.BVV(0x3000000, size=8*4)
arg = claripy.BVS("arg", size=8*8)
# ! 调用函数
state = project.factory.call_state(baseAddr+0x000006D7, strPointer, claripy.BVV(8, 32))
state.memory.store(strPointer, arg)

simulation = project.factory.simgr(state)
# ! 到达函数结尾 
simulation.explore(find=baseAddr+0x783)
if simulation.found:
    relState = simulation.found[0]
    # ! 添加约束条件 返回值 != 0
    relState.add_constraints(relState.regs.eax != 0)
    value1 = relState.solver.eval(arg, cast_to=bytes).decode('utf-8')
    print("solved: ", value1)
else:
    print("not found")

本文链接:https://blog.shi1011.cn/ctf/1520
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可

Mas0n

文章作者

发表回复

textsms
account_circle
email

翻车鱼

Angr_CTF学习笔记
最近做了一遍angr_CTF的例题,收获还是挺大的,先看目录下的PPT,了解符号执行的原理和过程 而后可以使用angr解决例题,学会如何使用angr 我并不是刚刚知道有angr,之所以拖到…
扫描二维码继续阅读
2021-07-29