0%

angr

Angr

有好几个题目,我们全部用angr来做,

00_angr_find

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+1Ch] [ebp-1Ch]
char s1[9]; // [esp+23h] [ebp-15h] BYREF
unsigned int v6; // [esp+2Ch] [ebp-Ch]

v6 = __readgsdword(0x14u);
printf("Enter the password: ");
__isoc99_scanf("%8s", s1);
for ( i = 0; i <= 7; ++i )
s1[i] = complex_function(s1[i], i);
if ( !strcmp(s1, "ILIUFVJF") )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

comlex函数中也就是一个if函数和return,并不难,如何用angr写脚本是一个难的问题

angr的使用也比较麻烦,因为angr带有z3,如果直接安装,会出现问题,这个z3与python的z3是由一点去别的,所以我们每次用都要搞一个虚拟环境,我们每次使用先打开虚拟环境:

其实只用后两个命令都行

1
2
3
4
5
6
cd
sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper
export WORKON_HOME=~/HOME
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
mkvirtualenv --python=$(which python3) angr && pip install angr

这样就行了

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
import angr
import sys
def main(argv):
#目标文件路径
path_to_binary = './00_angr_find/00_angr_find'
#创建项目
project = angr.Project(path_to_binary)
#设置项目起点,entry_state是程序的入口处,相当于main
initial_state = project.factory.entry_state()
#设置模拟器
simulation = project.factory.simgr(initial_state)
#设置目标地址
print_good_addr = 0x08048694
simulation.explore(find=print_good_addr)

#如果到达目标地址,打印此时符号向量
if simulation.found:
solution_state = simulation.found[0]
print(solution_state.posix.dumps(sys.stdin.fileno()))

#无解或出错抛出异常
else:
raise Exception('Could not find solution')

if __name__ == '__main__':
main(sys.argv)
1
2
3
4
5
6
7
8
9
10
(angr) ┌─(~/syclover/angr/decode)───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────(jonathan@DESKTOP-4L3BSKM:pts/0)─┐
└─(12:51:45)──> python3 angr0.py
WARNING | 2022-03-12 12:53:13,212 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-12 12:53:13,212 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-12 12:53:13,212 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-12 12:53:13,212 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-12 12:53:13,212 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-12 12:53:13,213 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x80486c1 (__libc_csu_init+0x1 in 00_angr_find (0x80486c1))
WARNING | 2022-03-12 12:53:14,270 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeff50 with 4 unconstrained bytes referenced from 0x8186b80 (strcmp+0x0 in libc.so.6 (0x86b80))
b'IICLTGRK'

得到结果。

sys.argv

传递给Python脚本的命令行参数列表。argv[0]是脚本名称(依赖于操作系统,无论这是否是完整路径名)。如果使用-c解释器的命令行选项执行命令,argv[0]则将其设置为字符串’-c’。如果没有脚本名称传递给Python解释器,argv[0]则为空字符串。

这个就是命令行输入

if name == ‘main‘:

不能在import引用的脚本中执行。一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if name == ‘main’: 的作用就是控制这两种情况执行代码的过程,在 if name == ‘main’: 下的代码只有在第一种情况下

factory

angr中有许多使用时需要一个实例化的project的类,可以使用project.factory而不用把project到处传递。

states

Project对象只代表程序的一个初始化镜像,当你使用angr来执行时,你在使用一个表示模拟程序状态的一个特殊对象SimState

01_angr_avoid

通过字符串搜索到good job

这一题是明显让我们使用avoid,那么avoid其实就是告诉脚本不要走哪边。

主函数太大,无法反编译,估计是有很多别的路,所以要加avoid,我们可以用上一个脚本,但稍微改一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from doctest import FAIL_FAST
import angr
import sys

def main(argv):
path_to_binary = '../solutions/01_angr_avoid/01_angr_avoid'
project = angr.Project(path_to_binary)

initial_state = project.factory.entry_state()

simulation = project.factory.simgr(initial_state)
print_good_address = 0x080485FC
fail_address = 0x0804860E
simulation.explore(find=print_good_address,avoid=fail_address)
if simulation.found:
solution_state = simulation.found[0]
print(solution_state.posix.dumps(sys.stdin.fileno()))

else:
raise Exception('Could not find solution')

if __name__ == '__main__':
main(sys.argv)

我们只是在模拟器中添加了avoid。

1
2
3
4
5
6
7
8
9
WARNING | 2022-03-12 14:12:22,299 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-12 14:12:22,299 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-12 14:12:22,299 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-12 14:12:22,299 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-12 14:12:22,299 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-12 14:12:22,300 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x80d45b1 (__libc_csu_init+0x1 in 01_angr_avoid (0x80d45b1))
WARNING | 2022-03-12 14:12:51,054 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeff1d with 11 unconstrained bytes referenced from 0x8187170 (strncmp+0x0 in libc.so.6 (0x87170))
WARNING | 2022-03-12 14:12:51,054 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeff40 with 4 unconstrained bytes referenced from 0x8187170 (strncmp+0x0 in libc.so.6 (0x87170))
b'JLVUSGJZ'

02_angr_find_condition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+18h] [ebp-40h]
int j; // [esp+1Ch] [ebp-3Ch]
char s1[20]; // [esp+24h] [ebp-34h] BYREF
char s2[20]; // [esp+38h] [ebp-20h] BYREF
unsigned int v8; // [esp+4Ch] [ebp-Ch]

v8 = __readgsdword(0x14u);
for ( i = 0; i <= 19; ++i )
s2[i] = 0;
qmemcpy(s2, "CAWMCZTB", 8);
printf("Enter the password: ");
__isoc99_scanf("%8s", s1);
for ( j = 0; j <= 7; ++j )
s1[j] = complex_function(s1[j], j + 8);
if ( !strcmp(s1, s2) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

这个题哦,看上去没啥区别,当我们找puts时,就会出现问题

这么多puts:good,应该怎么办,解决方法是通过判断控制台输出数据是不是”Good Job” 和”Try again” 来确认执行到了成功还是失败分支.即我们不再确认地址,我们只看输出是不是我们想要的

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
import sys
import angr
def main(argv):
path = '../solutions/02_angr_find_condition/02_angr_find_condition'
project = angr.Project(path)
state = project.factory.entry_state()
simulation = project.factory.simgr(state)

def good_job(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())

return 'Good Job' in str(stdout_output)
#含义就是在所有输出里找try again
def try_again(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())

return 'Try again' in str(stdout_output)

simulation.explore(find=good_job,avoid=try_again)

if simulation.found:
solution_state = simulation.found[0]
#下面是打印输入流,输出是stdout
print(solution_state.posix.dumps(sys.stdin.fileno()))
else:
raise Exception('NOooooooo!')

if __name__ == '__main__':
main(sys.argv)

1
2
3
4
5
6
7
8
9
WARNING | 2022-03-12 14:41:20,664 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-12 14:41:20,664 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-12 14:41:20,664 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-12 14:41:20,664 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-12 14:41:20,664 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-12 14:41:20,664 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x804d2a1 (__libc_csu_init+0x1 in 02_angr_find_condition (0x804d2a1))
WARNING | 2022-03-12 14:41:21,644 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeff0d with 11 unconstrained bytes referenced from 0x8186b80 (strcmp+0x0 in libc.so.6 (0x86b80))
WARNING | 2022-03-12 14:41:21,644 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeff30 with 4 unconstrained bytes referenced from 0x8186b80 (strcmp+0x0 in libc.so.6 (0x86b80))
b'OHYJUMBE'

03_angr_symbolic_registers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 user_input; // rax
int v5; // [esp+4h] [ebp-14h]
int v6; // [esp+8h] [ebp-10h]
int v7; // [esp+Ch] [ebp-Ch]
int v8; // [esp+Ch] [ebp-Ch]

printf("Enter the password: ");
user_input = get_user_input();
v7 = HIDWORD(user_input);
v5 = complex_function_1(user_input);
v6 = complex_function_2();
v8 = complex_function_3(v7);
if ( v5 || v6 || v8 )
puts("Try again.");
else
puts("Good Job.");
return 0;
}

三个complex,里面全是运算,有一点这三个函数只有两个有参数,但我们看汇编发现其实是有三个值,那么我们只需要求出eax,ebx,edx的值就行了

那么我们就要学会如何从寄存器中获得输入

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
38
39
40
import sys
import angr
import claripy
def main():
path = '../solutions/03_angr_symbolic_registers/03_angr_symbolic_registers'
project = angr.Project(path)
#自己设置项目起始地址
start_addr = 0x080488C7
state = project.factory.blank_state(addr=start_addr)

bit_lenth = 32
psd0 = claripy.BVS('psd0',bit_lenth)
psd1 = claripy.BVS('psd1',bit_lenth)
psd2 = claripy.BVS('psd2',bit_lenth)

state.regs.eax = psd0
state.regs.ebx = psd1
state.regs.edx = psd2

simulation = project.factory.simgr(state)

good_add = 0x0804892F
fail_add = 0x0804891D
simulation.explore(find=good_add,avoid=fail_add)

if simulation.found:
solution_state = simulation.found[0]
#如何进行寄存器输出
solution0 =solution_state.se.eval(psd0)
solution1 =solution_state.se.eval(psd1)
solution2 =solution_state.se.eval(psd2)
solution = ' '.join(map('{:x}'.format,[solution0,solution1,solution2]))
print(solution)
else:
raise Exception('Noooooooo!')
if __name__ == '__main__':
main()



最主要的是,如果我们要从寄存器中找数据,那么我们一定要自己把函数位置找到,因为寄存器是会变的。

初始化寄存器操作:

1
2
3
bit_length = 32
psd0 = claripy.BVS('psd0', bit_length)
initial_state.regs.eax = psd0

eval

是Python的一个内置函数,功能十分强大,这个函数的作用是,返回传入字符串的表达式的结果。就是说:将字符串当成有效的表达式 来求值 并 返回计算结果。

formamt

fotmat作为Python的的格式字符串函数,主要通过字符串中的花括号{},来识别替换字段,从而完成字符串的格式化。

上面主要是变成十六进制再连起来

1
2
3
4
5
6
7
8
WARNING | 2022-03-12 15:33:58,675 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-12 15:33:58,676 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-12 15:33:58,676 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-12 15:33:58,676 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-12 15:33:58,676 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-12 15:33:58,676 | angr.storage.memory_mixins.default_filler_mixin | Filling register ebp with 4 unconstrained bytes referenced from 0x80488c7 (main+0x26 in 03_angr_symbolic_registers (0x80488c7))
CRITICAL | 2022-03-12 15:33:59,119 | angr.sim_state | The name state.se is deprecated; please use state.solver.
e9b37483 7aab5fde 8f5b48ea

总结:

1
2
3
4
5
6
7
project.factory.blank_state(addr=start_address) => 创建自定义入口的状态上下文

initial_state.regs => 操作状态上下文的寄存器

claripy.BVS('变量名', 变量大小) => 创建求解变量

solution_state.se.eval(变量) => 求解符号变量

04_angr_symbolic_stack

这个题又不一样了,这个是局部变量

1
2
3
4
5
6
int __cdecl main(int argc, const char **argv, const char **envp)
{
printf("Enter the password: ");
handle_user();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
int handle_user()
{
int v1; // [esp+8h] [ebp-10h] BYREF
int v2[3]; // [esp+Ch] [ebp-Ch] BYREF

__isoc99_scanf("%u %u", v2, &v1);
v2[0] = complex_function0(v2[0]);
v1 = complex_function1(v1);
if ( v2[0] == 2083606899 && v1 == -99478518 )
return puts("Good Job.");
else
return puts("Try again.");
}

我们知道局部变量是储存在栈中的,所以我们要构造栈上的内存

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
38
39
40
41
42
43
44
45
46
47
48
49
from mimetypes import init
import sys
import angr
import claripy


def main():
binary_path = '../solutions/04_angr_symbolic_stack/04_angr_symbolic_stack'
project = angr.Project(binary_path)

start_addr = 0x080486AE
initial_state = project.factory.blank_state(addr=start_addr)

initial_state.regs.ebp = initial_state.regs.esp # 初始化栈,令ebp等于esp

password0 = claripy.BVS('password0', 32) # 初始化两个位向量
password1 = claripy.BVS('password1', 32)

padding_length_in_bytes = 0x8 # 填充栈 integer * 2
initial_state.regs.esp -= padding_length_in_bytes

initial_state.stack_push(password0) # 将位向量压入栈中
initial_state.stack_push(password1)

simulation = project.factory.simgr(initial_state)

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:
solution_state = simulation.found[0]

solution0 = solution_state.se.eval(password0)
solution1 = solution_state.se.eval(password1)

solution = '%u %u' % (solution0, solution1)
print(solution)
else:
raise Exception('could not find the solution')

if __name__ == '__main__':
main()

符号化栈空间的运用:

1
2
3
4
5
6
initial_state.regs.ebp = initial_state.regs.esp # 初始化栈,令ebp等于esp

padding_length_in_bytes = 0xC # 填充栈
initial_state.regs.esp -= padding_length_in_bytes

initial_state.stack_push(password0) # 将位向量压入栈中

05_angr_symbolic_memory

这个题考的是bss段的输入,我们要构造bss段符号表示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+Ch] [ebp-Ch]

memset(user_input, 0, 0x21u);
printf("Enter the password: ");
__isoc99_scanf("%8s %8s %8s %8s", user_input, &unk_AB232C8, &unk_AB232D0, &unk_AB232D8);
for ( i = 0; i <= 31; ++i )
*(_BYTE *)(i + 179450560) = complex_function(*(char *)(i + 179450560), i);
if ( !strncmp(user_input, "OSIWHBXIFOQVSBZBISILSCLBIAXSEWUT", 0x20u) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}
1
2
3
4
5
6
7
8
9
int __cdecl complex_function(int a1, int a2)
{
if ( a1 <= 64 || a1 > 90 )
{
puts("Try again.");
exit(1);
}
return (9 * a2 + a1 - 65) % 26 + 65;
}

给出脚本:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import angr
import sys
import claripy

def main(agrv):
path = '../solutions/05_angr_symbolic_memory/05_angr_symbolic_memory'
project = angr.Project(path)
adds = 0x08048618#scanf后
state = project.factory.blank_state(add=adds)
# 64 = 8(8个字符) * 1(每个字符一字节) * 8(每个字节8比特)
psd0 =claripy.BVS('psd0',64)
psd1 =claripy.BVS('psd1',64)
psd2 =claripy.BVS('psd2',64)
psd3 =claripy.BVS('psd3',64)

psd0_add = 0x0AB232C0
psd1_add = 0x0AB232C8
psd2_add = 0x0AB232D0
psd3_add = 0x0AB232D8

state.memory.store(psd0_add,psd0)#把位向量存入内存
state.memory.store(psd1_add,psd1)
state.memory.store(psd2_add,psd2)
state.memory.store(psd3_add,psd3)

simulation = project.factory.simgr(state)

def good_add(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job.' in str(stdout_output)

def fail_add(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Try again.' in str(stdout_output)

simulation.explore(find=good_add,avoid=fail_add)

if simulation.found:
solution_state = simulation.found[0]
solution0 = solution_state.se.eval(psd0)
solution1 = solution_state.se.eval(psd1)
solution2 = solution_state.se.eval(psd2)
solution3 = solution_state.se.eval(psd3)
solution = ' '.join(map('{:x}'.format, [ solution0, solution1,solution2,solution3 ]))
print(solution)
else:
raise Exception('Noooooooo!')

if __name__ == '__main__':
main(sys.argv)

1
2
3
4
5
6
7
8
9
10
11
12
WARNING | 2022-03-12 20:06:00,666 | angr.sim_state | Unused keyword arguments passed to SimState: add
WARNING | 2022-03-12 20:06:00,673 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-12 20:06:00,674 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-12 20:06:00,674 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-12 20:06:00,674 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-12 20:06:00,674 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-12 20:06:00,674 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fff0000 with 4 unconstrained bytes referenced from 0x8048432 (_start+0x2 in 05_angr_symbolic_memory (0x8048432))
WARNING | 2022-03-12 20:06:00,675 | angr.storage.memory_mixins.default_filler_mixin | Filling register eax with 4 unconstrained bytes referenced from 0x8048438 (_start+0x8 in 05_angr_symbolic_memory (0x8048438))
WARNING | 2022-03-12 20:06:00,676 | angr.storage.memory_mixins.default_filler_mixin | Filling register edx with 4 unconstrained bytes referenced from 0x804843a (_start+0xa in 05_angr_symbolic_memory (0x804843a))
WARNING | 2022-03-12 20:06:00,746 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x80486a1 (__libc_csu_init+0x1 in 05_angr_symbolic_memory (0x80486a1))
CRITICAL | 2022-03-12 20:06:05,988 | angr.sim_state | The name state.se is deprecated; please use state.solver.
0 0 0 0

06_angr_symbolic_dynamic_memory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+Ch] [ebp-Ch]

buffer0 = (char *)malloc(9u);
buffer1 = (char *)malloc(9u);
memset(buffer0, 0, 9u);
memset(buffer1, 0, 9u);
printf("Enter the password: ");
__isoc99_scanf("%8s %8s", buffer0, buffer1);
for ( i = 0; i <= 7; ++i )
{
buffer0[i] = complex_function(buffer0[i], i);
buffer1[i] = complex_function(buffer1[i], i + 32);
}
if ( !strncmp(buffer0, "OSIWHBXI", 8u) && !strncmp(buffer1, "FOQVSBZB", 8u) )
puts("Good Job.");
else
puts("Try again.");
free(buffer0);
free(buffer1);
return 0;
}

这次scanf() 有两个输入参数,数据保存的位置是通过全局变量的char* 指针来保存到buffer 中,大小为8 字节.我们主要是对buffer两个内存进行求解。我们如何将两块动态申请来的内存符号化,malloc申请的空间是动态的,但存放malloc的buffer是再bss段,属于静态,我们选择伪造指针使其指向一片可写的内存,将内存符号化

image-20220313151556700

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
38
import sys
import angr
import claripy
from operator import is_

def main():
path = '../solutions/06_angr_symbolic_dynamic_memory/06_angr_symbolic_dynamic_memory'
project = angr.Project(path)

start_address = 0x080486AF
state = project.factory.blank_state(addr=start_address)

psd0 = claripy.BVS('psd0',64)
psd1 = claripy.BVS('psd1',64)
fake_address0 = 0x0A2DEF30# 伪造malloc得来的内存,在bss上随便找的
pointer_to_address0 = 0x0A2DEF74# 指向伪造内存的指针
state.memory.store(pointer_to_address0,fake_address0,endness=project.arch.memory_endness)# 将指针指向伪造的内存
fake_address1 = 0x0A2DEF40
pointer_to_address1 = 0x0A2DEF7C
state.memory.store(pointer_to_address1,fake_address1,endness=project.arch.memory_endness)
state.memory.store(fake_address0,psd0)# 将伪造的内存符号化
state.memory.store(fake_address1,psd1)
simulation = project.factory.simgr(state)
simulation.explore(find=0x0804877A,avoid=0x08048768)

if simulation.found:
solution_state = simulation.found[0]
solution0 = solution_state.se.eval(psd0)
solution1 = solution_state.se.eval(psd1)
solution = ' '.join(map('{:x}'.format,[solution0,solution1]))
print(solution)
else:
raise Exception('Nooooooooo!')

if __name__ == '__main__':
main()


1
2
3
4
5
6
7
8
9
10
WARNING | 2022-03-13 15:07:11,666 | angr.storage.memory_mixins.bvv_conversion_mixin | Unknown size for memory data 0xa2def30. Default to arch.bits.
WARNING | 2022-03-13 15:07:11,667 | angr.storage.memory_mixins.bvv_conversion_mixin | Unknown size for memory data 0xa2def40. Default to arch.bits.
WARNING | 2022-03-13 15:07:11,672 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-13 15:07:11,672 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-13 15:07:11,672 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-13 15:07:11,672 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-13 15:07:11,672 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-13 15:07:11,672 | angr.storage.memory_mixins.default_filler_mixin | Filling register ebp with 4 unconstrained bytes referenced from 0x80486af (main+0x8c in 06_angr_symbolic_dynamic_memory (0x80486af))
CRITICAL | 2022-03-13 15:07:15,521 | angr.sim_state | The name state.se is deprecated; please use state.solver.
4f46494a484f5856 46425149534f5a4f

这节学到了符号化申请动态内存,通过伪造内存方式:

1
2
initial_state.memory.store(buffer0_addr, fake0_addr, endness=project.arch.memory_endness) # 将指针指向伪造的内存
initial_state.memory.store(fake0_addr, password0) # 将伪造的内存符号化

endness的参数是小端写入,因为angr默认大端。

07_angr_symbolic_file

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
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [esp-14h] [ebp-30h]
int v4; // [esp-10h] [ebp-2Ch]
int v5; // [esp-Ch] [ebp-28h]
int v6; // [esp-8h] [ebp-24h]
int v7; // [esp-4h] [ebp-20h]
int v8; // [esp+0h] [ebp-1Ch]
int i; // [esp+0h] [ebp-1Ch]

memset(buffer, 0, sizeof(buffer));
printf("Enter the password: ");
__isoc99_scanf("%64s", buffer, v3, v4, v5, v6, v7, v8);
ignore_me((int)buffer, 0x40u);
memset(buffer, 0, sizeof(buffer));
fp = fopen("FOQVSBZB.txt", "rb");
fread(buffer, 1u, 0x40u, fp);
fclose(fp);
unlink("FOQVSBZB.txt");
for ( i = 0; i <= 7; ++i )
*(_BYTE *)(i + 134520992) = complex_function(*(char *)(i + 134520992), i);
if ( strcmp(buffer, "OSIWHBXI") )
{
puts("Try again.");
exit(1);
}
puts("Good Job.");
exit(0);
}

这个是将输入写入文件,然后再打开文件进行加密

所以要构建文件。

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
38
39
40
41
import sys
import claripy
import angr
import binascii
from libnum import n2s
def main():
path = '../solutions/07_angr_symbolic_file/07_angr_symbolic_file'
project = angr.Project(path)

start_address = 0x080488BC
initial_state = project.factory.blank_state(add=start_address)

filename = 'FOQVSBZB.txt'
symbolic_file_size_bytes = 0x40#64位

psd = claripy.BVS('psd',symbolic_file_size_bytes * 8)
psd_file = angr.SimFile(filename, content=psd, size=symbolic_file_size_bytes) # 符号化文件

initial_state = project.factory.blank_state(addr=start_address, fs={filename: psd_file}) # 再初始状态中添加一个虚拟的文件系统
simulation = project.factory.simgr(initial_state)
def good_job(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())

return 'Good Job' in str(stdout_output)

def try_again(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())

return 'Try again' in str(stdout_output)

simulation.explore(find=good_job,avoid=try_again)
if simulation.found:
solution_state = simulation.found[0]
solution = n2s(solution_state.solver.eval(psd))
print(solution)
else:
raise Exception('Nooooooo!!!')

if __name__ == '__main__':
main()

1
2
3
4
5
6
7
8
WARNING | 2022-03-13 15:50:33,858 | angr.sim_state | Unused keyword arguments passed to SimState: add
WARNING | 2022-03-13 15:50:33,908 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-13 15:50:33,909 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-13 15:50:33,909 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-13 15:50:33,909 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-13 15:50:33,909 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-13 15:50:33,909 | angr.storage.memory_mixins.default_filler_mixin | Filling register ebp with 4 unconstrained bytes referenced from 0x8048922 (main+0xc4 in 07_angr_symbolic_file (0x8048922))
OBAXRUZT

总结:

1
2
3
angr.storage.SimFile(文件名,文件内容, size = 文件大小) => 创建一个模拟文件,当有被执行的程序fopen 打开文件时,我们可以控制其里面的内容

initial_state.posix.fs => 状态上下文的文件系统对象

要注意点,但我们创建符号good_job其参数是state,所以我们在创建项目时,不能用state,可以用initial_state

08_angr_constraints

这道题的特点就是会一个一个字符比较,所以不能用之前的方法,否则会有2的16次方中可能,会爆炸的,我们要做的就是符号化buffer,然后进行加密加密后获得控制权,从而检查psd是否与对比的一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+Ch] [ebp-Ch]

qmemcpy(&password, "OSIWHBXIFOQVSBZB", 16);
memset(&buffer, 0, 0x11u);
printf("Enter the password: ");
__isoc99_scanf("%16s", &buffer);
for ( i = 0; i <= 15; ++i )
*(_BYTE *)(i + 134520896) = complex_function(*(char *)(i + 134520896), 15 - i);
if ( check_equals_OSIWHBXIFOQVSBZB(&buffer, 16) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

给出脚本:

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
import angr
import sys
import claripy
from libnum import n2s
def main():
path = '../solutions/08_angr_constraints/08_angr_constraints'
project = angr.Project(path)
start_add = 0x0804863C #scanf后面
initial_state = project.factory.blank_state(add=start_add)
buffer = claripy.BVS('buffer',0x10*8)#buffer的大小是0x10 字节,也就是0x10 * 8 比特
buffer_address = 0x0804A040
initial_state.memory.store(buffer_address,buffer)#buffer 是全局变量,地址是0x804A040
simulation = project.factory.simgr(initial_state)
address_to_check_constraint = 0x08048683
simulation.explore(find=address_to_check_constraint)# compilex_function() 计算结束位置
if simulation.found:
solution_state = simulation.found[0]
constrained_parameter_address = 0x0804A040 # 计算约束的内存位置
constrained_parameter_size_bytes = 0x10 # 计算约束的内存大小
constrained_parameter_bitvector = solution_state.memory.load( constrained_parameter_address,constrained_parameter_size_bytes) # 加载内存

constrained_parameter_desired_value = "OSIWHBXIFOQVSBZB"# Key-String
solution_state.add_constraints(constrained_parameter_bitvector == constrained_parameter_desired_value )# 添加约束
solution = solution_state.se.eval(buffer)
print(n2s(solution))
else:
raise Exception('nooooooooo!')

if __name__ == '__main__':
main()

学到:

1
2
3
solution_state.memory.load(内存地址,内存大小) => 加载内存

solution_state.add_constraints(约束条件) => 添加约束条件

09_angr_hooks

这个题主要是对比的时候在遍历分支的时候会用很长时间,我们直接hook掉,然后替换成我们自己对比函数就行

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
38
39
import sys
import claripy
import angr
def main():
path = '../solutions/09_angr_hooks/09_angr_hooks'
project = angr.Project(path)
initial_state = project.factory.entry_state()

check_equals = 0x080486CA
instruction_to_skip_lenth = 5
@project.hook(check_equals, length=instruction_to_skip_lenth)
def skip_check_equals(state):
user_input_buffer_addr = 0x0804A044#buffer地址
user_input_buffer_lenth = 16

user_input_string = state.memory.laod( user_input_buffer_addr,user_input_buffer_lenth)
check_against_string = 'OSIWHBXIFOQVSBZB'
state.regs.eax = claripy.If(user_input_string == check_against_string,claripy.BVV(1,32),claripy.BVV(0,32))
simulation = project.factory.simgr(initial_state)

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

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

simulation.explore(find=is_successful, avoid=should_abort) # Try Explore Execute Path

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

if __name__ == '__main__':
main()

上面脚本不如下面脚本:

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
import sys
import claripy
import angr
def main():
path = '../solutions/09_angr_hooks/09_angr_hooks'
project = angr.Project(path)

initial_state = project.factory.entry_state()

class ReplacementCheckEquals(angr.SimProcedure):
def run(self, check_data_address, check_data_length):
check_input_string = self.state.memory.load(check_data_address,check_data_length)
check_against_string = 'OSIWHBXIFOQVSBZB'

return claripy.If(check_input_string == check_against_string,claripy.BVV(1,32),claripy.BVV(0,32))

check_equals_symbol = 'check_equals_OSIWHBXIFOQVSBZB'
project.hook_symbol(check_equals_symbol,ReplacementCheckEquals())

simulation = project.factory.simgr(initial_state)

def good_job(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job' in str(stdout_output)

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

simulation.explore(find=good_job,avoid=should_abort)
if simulation.found:
solution_state = simulation.found[0]

solution = solution_state.posix.dumps(sys.stdin.fileno())
print(solution)
if __name__ == '__main__':
main()
1
2
3
4
5
6
7
8
WARNING | 2022-03-14 15:40:43,538 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-14 15:40:43,538 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-14 15:40:43,538 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-14 15:40:43,538 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-14 15:40:43,538 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-14 15:40:43,539 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x80487a1 (__libc_csu_init+0x1 in 09_angr_hooks (0x80487a1))
WARNING | 2022-03-14 15:40:46,867 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
b'QREPXOHPJPOQKQLKNOBMULEMGMLNHNIH'

总结:

1
2
3
4
5
6
7
8
9
Hook回调函数格式:

@project.hook(Hook地址,执行完Hook函数后指令往后跳转n字节) def skip_check_equals_(state):

pass

claripy.If(条件,条件为True时的返回值,条件为False时的返回值) => 创建条件判断

claripy.BVV(值,值大小) => 创建一个数值

10_angr_simprocedures

还是一样,先输入flag然后循环运算,接下来函数中对比。逐字节比较太麻烦,我们仍需对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+20h] [ebp-28h]
char s[17]; // [esp+2Bh] [ebp-1Dh] BYREF
unsigned int v6; // [esp+3Ch] [ebp-Ch]

v6 = __readgsdword(0x14u);
memcpy(&password, "OSIWHBXIFOQVSBZB", 0x10u);
memset(s, 0, sizeof(s));
printf("Enter the password: ");
__isoc99_scanf("%16s", s);
for ( i = 0; i <= 15; ++i )
s[i] = complex_function(s[i], 18 - i);
if ( check_equals_OSIWHBXIFOQVSBZB(s, 16) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

本题跟9题的区别就在于,本题call equal指令太多,不像9题只有一个,所以我们需要多个hook

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
import sys
import claripy
import angr
def main():
path = '../solutions/10_angr_simprocedures/10_angr_simprocedures'
project = angr.Project(path)

initial_state = project.factory.entry_state()

class ReplacementCheckEquals(angr.SimProcedure):
def run(self, check_data_address, check_data_length):
check_input_string = self.state.memory.load(check_data_address,check_data_length)
check_against_string = 'OSIWHBXIFOQVSBZB'

return claripy.If(check_input_string == check_against_string,claripy.BVV(1,32),claripy.BVV(0,32))

check_equals_symbol = 'check_equals_OSIWHBXIFOQVSBZB'
project.hook_symbol(check_equals_symbol,ReplacementCheckEquals())

simulation = project.factory.simgr(initial_state)

def good_job(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job' in str(stdout_output)

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

simulation.explore(find=good_job,avoid=should_abort)
if simulation.found:
solution_state = simulation.found[0]

solution = solution_state.posix.dumps(sys.stdin.fileno())
print(solution)
if __name__ == '__main__':
main()
1
2
3
4
5
6
7
8
WARNING | 2022-03-14 15:02:40,607 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-14 15:02:40,607 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-14 15:02:40,607 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-14 15:02:40,607 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-14 15:02:40,607 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-14 15:02:40,607 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x804a9d1 (__libc_csu_init+0x1 in 10_angr_simprocedures (0x804a9d1))
WARNING | 2022-03-14 15:02:43,850 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
b'MTMDRONBBNSAAMNS'

这个题hook整个函数。采用SimProcedure类

1
2
3
4
5
6
7
8
9
10
11
Hook 回调函数格式:

class ReplacementCheckEquals(angr.SimProcedure):

def run(self, Hook的函数参数列表):

….

return 函数返回值 # 如果是void函数可以省略

project.hook_symbol(要Hook的函数名,SimProcedure类实例)

通过这个题,我在想上个题是否也能用这个回调函数呢,这个脚本会省去很多事,成功了!

11_angr_sim_scanf

本题加密的是对比数据,加密完再输入,然后对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+20h] [ebp-28h]
char s[20]; // [esp+28h] [ebp-20h] BYREF
unsigned int v7; // [esp+3Ch] [ebp-Ch]

v7 = __readgsdword(0x14u);
memset(s, 0, sizeof(s));
qmemcpy(s, "LOGMHXHI", 8);
for ( i = 0; i <= 7; ++i )
s[i] = complex_function(s[i], i);
printf("Enter the password: ");
__isoc99_scanf("%u %u", buffer0, buffer1);
if ( !strncmp(buffer0, s, 4u) && !strncmp(buffer1, &s[4], 4u) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

这道题是让我们模拟scanf

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
38
39
40
41
42
43
import sys
import angr
import claripy

def main():
path = '../solutions/11_angr_sim_scanf/11_angr_sim_scanf'
project = angr.Project(path)

initial_state = project.factory.entry_state()

class ReplacementScanf(angr.SimProcedure):
def run(self,format_string,scanf0_address,scanf1_address):
scanf0 = claripy.BVS('scanf0', 32)
scanf1 = claripy.BVS('scanf1', 32)

self.state.memory.store(scanf0_address,scanf0,endness=project.arch.memory_endness)
self.state.memory.store(scanf1_address,scanf1,endness=project.arch.memory_endness)

self.state.globals['solution0'] = scanf0
self.state.globals['solution1'] = scanf1

scanf_symbol = '__isoc99_scanf'
project.hook_symbol(scanf_symbol, ReplacementScanf())
simulation = project.factory.simgr(initial_state)
def good_job(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job.' in str(stdout_output)
def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Try again' in str(stdout_output)

simulation.explore(find=good_job,avoid=should_abort)
if simulation.found:
solution_state = simulation.found[0]
store_solution0 = solution_state.globals['solution0']
store_solution1 = solution_state.globals['solution1']
solution0 = solution_state.se.eval(store_solution0)
solution1 = solution_state.se.eval(store_solution1)
print(solution0,solution1)
if __name__ =='__main__':
main()


1
2
3
4
5
6
7
8
9
10
WARNING | 2022-03-14 16:09:33,831 | angr.project | Address is already hooked, during hook(0x81513a0, <SimProcedure ReplacementScanf>). Re-hooking.
WARNING | 2022-03-14 16:09:33,903 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-14 16:09:33,903 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-14 16:09:33,903 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-14 16:09:33,903 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-14 16:09:33,903 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-14 16:09:33,903 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x804fce1 (__libc_csu_init+0x1 in 11_angr_sim_scanf (0x804fce1))
WARNING | 2022-03-14 16:09:34,137 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeff40 with 4 unconstrained bytes referenced from 0x8187170 (strncmp+0x0 in libc.so.6 (0x87170))
CRITICAL | 2022-03-14 16:09:34,334 | angr.sim_state | The name state.se is deprecated; please use state.solver.
1447907916 1146768724

这个题学到了构造scanf的hook:

1
2
3
4
5
#将位向量储存到当前状态并且获取位向量的方法
self.state.globals['solution0'] = scanf0
#保存当前状态
solution0 = solution_state.globals['solution0']
#去出scanf

12_angr_veritesting

如果说这个题跟第一题有什么区别的话,就是这个输入32位,很容易爆炸,所以有veritesting参数来表示是否合并路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys
import angr
def main():
path = '../solutions/12_angr_veritesting/12_angr_veritesting'
project = angr.Project(path)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state,veritesting = True)
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job.' in str(stdout_output) # :boolean
def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Try again.' in str(stdout_output)

simulation.explore(find=is_successful,avoid=should_abort)
if simulation.found:
solution = simulation.found[0]
print(solution.posix.dumps(sys.stdin.fileno()))
if __name__ =='__main__':
main()
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
WARNING | 2022-03-14 16:30:57,745 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-14 16:30:57,745 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-14 16:30:57,745 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-14 16:30:57,745 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-14 16:30:57,745 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-14 16:30:57,746 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x80486e1 (__libc_csu_init+0x1 in 12_angr_veritesting (0x80486e1))
WARNING | 2022-03-14 16:30:57,757 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:57,758 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
Deprecation warning: Use self.model.get_any_node() instead of get_any_node
WARNING | 2022-03-14 16:30:57,789 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:57,790 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:57,852 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:57,853 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:57,887 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:57,887 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,001 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,001 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,098 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,099 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,209 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,209 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:30:58,322 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:30:58,564 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:30:58,807 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:30:59,033 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:30:59,259 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:30:59,507 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:30:59,751 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:00,001 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:00,253 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:00,526 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:00,801 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:01,072 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:01,352 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:01,645 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:01,934 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:02,240 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:02,541 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:02,851 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:03,179 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:03,504 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:03,826 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:04,170 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:04,519 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:04,869 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:05,314 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:05,676 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:06,060 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:06,456 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:06,859 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:07,269 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:07,704 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:31:08,188 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
b'YNCRGVKZODSHWLAPETIXMBQFUJYNCRGV'

学习了如何自动合并路径:

1
simulation = project.factory.simgr(initial_state, veritesting=True) 

13_angr_static_binary

看起来很简单,用第一问的脚本就行了,实际不行,因为这个是用静态链接编译的,我们还要实现或者引用一些函数的hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [esp+1Ch] [ebp-3Ch]
int j; // [esp+20h] [ebp-38h]
char v6[20]; // [esp+24h] [ebp-34h] BYREF
char v7[20]; // [esp+38h] [ebp-20h] BYREF
unsigned int v8; // [esp+4Ch] [ebp-Ch]

v8 = __readgsdword(0x14u);
for ( i = 0; i <= 19; ++i )
v7[i] = 0;
qmemcpy(v7, "ELZXQOOQ", 8);
printf("Enter the password: ");
_isoc99_scanf("%8s", v6);
for ( j = 0; j <= 7; ++j )
v6[j] = complex_function(v6[j], j);
if ( j_strcmp_ifunc(v6, v7) )
puts("Try again.");
else
puts("Good Job.");
return 0;
}
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
import angr
import sys

def main():
path = '../solutions/13_angr_static_binary/13_angr_static_binary'
project = angr.Project(path)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state,veritesting = True)

project.hook(0x0804FAB0,angr.SIM_PROCEDURES['libc']['printf']())
project.hook(0x0804FB10,angr.SIM_PROCEDURES['libc']['scanf']())
project.hook(0x080503F0,angr.SIM_PROCEDURES['libc']['puts']())
project.hook(0x08048D60,angr.SIM_PROCEDURES['glibc']['__libc_start_main']())
def is_successful(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job.' in str(stdout_output) # :boolean
def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Try again.' in str(stdout_output)

simulation.explore(find=is_successful,avoid=should_abort)
if simulation.found:
solution_state = simulation.found[0]
print(solution_state.posix.dumps(sys.stdin.fileno()))
if __name__ == '__main__':
main()
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
WARNING | 2022-03-14 16:55:19,180 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-14 16:55:19,180 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-14 16:55:19,180 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-14 16:55:19,180 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-14 16:55:19,181 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-14 16:55:19,181 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x80497b1 (__libc_csu_init+0x1 in 13_angr_static_binary (0x80497b1))
WARNING | 2022-03-14 16:55:19,185 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,186 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
Deprecation warning: Use self.model.get_any_node() instead of get_any_node
WARNING | 2022-03-14 16:55:19,255 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,255 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,279 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,279 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,323 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,325 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,406 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,406 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,422 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,422 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,502 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,502 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,528 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,528 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,566 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:19,566 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:20,020 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:20,021 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:20,310 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:20,311 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:20,391 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:20,392 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:21,303 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:21,304 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:24,416 | angr.sim_manager | Cannot find states with common history line to merge. Fall back to the naive merging strategy and merge all states.
WARNING | 2022-03-14 16:55:25,412 | angr.storage.memory_mixins.default_filler_mixin | Filling register es with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
WARNING | 2022-03-14 16:55:25,412 | angr.storage.memory_mixins.default_filler_mixin | Filling register gs with 4 unconstrained bytes referenced from 0x0 (not part of a loaded object)
b'EADQYLAR'

我们学到了获取angr内部系统函数:

1
angr.SIM_PROCEDURES[ 系统库名 ] [ 系统函数名 ] () => 获取Angr 内部实现的系统函数

14_angr_shared_library

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[16]; // [esp+1Ch] [ebp-1Ch] BYREF
unsigned int v5; // [esp+2Ch] [ebp-Ch]

v5 = __readgsdword(0x14u);
memset(s, 0, sizeof(s));
printf("Enter the password: ");
__isoc99_scanf("%8s", s);
if ( validate(s, 8) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

好像很简单,但我们发现validate函数在另一个so文件,该题考的是动态链接的符号执行,我们只要搞出validate的符号执行就ok

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys
import angr
import claripy

def main():
path = '../solutions/14_angr_shared_library/lib14_angr_shared_library.so'
base = 0x40000000#随意
project = angr.Project(path,load_options={'main_opts' : {'custom_base_addr' : base}})
buffer_pointer = claripy.BVV(0x30000000,32)#创建buffer指针
validate_function_address = base + 0x670 #在该文件中的调用地址
initial_state = project.factory.call_state(validate_function_address,buffer_pointer,claripy.BVV(8,32))
# 调用validate_function,因为函数声明validata_function(buffer_point,buffer_length) ,所以我们构造出调用validata_function(0x3000000,0x8) .
password = claripy.BVS('password', 64)

initial_state.memory.store(buffer_pointer,password)
simulation = project.factory.simgr(initial_state)
simulation.explore(find=base+0x71C)# 执行到validate 函数的RETN 指令
if simulation.found:
solution_state = simulation.found[0]
solution_state.add_constraints(solution_state.regs.eax !=0)
solution = solution_state.se.eval(password)
print(solution)
if __name__ == '__main__':
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CRITICAL | 2022-03-14 17:38:36,605 | cle.backends | Deprecation warning: the custom_base_addr parameter has been renamed to base_addr
WARNING | 2022-03-14 17:38:36,862 | angr.calling_conventions | Guessing call prototype. Please specify prototype.
WARNING | 2022-03-14 17:38:36,868 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-14 17:38:36,869 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-14 17:38:36,869 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-14 17:38:36,869 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-14 17:38:36,869 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-14 17:38:36,869 | angr.storage.memory_mixins.default_filler_mixin | Filling register ebp with 4 unconstrained bytes referenced from 0x40000670 (validate+0x0 in lib14_angr_shared_library.so (0x670))
WARNING | 2022-03-14 17:38:36,870 | angr.storage.memory_mixins.default_filler_mixin | Filling register ebx with 4 unconstrained bytes referenced from 0x40000673 (validate+0x3 in lib14_angr_shared_library.so (0x673))
WARNING | 2022-03-14 17:38:37,842 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x30000008 with 121 unconstrained bytes referenced from 0x40186b80 (strcmp+0x0 in libc.so.6 (0x86b80))
WARNING | 2022-03-14 17:38:37,911 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffeffe8 with 4 unconstrained bytes referenced from 0x40186b80 (strcmp+0x0 in libc.so.6 (0x86b80))
WARNING | 2022-03-14 17:38:37,911 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fff0000 with 77 unconstrained bytes referenced from 0x40186b80 (strcmp+0x0 in libc.so.6 (0x86b80))
CRITICAL | 2022-03-14 17:38:38,105 | angr.sim_state | The name state.se is deprecated; please use state.solver.
6076275416825026394

学习到了:

1
2
3
4
5
6
如何加载共享库
base = 0x40000000#随意
project = angr.Project(path,load_options={'main_opts' : {'custom_base_addr' : base}})
initial_state = project.factory.call_state(validate_function_address,buffer_pointer,claripy.BVV(8,32))
# 构造指针给函数使用.

15_angr_arbitrary_read

当if成立,s输出,以为会输出tryagain,但v4要写入20字节,就会有溢出,因为s到v4只有16字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4; // [esp+Ch] [ebp-1Ch] BYREF
char *s; // [esp+1Ch] [ebp-Ch]

s = try_again;
printf("Enter the password: ");
__isoc99_scanf("%u %20s", &key, &v4);
if ( key == 2358019 )
puts(s);
else
puts(try_again);
return 0;
}

脚本如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import sys
import angr
import claripy
def main():
path = '../solutions/15_angr_arbitrary_read/15_angr_arbitrary_read'
project = angr.Project(path)

initial_state = project.factory.entry_state()

class ReplacementScanf(angr.SimProcedure):# 实现Scanf Hook 函数

def run(self,format_string, check_key_address,input_buffer_address):
scanf0 = claripy.BVS('scanf0',32)#check_key
scanf1 = claripy.BVS('scanf1',160)#inputbuffer

for char in scanf1.chop(bits=8):
self.state.add_constraints(char >= '0', char <= 'z')# 对input_buffer 的输入约束

self.state.memory.store(check_key_address,scanf0 ,endness =project.arch.memory_endness)# 保存求解变量到指定的内存中

self.state.memory.store(input_buffer_address,scanf1 ,endness =project.arch.memory_endness)

self.state.globals['solution0'] = scanf0# 保存这两个变量到state 中,后续求解需要用到
self.state.globals['solution1'] = scanf1

scanf_symbol = '__isoc99_scanf'
project.hook_symbol(scanf_symbol,ReplacementScanf())
def check_puts(state):
puts_parameter = state.memory.load(state.regs.esp + 4,4,endness=project.arch.memory_endness)

if state.se.symbolic(puts_parameter):
good_job_string_address = 0x08048562#利用try again的函数调用
copied_state = state.copy() # 复制执行状态上下文进行约束求解,不影响原理的执行上下文
copied_state.add_constraints(puts_parameter == good_job_string_address)# puts 的参数地址是否可以被指定为 0x08048562 ,如果可以的话,那就证明这个值是可控的

if copied_state.satisfiable():# 判断添加了上面这个约束是否有解
state.add_constrains(puts_parameter == good_job_string_address) # 如果有解的话就保存到我们执行的那个状态对象
return True
else:
return False
else:
return False

simulation = project.factory.simgr(initial_state)
def is_successful(state):
puts_address = 0x0804854F# 当程序执行到puts() 函数时,我们就认为路径探索到了这里,然后再去通过check_puts() 判断这里是否存在漏洞,告诉Angr这是不是我们需要找的那条执行路径

if state.addr == puts_address:
return check_puts(state)
else:
return False
simulation.explore(find=is_successful)
if simulation.found:
solution_state = simulation.found[0]
solution0 = solution_state.se.eval(solution_state.globals['solution0'])
solution1 = solution_state.se.eval(solution_state.globals['solution1'],cast_to=bytes)
print(solution0,solution1)

if __name__ == '__main__':
main()
1
2
3
4
5
state.copy() => 复制状态上下文

state.satisfiable() => 判断当前的所有约束是否有解

solution_state.se.eval(求解变量,cast_to=bytes) => 序列化变量内容为字符串

16_angr_arbitrary_write

这个题很明显,password是不等于NEDVTNOP,所以我们可以用s溢出覆盖dest的值,使其指向password,这样就能修改其内容了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[16]; // [esp+Ch] [ebp-1Ch] BYREF
char *dest; // [esp+1Ch] [ebp-Ch]

dest = unimportant_buffer;
memset(s, 0, sizeof(s));
strncpy(password_buffer, "PASSWORD", 0xCu);
printf("Enter the password: ");
__isoc99_scanf("%u %20s", &key, s);
if ( key == 6712341 )
strncpy(dest, s, 0x10u);
else
strncpy(unimportant_buffer, s, 0x10u);
if ( !strncmp(password_buffer, "NEDVTNOP", 8u) )
puts("Good Job.");
else
puts("Try again.");
return 0;
}

我们输入20个字节是正好覆盖s的16个字节+的dest的字节的

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import sys
import angr
import claripy

def main():
path = '../solutions/16_angr_arbitrary_write/16_angr_arbitrary_write'
project = angr.Project(path)
initial_state = project.factory.entry_state()

class ReplacementScanf(angr.SimProcedure):
def run(self,format_string,check_key,input_buffer):
scanf0 = claripy.BVS('scanf0',32)
scanf1 = claripy.BVS('scanf1',160)

for char in scanf1.chop(bits=8):
self.state.add_constraints(char >= 'a',char <= 'z')

self.state.memory.store(check_key,scanf0,endness=project.arch.memory_endness)
self.state.memory.store(input_buffer,scanf1,endness=project.arch.memory_endness)

self.state.globals['solution0'] = scanf0
self.state.globals['solution1'] = scanf1

scanf_symbol = '__isoc99_scanf'
project.hook_symbol(scanf_symbol,ReplacementScanf())
def check_strnpy(state):
strncpy_dest = state.memory.load(state.regs.esp + 4,4,endness=project.arch.memory_endness)
strncpy_src = state.memory.load(state.regs.esp + 8, 4, endness=project.arch.memory_endness)
strncpy_len = state.memory.load(state.regs.esp + 12, 4, endness=project.arch.memory_endness)
src_contents = state.memory.load(strncpy_src, strncpy_len)
# 因为参数中只保存了地址,我们需要根据这个地址去获取内容
if state.se.symbolic(strncpy_dest) and state.se.symbolic(src_contents):
# 判断dest 和src 的内容是不是符号化对象
if state.satisfiable(extra_constraints=(src_contents[-1:-64] == 'NEDVTNOP',strncpy_dest == 0x4D43523C)):
# 尝试求解,其中strncpy_dest == 0x4D43523C 的意思是判断dest 是否可控为password 的地址;src_contents[ -1 : -64 ] == 'KZYRKMKE' 是判断input_buffer 的内容是否可控为'KZYRKMKE' ,因为这块内存是倒序,所以需要通过[ -1 : -64 ] 倒转(contentes 的内容是比特,获取8 字节的大小为:8*8 = 64),然后判断该值是否为字符串'KZYRKMKE'
state.add_constraints(src_contents[ -1 : -64 ] == 'NEDVTNOP',strncpy_dest == 0x4D43523C)
return True
else:
return False
else:
return False
simulation = project.factory.simgr(initial_state)
def good_job(state):
strncpy_address = 0x0804860D
if state.addr == strncpy_address:
return check_strnpy(state)
else:
return False
simulation.explore(find=good_job)
if simulation.found:
solution_state = simulation.found[0]
solution0 = solution_state.se.eval(solution_state.globals['solution0'])
solution1 = solution_state.se.eval(solution_state.globals['solution1'],cast_to=bytes)
print(solution0,solution1)
if __name__ =='__main__':
main()

总结:state.satisfiable(extra_constraints=(条件1,条件2)) => 合并多个条件计算是否存在满足约束的解(注意两个或多个条件之间是And 合并判断,不是Or )

17_angr_arbitrary_jump

最后一题,在read_print中检查返回地址是否是godjob

1
2
3
4
5
6
7
int __cdecl main(int argc, const char **argv, const char **envp)
{
printf("Enter the password: ");
read_input();
puts("Try again.");
return 0;
}
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import angr
import claripy

def main():
binary_path = '../solutions/17_angr_arbitrary_jump/17_angr_arbitrary_jump'
project = angr.Project(binary_path)

initial_state = project.factory.entry_state()
simulation = project.factory.simgr(
initial_state,
save_unconstrained=True,
stashes={
'active' : [initial_state],
'unconstrained' : [],
'found' : [],
'not_needed' : []
}
)

class ReplacementScanf(angr.SimProcedure):

def run(self, fmt, string_addr):
exploit = claripy.BVS('exploit', 8 * 64)

for char in exploit.chop(bits=8):
self.state.add_constraints(char >= '0', char <= 'z')

exploit_addr = string_addr
self.state.memory.store(exploit_addr, exploit)

self.state.globals['solution'] = exploit

scanf_symbol = '__isoc99_scanf'
project.hook_symbol(scanf_symbol, ReplacementScanf())

while (simulation.active or simulation.unconstrained) and (not simulation.found):
for unconstrained_state in simulation.unconstrained:
def should_move(s):
return s is unconstrained_state

simulation.move('unconstrained', 'found', filter_func=should_move)


simulation.step()

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

solution_state.add_constraints(solution_state.regs.eip == 0x4D435250)

solution = solution_state.se.eval(solution_state.globals['solution'],cast_to = bytes)
print(solution)
else:
raise Exception('Could not find the solution')


if __name__ == '__main__':
main()

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
WARNING | 2022-03-15 13:47:38,088 | angr.project | Address is already hooked, during hook(0x4d5513a0, <SimProcedure ReplacementScanf>). Re-hooking.
WARNING | 2022-03-15 13:47:38,226 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory or registers with an unspecified value. This could indicate unwanted behavior.
WARNING | 2022-03-15 13:47:38,226 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2022-03-15 13:47:38,226 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2022-03-15 13:47:38,226 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2022-03-15 13:47:38,226 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2022-03-15 13:47:38,226 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x4d4352e1 (__libc_csu_init+0x1 in 17_angr_arbitrary_jump (0x4d4352e1))
WARNING | 2022-03-15 13:47:38,229 | angr.storage.memory_mixins.default_filler_mixin | Filling register edi with 4 unconstrained bytes referenced from 0x4d4352e1 (__libc_csu_init+0x1 in 17_angr_arbitrary_jump (0x4d4352e1))
WARNING | 2022-03-15 13:47:38,340 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,340 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,341 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,342 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,343 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,344 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,345 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,346 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,347 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,348 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,349 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,350 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,350 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,350 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,350 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,350 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,350 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,351 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,351 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,351 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,351 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,351 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,351 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,352 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,353 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,354 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,354 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,354 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,354 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,393 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,394 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,394 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,394 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,394 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,394 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,395 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,396 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,397 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,398 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,399 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,400 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,401 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,402 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,403 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,404 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,405 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,406 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,407 | claripy.ast.bv | BVV value is being coerced from a unicode string, encoding as utf-8
WARNING | 2022-03-15 13:47:38,766 | angr.engines.successors | Exit state has over 256 possible solutions. Likely unconstrained; skipping. <BV32 Reverse(exploit_11_512[135:104])>
WARNING | 2022-03-15 13:47:39,144 | angr.engines.successors | Exit state has over 256 possible solutions. Likely unconstrained; skipping. <BV32 Reverse(exploit_12_512[135:104])>
CRITICAL | 2022-03-15 13:47:39,181 | angr.sim_state | The name state.se is deprecated; please use state.solver.
b'00000000000000000000000000000000000000000000000PRCM00@0000000000'

总结:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class ReplacementScanf(angr.SimProcedure):class ReplacementScanf(angr.SimProcedure):import angr
#导入文件
path = ''
#打开二进制文件
project = angr.Project(path)
#接下来两种选择
#第一种
initial_state = project.factory.entry_state()#直接创建空白的执行上下文环境
#第二种
start_address = xxxx
initial_state = project.factory.blank_state(addr=start_address)
#创建模拟器,第二个参数是指定是否合并路径,路径多会爆炸
simulation = project.factory.simgr(initial_state,veritesting = True)
#good和try有两种方法,第一个是找到call puts的地址不再说了
#第二种是进行函数定义
def is_successful(state):
#从输出中提取
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Good Job' in str(stdout_output) # :boolean
def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Try again' in str(stdout_output) # :boolean
#执行搜索路径(里面是要到达的地址)
simulation.explore(find=print_good_address,avoid=print_try_avoid)
#打印出结果,搜索结果的集合,simulation.found是python的list集合
if simulation.found:
solution_state = simulation.found[0]
#获取标准输入
print(solution_state.posix.dumps(sys.stdin.fileno()))

#寄存器类,比如输入了好几个参数,我们能从寄存器下手找到输入源
#创建求解变量
password0 = claripy.BVS('password0', password0_size_in_bits)
#告诉符号执行,执行的寄存器是什么
initial_state.regs.eax = password0
#在if中进行求解符号变量
solution0 = solution_state.se.eval(password0)
#栈类,如果结果保存在栈中
#将创建的变量从stack中取出来
initial_state.stack_push(password0)
#变量存在bss段,符号化内存
#第一个参数是变量的地址
initial_state.memory.store(password0_address, password0)
#数字字节顺序,可以表示为:project.arch.memory_endness
initial_state.memory.store(地址,数据,endness = 数据字节顺序) => 设置初始化内存数据
#有关文件就是第七题
#多分支比较,建立比较机制
#先在if里进行约束
constrained_parameter_address = 0x804A050 # 计算约束的内存位置
constrained_parameter_size_bytes = 0x10 # 计算约束的内存大小
constrained_parameter_bitvector = solution_state.memory.load( # 加载内存
constrained_parameter_address,
constrained_parameter_size_bytes
)
#再用下述的进行字符串比较
solution_state.memory.load(内存地址,内存大小) => 加载内存
solution_state.add_constraints(约束条件) => 添加约束条件
#hook的写法
#连个参数分别是,hook的地址,执行后往后跳过几个字节
@project.hook(check_equals_called_address, length=instruction_to_skip_length)
def skip_check_equals_(state):
加载内存
claripy.If(条件,条件为True时的返回值,条件为False时的返回值) => 创建条件判断
claripy.BVV(值,值大小) => 创建一个数值
#另一种常见hook方法,常见于想hook的函数太多,无法定位情况
class ReplacementCheckEquals(angr.SimProcedure):
def run(self, Hook的函数参数列表):
加载内存
return 用claripy.If对比来返回值# 如果是void函数可以省略
#hook的函数名是真实函数名,第二个参数是ReplacementCheckEquals()
project.hook_symbol(要Hook的函数名,SimProcedure类实例)
#scanf太多,hookscanf
class ReplacementScanf(angr.SimProcedure):
def run(self, format_string, scanf0_address, scanf1_address ):
#创建求解变量
scanf0 = claripy.BVS('scanf0', 4 * 8)
#初始化内存
self.state.memory.store(scanf0_address, scanf0, endness=project.arch.memory_endness)
#保存当前状态
self.state.globals['solution0'] = scanf0
project.hook_symbol(要Hook的函数名,SimProcedure类实例)
#用angr自带hook程序
#用在simgr后
project.hook(0x804ed40, angr.SIM_PROCEDURES['libc']['printf']())
angr.SIM_PROCEDURES[ 系统库名 ] [ 系统函数名 ] () => 获取Angr 内部实现的系统函数
#遇到函数是动态链接的
#现设基地址
base = 0x40000000(随便)
#我们的path是指那个so文件
project = angr.Project(path_to_binary, load_options={
'main_opts' : {
'custom_base_addr' : base
}
})
initial_state = project.factory.call_state(validate_function_address, buffer_pointer,claripy.BVV(8, 32)) # 调用validate_function,因为函数声明validata_function(buffer_point,buffer_length) ,所以我们构造出调用validata_function(0x3000000,0x8)
#对于溢出而覆盖的题
#下面是约束的写法
for char in scanf1.chop(bits=8):
self.state.add_constraints(char >= '0', char <= 'z') # 对input_buffer 的输入约束
#约束完,存入内存,获取想要的puts
def check_puts(state):
puts_parameter = state.memory.load(state.regs.esp + 4, 4, endness=project.arch.memory_endness)
#检查这个参数是否为符号化对象
if state.se.symbolic(puts_parameter):
#复制执行状态上下文进行约束求解,不影响原理的执行上下文
copied_state = state.copy()
if copied_state.satisfiable(): # 判断添加了上面这个约束是否有解
state.add_constraints(puts_parameter == good_job_string_address) # 如果有解的话就保存到我们执行的那个状态对象
return True
else:
return False
else:
return False
#序列化变量内容为字符串
solution_state.se.eval(求解变量,cast_to=bytes)
#合并多个条件计算是否存在满足约束的解(注意两个或多个条件之间是And 合并判断,不是Or )
state.satisfiable(extra_constraints=(条件1,条件2))