ctf_angr

一个用于练习angr的ctf题库,从入门到进阶,同时配套全英文ppt,从符号执行到angr详细使用方式,一站式入门👍

GitHub下载地址[链接]

00_angr_find

ida分析

伪代码非常简单,执行流程为:输入->加密->比较->输出,分支少,所以遍历起来速度很快

伪代码易读,数据的字符串经过complex_function函数加密过后比较。

main_function

complex_function

如果按照传统的方法,需要逆加密算法然后写出解密算法,但是angr不需要这些繁琐的操作,只需要告诉其实地址和目标地址,angr就会进行所有遍历,对符号进行约束,从而得出结果。

angr遍历求解

首先贴出全代码以及运行结果,最后打印的值就是对符号不断约束求解得到的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import angr
import sys

filepath = '/home/fish/桌面/00_angr_find'

project = angr.Project(filepath)
initial_state = project.factory.entry_state()
print_good_addr = 0x0804867D
simulation = project.factory.simgr(initial_state)
simulation.explore(find = print_good_addr)

if simulation.found:
solution_state = simulation.found[0]
print(solution_state.posix.dumps(sys.stdin.fileno()))
else:
print('Could not find the solution')

使用angr过程

  1. 创建项目

    首先用Project函数创建一个项目,Project参数为需要求解的二进制文件路径

    1
    project = angr.Project(filepath)
  2. 告诉angr从哪儿开始执行

    entry_state()表明从main函数开始执行(从头开始执行)

    1
    initial_state = project.factory.entry_state()
  3. 创建模拟管理器

    simgr是创建函数

    1
    simulation = project.factory.simgr(initial_state)
  4. 开始探索二进制文件

    explore函数需要遍历的结束地址,也就是这个二进制程序中打印字符串**Good Job.**的地址。

    1
    2
    print_good_address = 0x0804867D
    simulation.explore(find=print_good_address)
  5. 检查是否找到了解决方案

    如果找到解决方案,found不为空(在pyhon中空代表false,不为空代表true),将解决方案打印到屏幕输出端

    1
    2
    if simulation.found:
    solution_state = simulation.found[0]

总结主要过程

创建工程 –> 指定执行入口 –> 创建二进制文件执行模拟器 –> 探索各个分支 –> 解出解决方案 –> 打印结果

01_angr_avoid

​ 这一次的文件较大,main函数在ida中不能F5,即便F5过后也可能因为伪代码较复杂无法阅读,所以在简单观察过后可以直接用angr看是否有解,但是作者这次在程序中加了一点料,方便我们学习avoid参数

should_succeed这个变量初始值为1本身并没有问题但是avoid_me函数会将should_succeed赋值为0。

​ 所以这个如果要打印出**Good Job.**需要两个条件同时满足(should_succeed值为1,且输入的字符串加密过后满足条件),如果在遍历时不添加avoid条件会花费大量的时间(虽然结果一样),为了尽可能的节约时间,需要在遍历时避免avoid_me函数,所以在上一个的条件下,需要在添加其他条件,这里需要添加avoid

1
2
avoid_addr = 0x080485A8 # avoid_me函数地址
simgr.explore(find = good_addr, avoid = avoid_addr) # 添加avoid条件

02_angr_condtion

出了在ida中直接寻找字符串地址,还可以自定义函数遍历所有字符串,寻找需要的字符串地址

1
2
3
4
5
6
7
8
9
10
11
12
13
# 自定义函数寻找字符串

def is_success(state):
#print(state)
stdout_stdout = state.posix.dumps(1)
print(stdout_stdout)
return b'Good Job.' in stdout_stdout

def is_fail(state):
#print(state)
stdout_stdout = state.posix.dumps(1)
print(stdout_stdout)
return b'Try again.' in stdout_stdout

完整脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from z3 import *
import angr
import sys

def main():
filepath = './02_angr_find_condition'
project = angr.Project(filepath)
init = project.factory.entry_state()
simgr = project.factory.simgr(init)


def is_success(state):
#print(state)
stdout_stdout = state.posix.dumps(1)
print(stdout_stdout)
return b'Good Job.' in stdout_stdout

def is_fail(state):
#print(state)
stdout_stdout = state.posix.dumps(1)
print(stdout_stdout)
return b'Try again.' in stdout_stdout
print(is_success)
print(is_fail)
simgr.explore(find=is_success, avoid=is_fail)

if simgr.found:
solution = simgr.found[0]
flag = solution.posix.dumps(0)
print(flag)
else:
raise Exception('not find')



if __name__ == "__main__":
main()

输出结果