首页 > 其他分享 >Angr

Angr

时间:2023-01-21 20:11:07浏览次数:57  
标签:Angr avoid init state angr found out

Angr

首先引用名言:

我超,这angr好几把神奇。
                ——iPlayForSG

angr的安装

我在kali上用(EPsilon学长/姐)/iPlayForSG学长的方法没成功,最后用的这个

angr_find

这一关让我们来熟悉angr的用法

写出脚本:

import angr

p = angr.Project('./00_angr_find')      #创建项目
init_state = p.factory.entry_state()    #设置入口点
s = p.factory.simgr(init_state)         #创建模拟器

s.explore(find = 0x08048678)            #设置条件

if s.found:
    print(s.found[0].posix.dumps(0))    #打印输入
else:
    print("fail")

运行得出结果:

angr_avoid

这题的文件大小就预示着它很不一般,尤其是不要试图F5它的main()函数,会死机。
在maby_good()函数里看见有一个should_succeed:

查看交叉引用,发现它在avoid_me()函数中被赋0,而avoid_me()函数被调用了......8191次......

写出脚本

import angr

p = angr.Project('./01_angr_avoid')
init_state = p.factory.entry_state()
s = p.factory.simgr(init_state)

s.explore(find = 0x080485E0, avoid = 0x080485AB)

if s.found:
    print(s.found[0].posix.dumps(0))
else:
    print("fail")

运行得出结果

angr_find_condition

虽然主函数看起来人畜无害

但是左下角的graph view非常感人

这个程序输出成功/失败提示的地方非常的多,用地址是不可能的了,所以检测输出

import angr

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)     #检查输出

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)    #检查输出

p = angr.Project('./02_angr_find_condition')
init_state = p.factory.entry_state()
s = p.factory.simgr(init_state)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].posix.dumps(0))
else:
    print("fail")

运行得出结果

angr_symbolic_registers

题目描述说angr做不了三个输入的题,所以要人为构造输入,在IDA里找到三个位置分别是eax,ebx,edx

写出脚本

import angr
import claripy

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

p = angr.Project('./03_angr_symbolic_registers')
init_state = p.factory.entry_state()
# init_state = p.factory.blank_state(addr = 0x08048980)   #自定义入口点,调用输入“之后”的地址
# input0 = claripy.BVS('input0', 4 * 8)                   #自定义输入,通过IDA查看输入的大小
# input1 = claripy.BVS('input1', 4 * 8)
# input2 = claripy.BVS('input2', 4 * 8)
# init_state.regs.eax = input0                            #自定义输入的位置(寄存器),通过IDA查看
# init_state.regs.ebx = input1
# init_state.regs.edx = input2

s = p.factory.simgr(init_state)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    # print(('{:x} {:x} {:x}'.format(s.found[0].solver.eval(input0), s.found[0].solver.eval(input1), s.found[0].solver.eval(input2))))
    print(s.found[0].posix.dumps(0))
else:
    print("fail")

为什么注释掉了一大堆捏?因为用推荐的方法写会报一大坨错,说数组越界,甚至用它给的标准答案都不行。angr在最初并不那么高级,但是现在高级了,也就不用这样了(然鹅理论上不应该报错才对)。运行得到结果

angr_symbolic_stack

同上一题,本意是在栈中手动模拟栈的操作,但是现在angr可以自己解决这个问题了。

add esp, 10h是恢复栈的操作,因此我们从0x8048697开始程序,并手动将两个输入填充到占空间上

import angr
import claripy

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

p = angr.Project('./04_angr_symbolic_stack')
# init_state = p.factory.entry_state()
init_state = p.factory.blank_state(addr = 0x08048697)       #人为创造入口点
init_state.regs.ebp = init_state.regs.esp                   #初始化ebp
input0 = claripy.BVS('input0', 4 * 8)
input1 = claripy.BVS('input1', 4 * 8)
padding = 8
init_state.regs.esp -= 8

init_state.stack_push(input0)
init_state.stack_push(input1)

s = p.factory.simgr(init_state)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(('{:d} {:d}'.format(s.found[0].solver.eval(input0), s.found[0].solver.eval(input1))))
    # print(s.found[0].posix.dumps(0))
else:
    print("fail")

具体原因如下

运行得到结果

诶嘿,这个可以正常运行而且没有WARNING诶~

angr_symbolic_memory

这一题需要我们在.bss段创建输入,同样的,现在的angr已经不需要这么做了。

写出代码

import angr
import claripy

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

p = angr.Project('./05_angr_symbolic_memory')
init_state = p.factory.blank_state(addr = 0x08048601)       #在scanf()之后开始

input0 = claripy.BVS('input0', 64)
input1 = claripy.BVS('input1', 64)
input2 = claripy.BVS('input2', 64)
input3 = claripy.BVS('input3', 64)
init_state.memory.store(0x0A1BA1C0, input0)                 #在.bss段存入数据
init_state.memory.store(0x0A1BA1C8, input1)
init_state.memory.store(0x0A1BA1D0, input2)
init_state.memory.store(0x0A1BA1D8, input3)

s = p.factory.simgr(init_state)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(('{} {} {} {}'.format(s.found[0].solver.eval(input0, cast_to = bytes), s.found[0].solver.eval(input1, cast_to = bytes), s.found[0].solver.eval(input2, cast_to = bytes), s.found[0].solver.eval(input3, cast_to = bytes))))
else:
    print("fail")

运行得出结果

这次的运行速度和普通写法差不多,相比于前几题慢了一些

angr_symbolic_dynamic_memory

这一题需要我们在堆区写入输入

写出脚本

import angr
import claripy

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

p = angr.Project('./06_angr_symbolic_dynamic_memory')
init_state = p.factory.blank_state(addr = 0x08048699)

input0 = claripy.BVS('input0', 64)
input1 = claripy.BVS('input1', 64)
fake_heap0 = 0x0ABCC88F                                                                 #在.bss段随便找一块没用的,人为创建堆
fake_heap1 = 0x0ABCC859
addr_input0 = 0x0ABCC8A4                                                                #记录输入的地址
addr_input1 = 0x0ABCC8AC
init_state.memory.store(addr_input0, fake_heap0, endness = p.arch.memory_endness)       #将输入数据的指针指向构建的堆区并采用小端存储
init_state.memory.store(addr_input1, fake_heap1, endness = p.arch.memory_endness)
init_state.memory.store(fake_heap0, input0)                                             #将输入存进堆区
init_state.memory.store(fake_heap1, input1)

s = p.factory.simgr(init_state)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].solver.eval(input0, cast_to = bytes) + b' ' + s.found[0].solver.eval(input1, cast_to = bytes))
else:
    print("fail")

运行得出结果

angr_symbolic_file

这题在文件中创建输入,从fopen前执行angr

写出脚本

import angr
import claripy

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

p = angr.Project('./07_angr_symbolic_file')
init_state = p.factory.blank_state(addr = 0x080488EA)

filename = 'OJKSQYDP.txt'                                           #定义文件名字
file_size = 8                                                       #虽然文件开了64 bytes,但是根据后续可知只用到了8 bytes
input = claripy.BVS('input', file_size * 8)
file = angr.SimFile(name = filename, content = input, size = 8)     #填充文件内容
init_state.fs.insert(filename, file)                                #将文件和angr建立联系

s = p.factory.simgr(init_state)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].solver.eval(input, cast_to = bytes))
else:
    print("fail")

运行得出结果

angr_constraints

这一题的对比函数会将16个字符判断完成后在进行反馈,这会导致angr的路径爆炸,因此我们需要在对比之前停下程序,自行对比

可以写出脚本

import angr
import claripy

p = angr.Project('./08_angr_constraints')
init_state = p.factory.blank_state(addr = 0x08048625)       #在scanf()后开始
input = claripy.BVS('input', 16 * 8)
init_state.memory.store(0x0804A050, input)                  #在.bss段存入输入
# init_state = p.factory.entry_state()
s = p.factory.simgr(init_state)

s.explore(find = 0x0804866C)                                #在对比函数前停止

if s.found:
    cmp_BVS = s.found[0].memory.load(0x0804A050, 16)        #调取加密后的输入
    aim_BVS = b'AUPDNNPROEZRJWKB'                           #调取目标值
    s.found[0].add_constraints(cmp_BVS == aim_BVS)          #添加成功条件
    print(s.found[0].solver.eval(input, cast_to = bytes))
    # print(s.found[0].posix.dumps(0))
else:
    print("fail")

现在angr高级了,在.bss存数据那一段用注释的内容也可以。运行得出结果

angr_hooks

本题中需要我们自行改写一个函数来避免路径爆炸

写出代码

import angr
import claripy

p = angr.Project('./09_angr_hooks')
init_state = p.factory.entry_state()

hook_addr = 0x080486B3                                                                              #被hook的函数的call指令地址
skip_length = 5                                                                                     #此条call指令所占字节
@p.hook(hook_addr, length = skip_length)                                                            #进行hook,“length = ”必须写

def my_check(state):                                                                                #创造自己的函数
    cmp_BVS = state.memory.load(0x0804A054, 16)
    aim_BVS = b'XYMKBKUHNIQYNQXE'
    state.regs.eax = claripy.If(cmp_BVS == aim_BVS, claripy.BVV(1, 32), claripy.BVV(0, 32))         #必须使用z3语法,必须使用BVV

s = p.factory.simgr(init_state)

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].posix.dumps(0))
else:
    print("fail")

运行得出结果

angr_simprocedures

这一题还是hook函数,不过这个函数被调用了256次。因此我们决定hook函数本身而不是像上一题那样hook调用的指令

写出脚本

import angr
import claripy

p = angr.Project('./10_angr_simprocedures')
init_state = p.factory.entry_state()

class my_check(angr.SimProcedure):                                                          #定义自己的函数
    def run(self, Str, len):                                                                #self之后的参数为被hook函数的参数
        cmp_BVS = self.state.memory.load(Str, len)
        aim_BVS = b'ORSDDWXHZURJRBDH'
        return claripy.If(cmp_BVS == aim_BVS, claripy.BVV(1, 32), claripy.BVV(0, 32))

# hook_func_name = 'check_equals_ORSDDWXHZURJRBDH'
# p.hook_symbol(hook_func_name, my_check())                                                 #第一种hook方式
hook_func_addr = 0x080485F5
p.hook(hook_func_addr, my_check())                                                          #第二种hook方式

s = p.factory.simgr(init_state)

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].posix.dumps(0))
else:
    print("fail")

运行得出结果

angr_sim_scanf

这一题的scanf()函数被调用了256次,由于古老版本angr处理不了多参数输入,因此需要hook,但现在angr已经不需要了

import angr
import claripy

p = angr.Project('./11_angr_sim_scanf')
init_state = p.factory.entry_state()

class my_scanf(angr.SimProcedure):
    def run(self, format_string, input_addr0, input_addr1):
        input0 = claripy.BVS('input0', 32)                                                  #创建输入
        input1 = claripy.BVS('input1', 32)
        self.state.memory.store(input_addr0, input0, endness = p.arch.memory_endness)       #存储输入
        self.state.memory.store(input_addr1, input1, endness = p.arch.memory_endness)
        self.state.globals['input0'] = input0                                               #全局化输入
        self.state.globals['input1'] = input1

p.hook_symbol('__isoc99_scanf', my_scanf())

s = p.factory.simgr(init_state)

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].solver.eval(s.found[0].globals['input0']), s.found[0].solver.eval(s.found[0].globals['input1']))
else:
    print("fail")

运行得出结果

angr_veritesting

Angr越来越高级了,现在我们只需要半行代码就可以自动规避一些路径爆炸了

import angr

p = angr.Project('./12_angr_veritesting')
init_state = p.factory.entry_state()

s = p.factory.simgr(init_state, veritesting = True)     #就是这半行

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].posix.dumps(0))
else:
    print("fail")

运行得出结果

angr_static_binary

这一题的程序采用静态编译。angr在模拟动态编译的程序时会将系统函数替换成自己的一套更快的代码。然而对于静态编译的程序则需要我们自己手动hook。好在angr提供了他自己的那一套代码。

import angr

p = angr.Project('./13_angr_static_binary')
init_state = p.factory.entry_state()

s = p.factory.simgr(init_state, veritesting = True)

p.hook_symbol('__libc_start_main', angr.SIM_PROCEDURES['glibc']['__libc_start_main']())     #静态编译的程序会先执行这个函数
p.hook_symbol('printf', angr.SIM_PROCEDURES['libc']['printf']())
p.hook_symbol('__isoc99_scanf', angr.SIM_PROCEDURES['libc']['scanf']())
p.hook_symbol('puts', angr.SIM_PROCEDURES['libc']['puts']())
p.hook_symbol('_strcmp', angr.SIM_PROCEDURES['libc']['strcmp']())

def aim_out(state):
    return b'Good Job.' in state.posix.dumps(1)

def avoid_out(state):
    return b'Try again.' in state.posix.dumps(1)

s.explore(find = aim_out, avoid = avoid_out)

if s.found:
    print(s.found[0].posix.dumps(0))
else:
    print("fail").posix.dumps(0))
else:
    print("fail")

运行得出结果(WARNING太多了,截不全)

结束语

再次引用名言:

我超,这angr好几把神奇。
                ——iPlayForSG

标签:Angr,avoid,init,state,angr,found,out
From: https://www.cnblogs.com/Clovershrub/p/17064015.html

相关文章

  • Angr
    Angr首先引用名言:我超,这angr好几把神奇。                ——iPlayForSGangr的安装我在kali上用(EPsilon学长/姐)/iPlayForSG学长的方法没成功,最......
  • Angr
    Angr首先引用名言:我超,这angr好几把神奇。                ——iPlayForSGangr的安装我在kali上用(EPsilon学长/姐)/iPlayForSG学长的方法没成功,最......
  • angr原理与实践(三)——Arbiter:一种弥合二进制程序漏洞发现中的静态和动态鸿沟
    ​转载请说明出处:信安科研人pleasesubscribemyofficialwechat:信安科研人获取更多安全资讯 原文链接:sec22-vadayath.pdf(usenix.org)代码开源地址:GitHub-jkr......
  • BUUCTF子[网鼎杯 2020 青龙组]singal(angr快速嗦哈解法)
    先查壳,发现是32位程序丢ida继续分析,发现存在vm_opread函数,根据以往做题经验来看,这个题像是虚拟机保护的题目。这里首先是将opcode_table(我自己命的名字)复制前456个字......
  • angr_ctf——从0学习angr(四):库操作和溢出漏洞利用
    angr_ctf项目中后面13~17题没有新的成块的有关angr的知识了,只是对之前题目使用到的模块的扩展和补充,因此就不先列知识点和使用方式了,直接在实战中边讲解边说明库操作13_a......
  • Reverse - Angr angr_ctf
    Reverse-Angrangr_ctf实验题目地址:这里这套题目也做了两三次了,但是不经常用就老忘,这次记录一下。里面有一些是自己的粗浅理解,有不正确的地方欢迎评论。Angr介绍Angr......
  • angr_ctf——从0学习angr(二):状态操作和约束求解
    状态操作angr中提到的状态(state)实际上是一个Simstate类,该类可由Project预设得到。预设完成后,还可以根据需要对某些部分进行细化操作。一个state包含了程序运行到某个阶段......
  • angr_ctf——从0学习angr(一):angr简介与核心概念
    我在学习angr时,先是阅读了开发者发布在IEEE上的论文IEEEXploreFull-TextPDF:该文章讲述了自动化漏洞挖掘的背景和方法,并对angr的架构和核心模块进行了介绍,非常经典值得......
  • kali2021.4a安装angr(使用virtualenv)
    在Linux中安装各种依赖python的软件时,最头疼的问题之一就是各个软件的python版本不匹配的问题,angr依赖python3,因此考虑使用virtualenv来安装angrVirtualenv简介virtualen......
  • Angr-CTF学习笔记11-13
    11_angr_sim_scanf汇编代码:.text:0804862Apush14h;n.text:0804862Cpush0;c.text:0804862Eleaeax,[ebp+key_string].text:08048631pusheax;s.text:08......