Canary保护机制及绕过

本文详细介绍了一种绕过Canary防护机制的方法,利用特定条件获取Canary值,并通过构造恶意返回地址实现对目标函数的调用。

Canary基本介绍

在基本的栈溢出中,我们可以通过没有限制输入长度或限制不严格的函数等向栈中写入我们构造的数据,可写入的数据包括但不限于:

  • 一段可执行的代码(关闭NX防护的前提下)

  • 一段特意构造的返回地址等

传统的防御机制之一就是开启
Canary防护,该机制会向我们运行程序的栈底放入一串8字节的随机数据,在函数即将返回时会验证该数据是否发生改变,若发生改变则说明栈被改变了,直接call__stack_chk_fail。验证成功则跳到leave 和 ret正常的返回。

WeChat
Screenshot_20221009181351.png

如何绕过

直接获取栈中canary的值
若该程序会输出我们输入的字符串,则可以在输入数据时估计超出输入的限制1字节,由于C字符串是以'\0'结尾的,我们多输入的1字节就会覆盖'\0',在接下来的输出中,程序本身使用的输出函数没有限制输出的长度,就会将栈中位于所存数据高地址处的Canary值泄露出来,在接下来我们向栈中写入恶意返回地址的时候就可以将该值覆写回去,验证成功。

获取fs:28h中的canary
通过观察汇编代码,我们可以发现每次运行程序产生的随机canary值都存在fs:28h中,接下来会将该值放入EAX中再mov进程序的栈空间内。

mov rax,fs:28h
mov [rbp-8],rax

所以若程序中存在任意读的功能的函数,就可以直接读取该地址中的值即可。

逐字节爆破canary

其余的利用方式由于没有碰到,所以暂时不说,后续遇到了会进行补充。

准备环节

源程序

我们接下来用上述所说的第一种方式来尝试绕过一下canary值的校验。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_LENGTH 100

void init()
{
    setvbuf(stdin,0,_IONBF,0);
    setvbuf(stdout,0,_IONBF,0);
}

void backdoor()
{

    system("/bin/sh");

}

int main()
{

    char buf[10] = {0};

    init();
    printf("[DEBUGING] main: %p\n",main);
    printf("Hello,What's Your name?\n");

    read(0,buf,MAX_LENGTH);

    printf("%s",buf);
    printf("Welcom!\n");
    printf("But wait,WHO ARE YOU?\n");

    read(0,buf,MAX_LENGTH);

    printf("I don't know you,so bye ;)\n");

    return 0;

}

对应的makefile语句。

OBJS=pwn_1.c
CC=gcc # 默认就为gcc
CFLAGS+=-fstack-protector -no-pie -g

pwn_1:$(OBJS)
        $(CC) $^ $(CFLAGS)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值