首页
社区
课程
招聘
[求助]关于angr学习使用中遇到的一些困惑
发表于: 2020-12-27 21:42 3734

[求助]关于angr学习使用中遇到的一些困惑

2020-12-27 21:42
3734

关于angr学习使用中的一些困惑

最近按照网上给的教程学习了一下angr,但是遇到了一些问题,按照教程的提示做却得不到争取的结果,查阅资料也没有得到可以调试angr的办法。

符号化寄存器

这一题的例子是angr-doc的example中的fauxware,其中的逻辑如下所示。

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)
{
  _BOOL4 v4; // [rsp+1Ch] [rbp-24h] BYREF
  char passwd[16]; // [rsp+20h] [rbp-20h] BYREF
  char buf[16]; // [rsp+30h] [rbp-10h] BYREF
 
  buf[8] = 0;
  passwd[8] = 0;
  puts("Username: ");
  read(0, buf, 8uLL);
  read(0, &v4, 1uLL);
  puts("Password: ");
  read(0, passwd, 8uLL);
  read(0, &v4, 1uLL);
  v4 = authenticate(buf, passwd);
  if ( !v4 )
    rejected(buf);
  return accepted(buf);
}

authenticate函数中是字符串比较函数,目标即使passwd与目标字符串相同,即可进入accepted函数打印字符串。

 

当我符号化usename、passwd栈区域的话,是可以成功探索到目标路径,并且求解处正确的passwd。

 

但是如下所示,我想通过直接符号化rdi、rsi寄存器,从地址0x4007AE来模拟执行程序,而不是通过符号化stack区来模拟构造输入时,虽然可以探索到目标路径,但是我求解出的passwd并不是正确的,这点使我很困惑。

1
2
3
4
5
.text:00000000004007A0                 lea     rdx, [rbp+passwd]
.text:00000000004007A4                 lea     rax, [rbp+buf]
.text:00000000004007A8                 mov     rsi, rdx
.text:00000000004007AB                 mov     rdi, rax
.text:00000000004007AE                 call    authenticate

错误脚本如下

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import angr
import claripy
import sys
import logging
logging.getLogger('angr.sim_manager').setLevel('DEBUG')
 
#symbolic_registers
 
if __name__ == '__main__':
    p = angr.Project('./fauxware')
 
    #set the start address
    start = 0x4007A8
    state = p.factory.blank_state(addr=start)
 
    #make the rbp = rsp
    state.regs.rbp = state.regs.rsp
 
    #set the reg symbol
    passwd = claripy.BVS('passwd', 64)
    username = claripy.BVS('username',64)
    state.regs.rax = username
    state.regs.rdx = passwd
 
 
    sm = p.factory.simulation_manager(state)
 
    '''
    explore choice one: use a fixed address to hit the address
    '''
    # aim = 0x4006F6 #the address want to hit
    # address_avoid = 0x4007CE#the address want to avoid
    # sm.explore(find=aim,avoid=address_avoid)
 
    '''
    explore choice two: use a flexible function to hit the address
    '''
    def auth(state):
        stdout = state.posix.dumps(1)
        if b'trusted u' in stdout: #must be byte object,not string object.
            return True
        else:
            return False
    def no_auth(state):
        stdout = state.posix.dumps(1)
        if b'Go away!' in stdout:
            return True
        else:
            return False
    sm.explore(find=auth,avoid=no_auth)
 
    import IPython; IPython.embed()
    if sm.found:
        result = sm.found[0].solver.eval(passwd,cast_to=bytes)[::-1] #求解路径约束
        print('solution is {}'.format(result))
 
    #why it doesn't work?

解决如下

 

原因:对rdx rax里面存储的内容理解错误,之前错误的认为其内容为字符串,实际是字符串存储地址,如果符号化寄存器来求解的话,需要通过寄存器求解处地址,然后读取内存,获取passwd.

 

脚本如下

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import angr
import claripy
import sys
import logging
logging.getLogger('angr.sim_manager').setLevel('DEBUG')
 
#symbolic_registers
 
if __name__ == '__main__':
    p = angr.Project('./fauxware')
 
    #set the start address
    start = 0x4007A8
    state = p.factory.blank_state(addr=start)
 
    #make the rbp = rsp
    state.regs.rbp = state.regs.rsp
 
    #set the reg symbol
    passwd_address = claripy.BVS('passwd_address', 64)
    username_address = claripy.BVS('username_address',64)
    state.regs.rax = username_address
    state.regs.rdx = passwd_address
 
 
    sm = p.factory.simulation_manager(state)
 
    '''
    explore choice one: use a fixed address to hit the address
    '''
    aim = 0x4006f6 #the address want to hit   400697 0x4006f6
    address_avoid = 0x4007CE#the address want to avoid
    sm.explore(find=aim,avoid=address_avoid)
 
    '''
    explore choice two: use a flexible function to hit the address
 
    def auth(state):
        stdout = state.posix.dumps(1)
        if b'trusted u' in stdout: #must be byte object,not string object.
            return True
        else:
            return False
    def no_auth(state):
        stdout = state.posix.dumps(1)
        if b'Go away!' in stdout:
            return True
        else:
            return False
 
    sm.explore(find=auth,avoid=no_auth)
    '''
    #import IPython; IPython.embed()
 
    if sm.found:
        address = format(sm.found[0].solver.eval(passwd_address),'x') #get the passwd_address
        passwd = sm.found[0].memory.load(int(address,16),8)# get the symbolic_passwd
        result = sm.found[0].solver.eval(passwd,cast_to=bytes)# solve the passwd
        print('solution is {}'.format(result))

符号化内存

程序如下所示,输入存储在了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+0h] [ebp-Ch]
 
  memset(user_input, 0, 0x21u);
  printf("Enter the password: ");
  __isoc99_scanf("%8s %8s %8s %8s", user_input, &unk_81F98A8, &unk_81F98B0);
  for ( i = 0; i <= 31; ++i )
    user_input[i] = complex_function(user_input[i], i);
  if ( !strncmp(user_input, "KQXWRXTYKNDANTQPDDKICJFTASVNCBZM", 0x20u) )
    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
31
32
33
34
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import angr
import claripy
import sys
import logging
logging.getLogger('angr.project.factory').setLevel('DEBUG')#angr.project.factory  angr.sim_manager
 
if __name__ == '__main__':
    p = angr.Project('./05_angr_symbolic_memory')
    #set the start address
    start = 0x08049357
    state = p.factory.blank_state(addr=start)
 
    #set the reg symbol
    passwd0 = claripy.BVS('passwd0', 64)
    passwd1 = claripy.BVS('passwd1', 64)
    passwd2 = claripy.BVS('passwd2', 64)
    passwd3 = claripy.BVS('passwd3', 64)
 
    passwd_address = 0x081F98A0
    state.memory.store(passwd_address,passwd0)
    state.memory.store(passwd_address+8,passwd1)
    state.memory.store(passwd_address+16,passwd2)
    state.memory.store(passwd_address+24,passwd3)
    sm = p.factory.simulation_manager(state)
    '''
    explore choice one: use a fixed address to hit the address
    '''
    aim = 0x080493D6 #the address want to hit   804935E 0x4006F6
    address_avoid = 0x080493C2#the address want to avoid
    sm.explore(find=aim,avoid=address_avoid)
    import IPython; IPython.embed()

程序find到目标地址处,进入ipython交互界面,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
In [6]: sm.found[0]
Out[6]: <SimState @ 0x80493d6>  成功找到了目标点
 
In [7]: sm.found[0].solver.eval(passwd0)
Out[7]: 0  但是求解出来的passwd是错误的?why?
 
通过观察程序log信息,发现其在0xfc1ad8a0处填写了0x20字节长度的字符串??
WARNING | 2020-12-27 08:31:30,209 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0xfc1ad8a0 with 1 unconstrained bytes referenced from 0x804936b (main+0x8b in 05_angr
_symbolic_memory (0x804936b))
......
WARNING | 2020-12-27 08:31:30,209 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0xfc1ad8bf with 1 unconstrained bytes referenced from 0x804936b (main+0x8b in 05_angr
_symbolic_memory (0x804936b))
 
尝试求解这0x20字节的字符串
In [4]: mm = sm.found[0].memory.load(0xfc1ad8a0,0x20)
 
In [5]: sm.found[0].solver.eval(mm,cast_to=bytes)
Out[5]: b'NPOJNSALTAJJWFWHWEBOYCQLWUDTDMIZ' 这个字符串求解出来是错的
 
why?
第一个疑问,为什么断在了目标点,但是passwd求解出来都是0
第二个疑问,为什么会要在一个奇奇怪怪的地址0xfc1ad8a0填入符号值

结语

按照官网教程却整不通,码一下,希望有师傅指点一下。

 

解决之后回来拔草


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-12-28 08:51 被sfftlt编辑 ,原因:
上传的附件:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 4811
活跃值: (886)
能力值: ( LV13,RANK:319 )
在线值:
发帖
回帖
粉丝
2

对于你符号化内存的点就是你用的blank_state,通用寄存器都没初始化,所以angr会给你符号化地址。08049357这里用到了栈的局部变量,你并没有初始化地址哦,所以你得初始化下ebp。然后后面在这里又用到了:

2021-5-20 16:58
0
游客
登录 | 注册 方可回帖
返回
//