符号执行之angr_ctf

前言

angr_ctf
之前一直弄环境没弄好,现在都解决了,终于可以全部过一遍了,仓库提供了三个部分的文件,一个是源码编译部分,一个是编译好的文件的集合最后是每题的题解部分分别在
在这里插入图片描述
值得注意的是编译好的文件都是elf类型的,所以最好采用Linux运行脚本,而且默认版本是python2的,使用它提供的模板时最好修改下print打印函数添加括号,其它部分倒没什么需要解决的

00_angr_find

可恶,编译好的windows版本一直不能运行,显示地址错误,不知道是不是开启了随机地址, 关了也没法
在这里插入图片描述

输入字符经过加密后等于QWSYJIQP,输出Good Job字符

#!/usr/bin/env python3

import angr
import sys
import os

def main():
  proj = angr.Project('/root/桌面/python-x/angr_ctf/solutions/00_angr_find/00_angr_find',auto_load_libs=False)
  initial_state = proj.factory.entry_state()
  pg = proj.factory.simgr(initial_state)
  pg.explore(find=0x804867d)
  print(pg.found[0].posix.dumps(0))

if __name__ == '__main__':
  main()

一个最基本的框架结构,事实上还可以更简化点

  • Project表示新建项目,载入大致基本信息,auto_load_libs=false表示不载入相关库文件,可以删掉,但默认会载入,会浪费些时间
  • entry_state创建新建状态,为后面模拟器初始化,可以理解成新建的对象,类,返回一个状态的对象
  • simgr新建模拟器,参数表示以该传入对象初始化模拟器,一般angr代码中这三个之后才能开始探索一类的事务
  • explore得到指定地址的输入,如果找到了返回一个数组,found[0]中保存有得到的路径的状态

不知道为什么windows中idapro反编译的地址和在Linux中的地址有一点细微的差别,导致找了半天
QTMPXTYU

01_angr_avoid

进去后main函数比较大,不能直接被反编译,当然想反编译也可以改一下配置文件但没必要,只需要知道find和avoid地址即可,因为函数比较大,不加避免条件就会一直跑卡死
explore(self, stash=None, n=None, find=None, avoid=None, find_stash=None, avoid_stash=None, cfg=None,
num_find=1, **kwargs)
在这里插入图片描述
分析也可以发现,不能进入avoid_me函数,他会把succeed变为0,判断的时候会影响跳转
在这里插入图片描述

import angr
Proj =angr.Project('/root/桌面/python-x/angr_ctf/solutions/01_angr_avoid/01_angr_avoid',auto_load_libs=False)
State =Proj.factory.entry_state()
Sim =Proj.factory.simgr(State)
Sim.explore(find =0x080485ed,avoid=0x080485a8)
print(Sim.found[0].posix.dumps(0))
                                     

RNGFXITY

02_angr_find_condition

和01不同,输出again 的地址固定都位于同一个函数中,所以我们避免执行这个函数地址即可,但这里在main函数中很多地方直接调用输出try again,不可能同时avoid这么多地址所以需要用函数进行判断,所以expolre第二种传参方式即可以通过函数传参

在这里插入图片描述

import angr
def good(state):
    a =state.posix.dumps(1)
    return True if 'Good Job' in a.decode('utf-8') else False
def Try(state):
    b =state.posix.dumps(1)
    return True if 'Try again' in b.decode('utf-8') else False
Proj =angr.Project('/root/桌面/python-x/angr_ctf/solutions/02_angr_find_condition/02_angr_find_condition',auto_load_libs=False)
State =Proj.factory.entry_state()
Sim =Proj.factory.simgr(State)
Sim.explore(find =good,avoid=Try)
print(Sim.found[0].posix.dumps(0))

0表示标准输入,1表示标准输出, a in b:a是否被包含在b中

03_angr_symbolic_registers

有多个变量的输入,angr无法像之前一样对输入直接爆破,需要从指定位置angr可以爆破的位置开始,所以我们需要自定义状态,entry_state默认从main函数开始
在这里插入图片描述
我们可以直接对寄存器赋值符号变量
可以使用project.factory.blank_state(addr=start_address)替代原有entry_state,blank中可以传递参数addr定义模块开始运行地址

import angr
import sys
import claripy
pro =angr.Project(sys.argv[1],auto_load_libs=False)
initial_state =pro.factory.blank_state(addr =0x080488D1)

#定义符号向量,给寄存器赋值
eax =claripy.BVS('eax',32)
ebx =claripy.BVS('ebx',32)
edx =claripy.BVS('edx',32)
initial_state.regs.eax =eax
initial_state.regs.ebx =ebx
initial_state.regs.edx =edx

sim =pro.factory.simgr(initial_state)
def good(state):
    return 'Good Job' in state.posix.dumps(1).decode('utf-8')
def again(state):
    return 'Try again' in state.posix.dumps(1).decode('utf-8')
sim.explore(find =good,avoid =again)
one =format(sim.found[0].solver.eval(eax),'x')
two =format(sim.found[0].solver.eval(ebx),'x')
three =format(sim.found[0].solver.eval(edx),'x')
print(one+' '+two+' '+three)

db01abf7 4930dc79 d17de5ce

04_angr_symbolic_stack

和上题不一样,上题可以直接通过寄存器传参这里只能通过栈
在这里插入图片描述
分析栈结构可知,参数地址在ebp-8~ebp-0c和ebp-0c:ebp-10所以要对赋值的ebp-8预留八位对齐参数

import angr
import sys
import claripy
pro =angr.Project(sys.argv[1])
ad =0x08048697
state =pro.factory.blank_state(addr=ad)
a1 =claripy.BVS('a1',32)
a2 =claripy.BVS('a2',32)
state.regs.ebp =state.regs.esp
state.regs.esp -=8
state.stack_push(a2)
state.stack_push(a1)
sim =pro.factory.simgr(state)
def good(a):
    return 'Good' in a.posix.dumps(1).decode('utf-8')
def again(b):
    return 'again' in b.posix.dumps(1).decode('utf-8')
sim.explore(find=good,avoid=again)
output1 =format(sim.found[0].solver.eval(a1),'u')
output2 =format(sim.found[0].solver.eval(a2),'u')
print(output1+' '+output2+' ')

1213922930 1153451551

05_angr_symbolic_memory

和上题的栈很像,只是这里需要将符号变量放入内存,现在理解的就是angr通过定义指定约束的符号变量,然后将这个变量放入指定位置,存储空间可以是一切存储介质,内存,寄存器,栈等

import angr
import sys
import claripy

pro = angr.Project(sys.argv[1])
ad = 0x08048603
state = pro.factory.blank_state(addr=ad)

meom1 = claripy.BVS('meom1', 64)
meom2 = claripy.BVS('meom2', 64)
meom3 = claripy.BVS('meom3', 64)
meom4 = claripy.BVS('meom4', 64)

ad1 = 0xa29faa0
ad2 = 0xa29faa8
ad3 = 0xa29fab0
ad4 = 0xa29fab8

# 将符号变量存入内存
state.memory.store(ad1, meom1)
state.memory.store(ad2, meom2)
state.memory.store(ad3, meom3)
state.memory.store(ad4, meom4)

smg = pro.factory.simgr(state)


def good(a):
    return 'Good' in a.posix.dumps(1).decode('utf-8')


def bad(b):
    return 'Try' in b.posix.dumps(1).decode('utf-8')


smg.explore(find=good, avoid=bad)

# 约束求解
if smg.found[0]:
    s1 = smg.found[0].solver.eval(meom1, cast_to=bytes)
    s2 = smg.found[0].solver.eval(meom2, cast_to=bytes)
    s3 = smg.found[0].solver.eval(meom3, cast_to=bytes)
    s4 = smg.found[0].solver.eval(meom4, cast_to=bytes)
    print("05:{} {} {} {}".format(s1.decode('utf-8'), s2.decode('utf-8'), s3.decode('utf-8'), s4.decode('utf-8')))
else:
    print("NULL")


状态初始化的地址需要为scanf后面

06_angr_symbolic_dynamic_memory

输入的空间是使用函数开辟的,因此不能像前面一样直接获得准确地址,所以我们可以直接为指针添加我们指定位置和空间作为符号向量的存储地
在这里插入图片描述

import angr
import sys
import claripy

pro =angr.Project(sys.argv[1])
ad =0x0804869e
state =pro.factory.blank_state(addr =ad)

m1 =claripy.BVS('m1',64)
m2 =claripy.BVS('m2',64)

ad1 =0x0a79a118
ad2 =0x0a79a120
ad3 =0x0a799cc0
ad4 =0x0a79a120

state.memory.store(ad1,ad3,endness=pro.arch.memory_endness)
state.memory.store(ad2,ad4,endness=pro.arch.memory_endness)

state.memory.store(ad3,m1)
state.memory.store(ad4,m2)

smg =pro.factory.simgr(state)

def good(a):
    return 'Good' in a.posix.dumps(1).decode('utf-8')


def bad(b):
    return 'Try' in b.posix.dumps(1).decode('utf-8')
smg.explore(find =good,avoid =bad)

if smg.found:
    s1 = smg.found[0].solver.eval(m1, cast_to=bytes)
    s2 = smg.found[0].solver.eval(m2, cast_to=bytes)
    print("05:{} {}".format(s1.decode('utf-8'), s2.decode('utf-8')))
else:
    print("NULL")

如果state地址不是scanf后面的地址会出现卡死,输入地址没有更改会找不到路径,相信把所有遇到的错误都记下,他们肯定是有限的,就能完全熟练了
IDMRHRCZ PLBQSLBO

07_angr_symbolic_file

输入由内存变成了文件读取输入,创建文件符号向量
在这里插入图片描述
状态开始地址设为88ef处,add esp,10h清空之前的栈

# -*- coding:utf-8 -*-
import angr
import sys
import claripy

pro = angr.Project(sys.argv[1])
ad = 0x080488ef

# 创建文件的符号向量
file = 'WCEXPXBW.txt'
file_size = 64
symbol = claripy.BVS('symbol', file_size * 8)
symbol_file = angr.SimFile(file, content=symbol, size=file_size)

state = pro.factory.blank_state(addr=ad, fs={file: symbol_file})
sim = pro.factory.simgr(state)


def good(a):
    return 'Good' in a.posix.dumps(1).decode('utf-8')


def bad(b):
    return 'Try' in b.posix.dumps(1).decode('utf-8')


sim.explore(find=good, avoid=bad)
if sim.found:
    res = sim.found[0].solver.eval(symbol, cast_to=bytes)
    print('06: {}'.format(res.decode('utf-8')))
else:
    raise Exception('No result')

GQLWJWWI
参考链接:
https://www.cnblogs.com/level5uiharu/p/16925991.html
https://space.bilibili.com/386563875/channel/seriesdetail?sid=1835245
https://blog.gentlecp.com/article/61784.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值