首页
社区
课程
招聘
[原创]从ANGR-CTF项目入手ANGR和符号执行技术
发表于: 2025-11-27 14:18 1085

[原创]从ANGR-CTF项目入手ANGR和符号执行技术

2025-11-27 14:18
1085

安装angr,部署angr-ctf项目。
先安装angr:

angr用project调用来加载二进制文件

其他的操作可以通过题目来学习

相关接口可参考下面的文章,本文的学习还是从angr-ctf这个项目中去学习。
b27K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5P5W2)9J5k6h3q4D9K9i4W2#2L8W2)9J5k6h3y4G2L8g2)9J5c8X3&6W2N6%4y4Q4x3V1j5$3y4K6p5K6i4K6t1K6N6r3!0U0i4K6u0V1x3e0b7`.

本文前面的几个会介绍的比较详细,后面的因为会技术有重复,所以简略的贴了一下脚本,所以只是angr的入门技术的讲解,深入学习需要在更多的实际程序中去跑。

项目的可执行文件再dist文件夹中,每个程序的目的都是让程序输出good job

可以看到逻辑就是一个输入,然后之后验证的过程。

现在需要用angr来进行分析。

load_options = {'auto_load_libs': False}: 是要求他不要载入其他的依赖文件,可以降低复杂性跟时间。
main_opts = {'base_addr': 0x804850}: 设置 entrypoint,也可以不加

然后设置:

下面需要让angt开始搜索路径

完整脚本:

找到了“JXWVXRKX”

输出的日志中angr.storage.memory*_mixins.default_*filler*_mixin* 这是在说遇到了一个没有初始值的寄存器或地址,angr会在稍后自动创建一个未约束的符号变量来填充,警告提到了三个提示:

暂时这些可以无视,这个00程序的目的就是让我们了解angr的基本调用,以及find参数去寻找指定的地址。

程序用Ida静态分析的时候会发现:

太长了,不能直接查看流程图。这也意味着如果我们直接按照00程序那样去find,会有超级多的路径,另外分析发现有个函数avoid_me被调用了过多次,并注意到这个函数只有一个作用,就是让should_succeed为0,所以这里要使用另一个参数avoid来避开设计这个函数的路径分支。

这样就跑出来了。

02程序跟前两个逻辑基本一致,这里是让我们去动态选择需要的state,也就是用strings参数去找正确和错误的字符串,不再直接输入地址。

程序读取一个输入,然后分别做了三个复杂的变换,之后判定满足条件就能输出。angr 对 scanf 的复杂输入处理的不是很好,但是发现输入之后的三个参数被放在了三个寄存器里面。程序从这三个寄存器中再取值到三个变量里,然后进行三次复杂变换。我们可以直接控制寄存器的值,跳过用户的输入,这样更方便angr去分析。

输入值先被写入栈,然后被变换,最后与常量比较。要找到正确输入,必须让angr追踪这两个栈位置上的符号值。注意之类与03的区别,这里是scnaf把数据读取到栈里面,03是把数据读取到寄存器里,上一道题我们直接跳过了输入函数,因此eax,ebx,edx依次压入栈,所以我们直接修改寄存器的值就行,但是04需要我们去手动布置栈。从ida里面看,一个是[ebp-Ch],一个是[ebp-10h]。我们将符号执行的位置放在0x8048697开始,gdb看一下scanf之后的时候的栈,此时栈中以及被压入了2个4字节的数据,所以想要符号化栈中的这两个数据,我们先要将栈抬高,也就是esp-8,让esp指向目标变量区域的"顶部",然后再将两个符号化的栈值压入栈.

这个与4类似,但是这里是要用指定地址去设置参数,刚刚的04的脚本里面注释掉的那几行就是指定地址传参的形式。

注意这里scanf的是%8s,8字符,一个字符8字节,所以长度是64

前面是栈的符号化,现在是内存的符号化,scanf的两个参数是动态分配地址的,所以之前的方法并不能直接利用了,但是我们可以指定一个地址作为堆地址,堆地址存储在 bss 段的一个地址中,所以给 bss 段的变量一个自定义地址,往自定义地址里写输入位向量。

也就是说选择两个未使用的内存地址作为"伪造"的堆地址,将 buffer0 和 buffer1 中的指针值改为我们的伪造地址,将符号化输入直接存储到伪造地址中,让程序认为输入数据已经在 malloc 分配的内存中。

这个程序是考察文件系统符号化能力。程序从硬编码的文件名中读取密码,而非从标准输入获取。angr 默认不模拟真实文件系统,程序无法打开实际文件。需要将整个文件内容转换为符号变量。程序通过指针访问文件名,需确保地址解析正确。

构造虚拟文件对象,内容用符号变量填充。通过 state.fs.insert() 将虚拟文件挂载到指定路径。将 BSS 段的 file_str 指针指向我们控制的字符串地址。

08程序是约束条件的控制,必须要绕过 check_equals 的 2^16 路径爆炸。直接执行的话会路径爆炸,所以需要进行剪枝、聚焦到有效的解空间。

在创建符号变量的时候,主动添加约束条件,减少路径。(使用 state.solver.add() 主动限制变量范围)

09程序是让我们区写一个hook的函数。通过拦截并替换复杂函数,彻底避免路径爆炸。第一次比较在check函数中按位比较,路径爆炸发生在check函数中,在函数调用点直接替换整个函数逻辑,用一行代码完成判断和返回值设置,不产生任何分支

第一步:让 scanf 真实执行(不 Hook)

关键洞察:无需手动 memory.store()scanf 自己会完成输入符号化。

第二步:Hook check_equals 函数(消除循环)

为什么用 hook_symbol 而非 @hook(addr)

第三步:在 Hook 内部读取 Buffer 并判断

此时 res 的值是什么?

res** 是 16 字节的符号表达式链**,基于 stdin 的符号变量。

第四步:探索到 Good Job 路径

执行流

第五步:求解 stdin 内容

求解器内部逻辑

完整的代码

这个题目要求找出两个无符号整数,使得它们经过scanf读入后,在内存中的字节表示能够匹配一个经过变换的8字节字符串。程序首先在栈上初始化一个字符串"SUQMKQFX",然后对每个字符应用complex_function进行位置相关的凯撒移位变换。接着程序调用scanf尝试从标准输入读取两个无符号整数到buffer0和buffer1指向的内存位置。这里的关键点在于,scanf被调用时传入的是两个指向无符号整数的指针,而随后的strncmp实际上比较的是这些整数在内存中的字节表示,而非整数值本身。

为了破解这个题目,我们需要hook scanf函数,因为真实执行scanf会从标准输入读取具体值,这会导致符号执行无法探索所有可能。脚本中定义了一个SimProcedure类来替换scanf的行为。在run方法中,我们创建两个32位的符号变量arg1和arg2,它们代表我们要寻找的两个整数。然后我们将这两个符号变量存储到scanf的参数指针所指向的内存位置,并使用小端序存储,这符合scanf对无符号整数的处理惯例。同时,我们将这两个符号变量的引用保存在state.globals字典中,以便后续求解时能够访问它们。

通过这种方式,我们让程序继续执行时,strncmp会比较符号变量在内存中的字节表示与变换后的目标字符串。当符号变量的值不符合要求时,程序会走向输出"Try again."的分支,这条路径会被标记为avoid。只有当符号变量的字节表示完全匹配目标字符串时,程序才会输出"Good Job.",这条路径会被保留下来。探索完成后,我们从全局状态中取出保存的符号变量,使用求解器计算它们的具体值。求解器会找到满足所有约束条件的整数解,即第一个整数的内存表示等于变换后字符串的前4个字节,第二个整数的内存表示等于后4个字节。

程序包含大量条件分支导致路径爆炸。利用 angr 的 Veritesting 技术自动合并相似路径,无需手动 hook。

静态链接的二进制文件,所有库函数都在二进制内部。需要 hook 系统调用(如 strlen)以避免复杂实现。

程序加载共享库(.so),验证函数在库中。需要加载库并直接对库函数执行符号执行。

用格式化字符串漏洞任意读取内存。需要找到正确的偏移读取 secret 字符串。

利用栈溢出漏洞任意写入内存。需要覆盖返回地址跳转到 secret 函数。

利用任意跳转漏洞控制程序计数器。需要找到输入使程序跳转到 secret 函数。

$sudo pip install angr
$sudo pip install angr
import angr
p = angr.Project('file_path')
import angr
p = angr.Project('file_path')
git clone https://github.com/jakespringer/angr_ctf
git clone https://github.com/jakespringer/angr_ctf
import angr
p = Project('./00_angr_find',load_options = {'auto_load_libs': False},main_opts = {'base_addr': 0x804850})
#p = Project('./00_angr_find',auto_load_libs=False)                                                
import angr
p = Project('./00_angr_find',load_options = {'auto_load_libs': False},main_opts = {'base_addr': 0x804850})
#p = Project('./00_angr_find',auto_load_libs=False)                                                
state = p.factory.entry_state()#初始化状态为程序运行到程序入口点的状态
#factory负责将Project实例化
simgr = p.factory.simgr(state)#创建模拟管理器,将初始化后的state添加到SM中
 
target = 0x8048678 #目标地址(输出Good job)
state = p.factory.entry_state()#初始化状态为程序运行到程序入口点的状态
#factory负责将Project实例化
simgr = p.factory.simgr(state)#创建模拟管理器,将初始化后的state添加到SM中
 
target = 0x8048678 #目标地址(输出Good job)
simgr.explore(find=target) #搜索路径,模拟管理器将尝试找到一个执行路径,使程序到达目标地址
if simgr.found: #找到满足条件的路径
    so_state = simgr.found[0] #获取第一个满足条件的状态
    print(so_state.posix.dumps(0)) #打印标准输入(文件描述符0)的内容==》程序运行过程中的输入内容
simgr.explore(find=target) #搜索路径,模拟管理器将尝试找到一个执行路径,使程序到达目标地址
if simgr.found: #找到满足条件的路径
    so_state = simgr.found[0] #获取第一个满足条件的状态
    print(so_state.posix.dumps(0)) #打印标准输入(文件描述符0)的内容==》程序运行过程中的输入内容
import angr
p = angr.Project('./00_angr_find',load_options = {'auto_load_libs': False},main_opts = {'base_addr': 0x804850})
#p = Project('./00_angr_find',auto_load_libs=False)  
state = p.factory.entry_state()#初始化状态为程序运行到程序入口点的状态
#factory负责将Project实例化
simgr = p.factory.simgr(state)#创建模拟管理器,将初始化后的state添加到SM中
 
target = 0x8048678 #目标地址(输出Good job)
simgr.explore(find=target) #搜索路径,模拟管理器将尝试找到一个执行路径,使程序到达目标地址
if simgr.found: #找到满足条件的路径
    so_state = simgr.found[0] #获取第一个满足条件的状态
    print(so_state.posix.dumps(0)) #打印标准输入(文件描述符0)的内容==》程序运行过程中的输入内容
import angr
p = angr.Project('./00_angr_find',load_options = {'auto_load_libs': False},main_opts = {'base_addr': 0x804850})
#p = Project('./00_angr_find',auto_load_libs=False)  
state = p.factory.entry_state()#初始化状态为程序运行到程序入口点的状态
#factory负责将Project实例化
simgr = p.factory.simgr(state)#创建模拟管理器,将初始化后的state添加到SM中
 
target = 0x8048678 #目标地址(输出Good job)
simgr.explore(find=target) #搜索路径,模拟管理器将尝试找到一个执行路径,使程序到达目标地址
if simgr.found: #找到满足条件的路径
    so_state = simgr.found[0] #获取第一个满足条件的状态
    print(so_state.posix.dumps(0)) #打印标准输入(文件描述符0)的内容==》程序运行过程中的输入内容
import angr
 
io = angr.Project('./01_angr_avoid',auto_load_libs=False)
 
init_state = io.factory.entry_state()
 
simgr = io.factory.simgr(init_state)
 
target = 0x80485E0 #目标地址
un_target = 0x80485A8 #不想被执行的地址
 
#avoid=un_target为不想执行这里
simgr.explore(find=target,avoid=un_target)
 
if simgr.found:
    so_state = simgr.found[0]
    print(so_state.posix.dumps(0))
import angr
 
io = angr.Project('./01_angr_avoid',auto_load_libs=False)
 
init_state = io.factory.entry_state()
 
simgr = io.factory.simgr(init_state)
 
target = 0x80485E0 #目标地址
un_target = 0x80485A8 #不想被执行的地址
 
#avoid=un_target为不想执行这里
simgr.explore(find=target,avoid=un_target)
 
if simgr.found:
    so_state = simgr.found[0]
    print(so_state.posix.dumps(0))
import angr
import sys
io = angr.Project('./02_angr_find_condition',auto_load_libs=False)
 
init_state = io.factory.entry_state()
 
simgr = io.factory.simgr(init_state)
 
#通过引入检测函数实现动态的选择想获取的state
def is_succ(state):
    #将标准输出的内容存储到变量std_out中
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Good Job.' in std_out:
        return True
    else:
        return False
 
def is_fail(state):
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Try again.' in std_out:
        return True
    else:
        return False
 
#采用状态检测
simgr.explore(find=is_succ,avoid=is_fail)
if simgr.found:
    so_state = simgr.found[0]
    print(so_state.posix.dumps(0))
import angr
import sys
io = angr.Project('./02_angr_find_condition',auto_load_libs=False)
 
init_state = io.factory.entry_state()
 
simgr = io.factory.simgr(init_state)
 
#通过引入检测函数实现动态的选择想获取的state
def is_succ(state):
    #将标准输出的内容存储到变量std_out中
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Good Job.' in std_out:
        return True
    else:
        return False
 
def is_fail(state):
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Try again.' in std_out:
        return True
    else:
        return False
 
#采用状态检测
simgr.explore(find=is_succ,avoid=is_fail)
if simgr.found:
    so_state = simgr.found[0]
    print(so_state.posix.dumps(0))
import angr
import claripy
import sys
io = angr.Project('./03_angr_symbolic_registers',auto_load_libs=False)
 
state_addr = 0x8048980
init_state = io.factory.blank_state(addr = state_addr) #跳过输入函数,从目标地址开始执行
 
passwd_size = 32 #符号向量大小
#通过claripy创建符号向量
passwd0 = claripy.BVS('passwd0',passwd_size)
passwd1 = claripy.BVS('passwd1',passwd_size)
passwd2 = claripy.BVS('passwd2',passwd_size)
#对寄存器进行赋值
init_state.regs.eax = passwd0
init_state.regs.ebx = passwd1
init_state.regs.edx = passwd2
 
simgr = io.factory.simgr(init_state)
 
def is_succ(state):
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Good Job.' in std_out:
        return True
    else:
        return False
 
def is_fail(state):
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Try again.' in std_out:
        return True
    else:
        return False
 
simgr.explore(find=is_succ,avoid=is_fail)
 
if simgr.found:
    so_state = simgr.found[0]
 
    so0 = hex(so_state.solver.eval(passwd0))
    so1 = hex(so_state.solver.eval(passwd1))
    so2 = hex(so_state.solver.eval(passwd2))
    print(so0,so1,so2)
import angr
import claripy
import sys
io = angr.Project('./03_angr_symbolic_registers',auto_load_libs=False)
 
state_addr = 0x8048980
init_state = io.factory.blank_state(addr = state_addr) #跳过输入函数,从目标地址开始执行
 
passwd_size = 32 #符号向量大小
#通过claripy创建符号向量
passwd0 = claripy.BVS('passwd0',passwd_size)
passwd1 = claripy.BVS('passwd1',passwd_size)
passwd2 = claripy.BVS('passwd2',passwd_size)
#对寄存器进行赋值
init_state.regs.eax = passwd0
init_state.regs.ebx = passwd1
init_state.regs.edx = passwd2
 
simgr = io.factory.simgr(init_state)
 
def is_succ(state):
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Good Job.' in std_out:
        return True
    else:
        return False
 
def is_fail(state):
    std_out = state.posix.dumps(sys.stdout.fileno())
    if b'Try again.' in std_out:
        return True
    else:
        return False
 
simgr.explore(find=is_succ,avoid=is_fail)
 
if simgr.found:
    so_state = simgr.found[0]
 
    so0 = hex(so_state.solver.eval(passwd0))
    so1 = hex(so_state.solver.eval(passwd1))
    so2 = hex(so_state.solver.eval(passwd2))
    print(so0,so1,so2)
import angr
import sys
import claripy
 
project = angr.Project('./04_angr_symbolic_stack')
initial_state = project.factory.blank_state(addr=0x8048697)
 
arg1 = claripy.BVS('arg1', 32)
arg2 = claripy.BVS('arg2', 32)
 
initial_state.regs.esp = initial_state.regs.ebp
initial_state.regs.esp -= 8  #esp-8
 
initial_state.stack_push(arg1)
initial_state.stack_push(arg2)
#v1_addr = initial_state.regs.ebp - 0x10   # 第二个输入直接指定地址
#v2_addr = initial_state.regs.ebp - 0x0C   # 第一个输入指定地址
#initial_state.memory.store(v1_addr, arg2, endness=project.arch.memory_endness)
#initial_state.memory.store(v2_addr, arg1, endness=project.arch.memory_endness)
 
simgr = project.factory.simulation_manager(initial_state)
 
def right(state):
    if b'Good' in state.posix.dumps(1):
        return True
    else:
        return False
 
def wrong(state):
    if b'Try' in state.posix.dumps(1):
        return True
    else:
        return False
 
simgr.explore(find=right, avoid=wrong)
 
if simgr.found:
    solution_state = simgr.found[0]
    print(solution_state.solver.eval(arg1))
    print(solution_state.solver.eval(arg2))
import angr
import sys
import claripy
 
project = angr.Project('./04_angr_symbolic_stack')
initial_state = project.factory.blank_state(addr=0x8048697)
 
arg1 = claripy.BVS('arg1', 32)
arg2 = claripy.BVS('arg2', 32)
 
initial_state.regs.esp = initial_state.regs.ebp
initial_state.regs.esp -= 8  #esp-8
 
initial_state.stack_push(arg1)
initial_state.stack_push(arg2)
#v1_addr = initial_state.regs.ebp - 0x10   # 第二个输入直接指定地址
#v2_addr = initial_state.regs.ebp - 0x0C   # 第一个输入指定地址
#initial_state.memory.store(v1_addr, arg2, endness=project.arch.memory_endness)
#initial_state.memory.store(v2_addr, arg1, endness=project.arch.memory_endness)
 
simgr = project.factory.simulation_manager(initial_state)
 
def right(state):
    if b'Good' in state.posix.dumps(1):
        return True
    else:
        return False
 
def wrong(state):
    if b'Try' in state.posix.dumps(1):
        return True
    else:
        return False
 
simgr.explore(find=right, avoid=wrong)
 
if simgr.found:
    solution_state = simgr.found[0]
    print(solution_state.solver.eval(arg1))
    print(solution_state.solver.eval(arg2))
import angr
import sys
import claripy
 
project = angr.Project('./05_angr_symbolic_memory')
initial_state = project.factory.blank_state(addr=0x8048601)
 
arg1 = claripy.BVS('arg1', 64)
arg2 = claripy.BVS('arg2', 64)
arg3 = claripy.BVS('arg3', 64)
arg4 = claripy.BVS('arg4', 64)
addr = 0xA1BA1C0
 
initial_state.memory.store(addr, arg1)
initial_state.memory.store(addr + 0x8, arg2)
initial_state.memory.store(addr + 0x10, arg3)
initial_state.memory.store(addr + 0x18, arg4)
 
simgr = project.factory.simulation_manager(initial_state)
 
def right(state):
    if b'Good' in state.posix.dumps(1):
        return True
    else:
        return False
 
def wrong(state):
    if b'Try' in state.posix.dumps(1):
        return True
    else:
        return False
 
simgr.explore(find=right, avoid=wrong)
 
if simgr.found:
    solution_state = simgr.found[0]
    print(solution_state.solver.eval(arg1, cast_to=bytes))
    print(solution_state.solver.eval(arg2, cast_to=bytes))
    print(solution_state.solver.eval(arg3, cast_to=bytes))
    print(solution_state.solver.eval(arg4, cast_to=bytes))
import angr
import sys
import claripy
 
project = angr.Project('./05_angr_symbolic_memory')
initial_state = project.factory.blank_state(addr=0x8048601)
 
arg1 = claripy.BVS('arg1', 64)
arg2 = claripy.BVS('arg2', 64)
arg3 = claripy.BVS('arg3', 64)
arg4 = claripy.BVS('arg4', 64)
addr = 0xA1BA1C0
 
initial_state.memory.store(addr, arg1)
initial_state.memory.store(addr + 0x8, arg2)
initial_state.memory.store(addr + 0x10, arg3)
initial_state.memory.store(addr + 0x18, arg4)
 
simgr = project.factory.simulation_manager(initial_state)
 
def right(state):
    if b'Good' in state.posix.dumps(1):
        return True
    else:
        return False
 
def wrong(state):
    if b'Try' in state.posix.dumps(1):
        return True
    else:
        return False
 
simgr.explore(find=right, avoid=wrong)
 
if simgr.found:
    solution_state = simgr.found[0]
    print(solution_state.solver.eval(arg1, cast_to=bytes))
    print(solution_state.solver.eval(arg2, cast_to=bytes))
    print(solution_state.solver.eval(arg3, cast_to=bytes))
    print(solution_state.solver.eval(arg4, cast_to=bytes))
import angr
import claripy
 
def solve():
    # 加载程序(不加载库函数,提升速度)
    proj = angr.Project('./06_angr_symbolic_dynamic_memory', auto_load_libs=False)
     
    # 从输入完成后开始执行(跳过malloc和scanf)
    start_addr = 0x08048699
    state = proj.factory.blank_state(addr=start_addr)
     
    # 创建两个符号变量(8字节密码)
    passwd0 = claripy.BVS('passwd0', 8 * 8)
    passwd1 = claripy.BVS('passwd1', 8 * 8)
     
    # 伪造堆地址(BSS段中未使用的区域)
    fake_chunk0 = 0x12340
    fake_chunk1 = 0x12350
     
    # 篡改指针:让buffer0/buffer1指向伪造地址
    # 注意:必须指定端序和size,否则会有警告[^12^]
    state.memory.store(0xABCC8A4, fake_chunk0,
                       endness=proj.arch.memory_endness, size=4)
    state.memory.store(0xABCC8AC, fake_chunk1,
                       endness=proj.arch.memory_endness, size=4)
     
    # 将符号变量存入伪造堆块
    state.memory.store(fake_chunk0, passwd0)
    state.memory.store(fake_chunk1, passwd1)
     
    # 创建模拟管理器
    simgr = proj.factory.simulation_manager(state)
     
    # 定义成功/失败条件
    def is_success(s):
        return b'Good Job.' in s.posix.dumps(1)
     
    def is_fail(s):
        return b'Try again.' in s.posix.dumps(1)
     
    # 探索路径
    simgr.explore(find=is_success, avoid=is_fail)
     
    if simgr.found:
        sol_state = simgr.found[0]
        # 求解并转换为字节
        sol0 = sol_state.solver.eval(passwd0, cast_to=bytes)
        sol1 = sol_state.solver.eval(passwd1, cast_to=bytes)
        print(f"Solution: {sol0} {sol1}")
        return sol0, sol1
    else:
        print("No solution found")
        return None
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    # 加载程序(不加载库函数,提升速度)
    proj = angr.Project('./06_angr_symbolic_dynamic_memory', auto_load_libs=False)
     
    # 从输入完成后开始执行(跳过malloc和scanf)
    start_addr = 0x08048699
    state = proj.factory.blank_state(addr=start_addr)
     
    # 创建两个符号变量(8字节密码)
    passwd0 = claripy.BVS('passwd0', 8 * 8)
    passwd1 = claripy.BVS('passwd1', 8 * 8)
     
    # 伪造堆地址(BSS段中未使用的区域)
    fake_chunk0 = 0x12340
    fake_chunk1 = 0x12350
     
    # 篡改指针:让buffer0/buffer1指向伪造地址
    # 注意:必须指定端序和size,否则会有警告[^12^]
    state.memory.store(0xABCC8A4, fake_chunk0,
                       endness=proj.arch.memory_endness, size=4)
    state.memory.store(0xABCC8AC, fake_chunk1,
                       endness=proj.arch.memory_endness, size=4)
     
    # 将符号变量存入伪造堆块
    state.memory.store(fake_chunk0, passwd0)
    state.memory.store(fake_chunk1, passwd1)
     
    # 创建模拟管理器
    simgr = proj.factory.simulation_manager(state)
     
    # 定义成功/失败条件
    def is_success(s):
        return b'Good Job.' in s.posix.dumps(1)
     
    def is_fail(s):
        return b'Try again.' in s.posix.dumps(1)
     
    # 探索路径
    simgr.explore(find=is_success, avoid=is_fail)
     
    if simgr.found:
        sol_state = simgr.found[0]
        # 求解并转换为字节
        sol0 = sol_state.solver.eval(passwd0, cast_to=bytes)
        sol1 = sol_state.solver.eval(passwd1, cast_to=bytes)
        print(f"Solution: {sol0} {sol1}")
        return sol0, sol1
    else:
        print("No solution found")
        return None
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    # 加载程序
    proj = angr.Project('./07_angr_symbolic_file', auto_load_libs=False)
     
    # 从文件读取完成后开始执行(跳过fopen/fscanf)
    start_addr = 0x080488D3
    state = proj.factory.blank_state(addr=start_addr)
     
    # 创建符号变量表示文件内容(0x40 = 64字节)
    file_content = claripy.BVS('file_content', 8 * 0x40)
     
    # 创建虚拟文件
    # 注意:文件名必须与程序硬编码的一致
    sim_file = angr.SimFile('OJKSQYDP.txt', content=file_content)
     
    # 将虚拟文件插入文件系统
    state.fs.insert('OJKSQYDP.txt', sim_file)
     
    # 关键:劫持全局文件名指针
    # file_str = 0xA1BA1C0,指向文件名字符串
    fake_path_addr = 0x12345
    state.memory.store(0xA1BA1C0, fake_path_addr,
                       endness=proj.arch.memory_endness, size=4)
    # 写入实际路径字符串
    state.memory.store(fake_path_addr, b'OJKSQYDP.txt\x00')
     
    # 创建模拟管理器
    simgr = proj.factory.simulation_manager(state)
     
    # 定义成功/失败条件
    def is_success(s):
        return b'Good Job.' in s.posix.dumps(1)
     
    def is_fail(s):
        return b'Try again.' in s.posix.dumps(1)
     
    # 探索路径
    simgr.explore(find=is_success, avoid=is_fail)
     
    if simgr.found:
        sol_state = simgr.found[0]
        # 求解文件内容并转换为字符串
        solution = sol_state.solver.eval(file_content, cast_to=bytes)
        # 提取有效部分(到\0为止)
        solution_str = solution[:solution.index(b'\x00')]
        print(f"Solution: {solution_str.decode()}")
        return solution_str
    else:
        print("No solution found")
        return None
 
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    # 加载程序
    proj = angr.Project('./07_angr_symbolic_file', auto_load_libs=False)
     
    # 从文件读取完成后开始执行(跳过fopen/fscanf)
    start_addr = 0x080488D3
    state = proj.factory.blank_state(addr=start_addr)
     
    # 创建符号变量表示文件内容(0x40 = 64字节)
    file_content = claripy.BVS('file_content', 8 * 0x40)
     
    # 创建虚拟文件
    # 注意:文件名必须与程序硬编码的一致
    sim_file = angr.SimFile('OJKSQYDP.txt', content=file_content)
     
    # 将虚拟文件插入文件系统
    state.fs.insert('OJKSQYDP.txt', sim_file)
     
    # 关键:劫持全局文件名指针
    # file_str = 0xA1BA1C0,指向文件名字符串
    fake_path_addr = 0x12345
    state.memory.store(0xA1BA1C0, fake_path_addr,
                       endness=proj.arch.memory_endness, size=4)
    # 写入实际路径字符串
    state.memory.store(fake_path_addr, b'OJKSQYDP.txt\x00')
     
    # 创建模拟管理器
    simgr = proj.factory.simulation_manager(state)
     
    # 定义成功/失败条件
    def is_success(s):
        return b'Good Job.' in s.posix.dumps(1)
     
    def is_fail(s):
        return b'Try again.' in s.posix.dumps(1)
     
    # 探索路径
    simgr.explore(find=is_success, avoid=is_fail)
     
    if simgr.found:
        sol_state = simgr.found[0]
        # 求解文件内容并转换为字符串
        solution = sol_state.solver.eval(file_content, cast_to=bytes)
        # 提取有效部分(到\0为止)
        solution_str = solution[:solution.index(b'\x00')]
        print(f"Solution: {solution_str.decode()}")
        return solution_str
    else:
        print("No solution found")
        return None
 
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    project = angr.Project('./08_angr_constraints', auto_load_libs=False)
     
    #  从 scanf 返回后开始
    initial_state = project.factory.blank_state(addr=0x08048625)
     
    sym_password = claripy.BVS('password', 8 * 16)
    buffer_addr = 0x0804A050
     
    initial_state.memory.store(buffer_addr, sym_password)
     
    simgr = project.factory.simulation_manager(initial_state)
     
    #  探索到 Good Job. 之前的状态
    simgr.explore(find=0x08048696
     
    if simgr.found:
        solution_state = simgr.found[0]
         
        #  变换后的 buffer
        transformed_buffer = solution_state.memory.load(buffer_addr, 16)
         
        #  延迟约束
        solution_state.add_constraints(transformed_buffer == b'AUPDNNPROEZRJWKB')
         
        #  求解
        solution = solution_state.solver.eval(sym_password, cast_to=bytes)
        print(solution)
        return solution
    else:
        print(f"Not found. Active: {len(simgr.active)}")
        print(f"Deadended: {len(simgr.deadended)}")
        return None
 
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    project = angr.Project('./08_angr_constraints', auto_load_libs=False)
     
    #  从 scanf 返回后开始
    initial_state = project.factory.blank_state(addr=0x08048625)
     
    sym_password = claripy.BVS('password', 8 * 16)
    buffer_addr = 0x0804A050
     
    initial_state.memory.store(buffer_addr, sym_password)
     
    simgr = project.factory.simulation_manager(initial_state)
     
    #  探索到 Good Job. 之前的状态
    simgr.explore(find=0x08048696
     
    if simgr.found:
        solution_state = simgr.found[0]
         
        #  变换后的 buffer
        transformed_buffer = solution_state.memory.load(buffer_addr, 16)
         
        #  延迟约束
        solution_state.add_constraints(transformed_buffer == b'AUPDNNPROEZRJWKB')
         
        #  求解
        solution = solution_state.solver.eval(sym_password, cast_to=bytes)
        print(solution)
        return solution
    else:
        print(f"Not found. Active: {len(simgr.active)}")
        print(f"Deadended: {len(simgr.deadended)}")
        return None
 
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    project = angr.Project('./09_angr_hooks', auto_load_libs=False)
     
    #  1. entry_state:自动初始化栈、寄存器
    initial_state = project.factory.entry_state(
        add_options={angr.options.ZERO_FILL_UNCONSTRAINED_REGISTERS} 
    )
     
    #  2. Hook check_equals(在函数内部做判断)
    check_equals_call = 0x80486B3  #
    buffer_addr = 0x804A054        #
    target_str = b'XYMKBKUHNIQYNQXE'  # 从函数名提取
     
    @project.hook(check_equals_call, length=5)
    def hook_check_equals(state):
        # 读取 buffer 内容
        res = state.memory.load(buffer_addr, 16)
        # 直接判断并设置返回值(eax)
        # 只有 res == target 时,eax=1 → Good Job 路径
        state.regs.eax = claripy.If(res == target_str, claripy.BVV(1, 32), claripy.BVV(0, 32))
     
    # 3. 创建模拟管理器
    simgr = project.factory.simulation_manager(initial_state)
 
    #  4. 探索与规避
    def right(state):
        return b'Good' in state.posix.dumps(1)
    def wrong(state):
        return b'Try' in state.posix.dumps(1)
 
    simgr.explore(find=right, avoid=wrong)
 
    # 5. 输出解
    if simgr.found:
        solution_state = simgr.found[0]
        print(solution_state.posix.dumps(0))  # 打印输入
        return solution_state.posix.dumps(0)
    else:
        print("[-] No solution")
        return None
 
if __name__ == '__main__':
    solve()
import angr
import claripy
 
def solve():
    project = angr.Project('./09_angr_hooks', auto_load_libs=False)
     
    #  1. entry_state:自动初始化栈、寄存器
    initial_state = project.factory.entry_state(
        add_options={angr.options.ZERO_FILL_UNCONSTRAINED_REGISTERS} 
    )
     
    #  2. Hook check_equals(在函数内部做判断)
    check_equals_call = 0x80486B3  #
    buffer_addr = 0x804A054        #
    target_str = b'XYMKBKUHNIQYNQXE'  # 从函数名提取
     
    @project.hook(check_equals_call, length=5)
    def hook_check_equals(state):
        # 读取 buffer 内容
        res = state.memory.load(buffer_addr, 16)
        # 直接判断并设置返回值(eax)
        # 只有 res == target 时,eax=1 → Good Job 路径
        state.regs.eax = claripy.If(res == target_str, claripy.BVV(1, 32), claripy.BVV(0, 32))
     
    # 3. 创建模拟管理器
    simgr = project.factory.simulation_manager(initial_state)
 
    #  4. 探索与规避
    def right(state):
        return b'Good' in state.posix.dumps(1)
    def wrong(state):
        return b'Try' in state.posix.dumps(1)
 
    simgr.explore(find=right, avoid=wrong)
 
    # 5. 输出解
    if simgr.found:
        solution_state = simgr.found[0]
        print(solution_state.posix.dumps(0))  # 打印输入
        return solution_state.posix.dumps(0)
    else:
        print("[-] No solution")
        return None
 
if __name__ == '__main__':
    solve()
initial_state = project.factory.entry_state()
initial_state = project.factory.entry_state()
@project.hook_symbol('check_equals_ORSDDWXHZURJRBDH', func())
@project.hook_symbol('check_equals_ORSDDWXHZURJRBDH', func())
def run(self, a1, a2):
    res = self.state.memory.load(a1, a2)  # 读取 s 的内容(已变换)
    return claripy.If(res == target, BVV(1, 32), BVV(0, 32))
def run(self, a1, a2):
    res = self.state.memory.load(a1, a2)  # 读取 s 的内容(已变换)
    return claripy.If(res == target, BVV(1, 32), BVV(0, 32))
// 程序执行到 check_equals 时:
s[i] = complex_function(original_input[i], 18-i);
// s 里已是变换后的值(符号表达式)
 
// 例如:
// res[0] = (stdin[0] + 18) % 26 + 'A'
// res[1] = (stdin[1] + 17) % 26 + 'A'
// ...
// 程序执行到 check_equals 时:
s[i] = complex_function(original_input[i], 18-i);
// s 里已是变换后的值(符号表达式)
 
// 例如:
// res[0] = (stdin[0] + 18) % 26 + 'A'
// res[1] = (stdin[1] + 17) % 26 + 'A'
// ...
simgr.explore(find=right, avoid=wrong)
 
def right(state):
    return b'Good' in state.posix.dumps(1)
simgr.explore(find=right, avoid=wrong)
 
def right(state):
    return b'Good' in state.posix.dumps(1)
if simgr.found:
    solution_state = simgr.found[0]
    print(solution_state.posix.dumps(0))  # 求解符号化的 stdin
if simgr.found:
    solution_state = simgr.found[0]
    print(solution_state.posix.dumps(0))  # 求解符号化的 stdin
# 约束方程组:
(stdin[0] + 18) % 26 + 'A' == 'O'
(stdin[1] + 17) % 26 + 'A' == 'R'
...
(stdin[15] + 3) % 26 + 'A' == 'H'
 
# 求解器逆向求解:
stdin[0] = ('O' - 'A' - 18) % 26 = 'M'
stdin[1] = ('R' - 'A' - 17) % 26 = 'S'
...
stdin[15] = ('H' - 'A' - 3) % 26 = 'K'
 
# 结果:b'MSWKNJNAVTTOZMRY'
# 约束方程组:
(stdin[0] + 18) % 26 + 'A' == 'O'
(stdin[1] + 17) % 26 + 'A' == 'R'
...
(stdin[15] + 3) % 26 + 'A' == 'H'
 
# 求解器逆向求解:
stdin[0] = ('O' - 'A' - 18) % 26 = 'M'
stdin[1] = ('R' - 'A' - 17) % 26 = 'S'

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-11-27 14:23 被S_i_d编辑 ,原因: 修改了部分图片错误
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 2126
活跃值: (1975)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2025-11-30 12:41
1
游客
登录 | 注册 方可回帖
返回