zoukankan      html  css  js  c++  java
  • Week1--漏洞学习

    来源于天问之路知识星球的每日安全推送。

    ASAN检测不到的bugs

    文章链接: https://nandynarwhals.org/bugs-asan-doesnt-detect/

    这篇文章是关于三个能够绕过ASAN检测的bugs,之前我没有接触过ASAN,借此了解一下。

    在gcc/g++下使用ASAN只需要在编译的时候加上-fsanitize=address,在此选项下编译简单的存在double free的C文件,运行时可以看到检测到double free:

    //TODO

    在源文章代码的基础上稍加修改在Linux Ubuntu16.04的环境下可以得到预期结果的源代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    
    struct sample {
        char buf[8];
        uint32_t val;
    };
    
    void choice1() {
        puts("1. Overflowing a buffer within a struct.");
    
        struct sample sample_struct;
        printf("sample_struct.val = 0x%x
    ", sample_struct.val);
        strncpy(sample_struct.buf, "ccccccccdddd", 12);
        printf("sample_struct.val = 0x%x
    ", sample_struct.val);
    }
    /*
    void choice2() {
        puts("2. Arbitrary write with integer overflows skipping over shadow mem.");
    
        char canary[10] = "IAMCANARY";
        char buf[10];
    
        printf("Canary = "%s"
    ", canary);
    
        int position = 2147483616;
        position = position * 2;
        printf("position = %d
    ", position);
        for (int i = 0; i < 9; i++) {
            buf[position + i] = 'X';
            printf("buf[%d] = 'X'
    ", position + i);
        }
    
        printf("Canary = "%s"
    ", canary);
    }
    */
    void choice2() {
        puts("2. Skipping over shadow memory.");
    
        char canary[10] = "IAMCANARY";
        char buf[10];
    
        printf("Canary = "%s"
    ", canary);
    
        int position = -64;
        printf("position = %d
    ", position);
        for (int i = 0; i < 9; i++) {
            buf[position + i] = 'X';
            printf("buf[%d] = 'X'
    ", position + i);
        }
    
        printf("Canary = "%s"
    ", canary);
    }
    
    void f1(int ** p) {
        int dangle = 0x41414141;
        *p = &dangle;
    }
    
    void f2() {
        int override1 = 0x42424242;
        long long int a=1;
        long long int b=2;
        long long int c=3;
        long long int d=4;
        long long int e=5;
        long long int f=6;
        long long int g=7;
        long long int h=8;
        long long int i=9;
        int j=10;
    }
    
    void choice3() {
        puts("3. Use of stack variable after returning from a function.");
    
        int * p = 0;
        printf("p = %p
    ", p);
        printf("*p = undefined
    ");
    
        f1(&p);
        printf("p = %p
    ", p);
        printf("*p = 0x%x
    ", *p);
    
        f2();
        printf("p = %p
    ", p);
        printf("*p = 0x%x
    ", *p);
    }
    
    int main(int argc, char ** argv) {
    
        choice1();
        choice2();
        choice3();
    
        return 0;
    }
    

    结果如下:

    //TODO

    其中choice1对应第一种漏洞:结构体中的缓冲区溢出。首先打印出了栈上未初始化的垃圾数据,其次利用结构体上的变量连续存储,第一个变量溢出,覆盖后一个本不该被赋值的变量,此缓冲区溢出不会被ASAN检测到。

    choice2对应第二种漏洞:跳过shadow memory。(由于我在查了一些资料后,对ASAN中的shadow memory仍然不是非常理解,这一部分先翻译原文章的内容。)此漏洞利用在二进制文件上启用了ASAN来执行相同的缓冲区上溢/下溢,通过计算一些偏移量来跳过保护缓冲区的shadow字节。

    choice3对应第三种漏洞:从函数返回后使用栈变量。在函数调用返回后,栈空间被销毁,下一次再次调用其他函数时不应该影响上一次调用的结果。但是由于在主函数中连续两次调用函数,会开拓同一段栈空间,因此可能会出现stack-use-after-return的bugs。choice3展示了该bug的一种情况,可以看到ASAN不会检测到使用指向已销毁栈帧的指针的情况。

    跟我一起写Makefile

    文章链接: https://seisman.github.io/how-to-write-makefile/index.html

    Makefile可以实现“自动化编译”,使用make命令就可以实现整个工程完全自动编译。

    规则

    Makefile的规则包含两个部分:依赖关系、生成目标的方法

    target ... : prerequisites ... 
    #或者 target : prerequisites ; command
     	command
     	...
    

    target: 目标文件/可执行文件/label

    prerequisites:生成该target所依赖的文件或target

    command:必须以Tab键开头,说明该target所要执行的命令(任意的shell命令)

    ==> target依赖于prerequisites中的文件,其生成规则定义在command中。

    prerequisites中如果有一个以上的文件比target文件要新,就会执行command定义的命令。

    一般来说,make命令会以UNIX的标准Shell,/bin/sh执行命令

    书写规则

    Makefile中只应该有一个最终目标,第一条规则中的第一个目标会成为最终的目标,也就是make命令所完成的目标。

    如果某一行过长,可以使用反斜杠作为换行符。

    make支持三个通配符:*?~

    Makefile包含的五个部分

    • 显示规则

      说明了如何生成一个或多个目标文件,包括要生成的文件、文件的依赖文件和生成的命令

    • 隐晦规则

      GNU的make可以自动推导文件以及文件依赖关系后面的命令,make看到一个.o文件,就会自动的把.c文件加在依赖关系中,并且推导出cc -c xxx.c命令

    • 变量的定义

      makefile的变量也就是一个字符串:定义字符串xxx=...,则可以通过$(xxx)来使用这个变量

    • 文件指示

      通过inlcude <filename>可以在一个Makefile中引用另一个Makefile文件;make也会引用环境变量MAKEFILES值所代表的所有Makefile,但引入Makefile的“目标”不起作用。

    • 注释

    Makefile的文件名

    默认情况下:make命令会在当前目录下按顺序寻找文件名为"GNUmakefile","makefile","Makefile",其中"GNUmakefile"只能由GNU的make识别。

    GNU make的工作方式

    1. 读入所有的Makefile
    2. 读入被include的其它Makefile
    3. 初始化文件中的变量
    4. 推导隐晦规则,并分析所有规则
    5. 为所有的目标文件创建依赖关系链
    6. 根据依赖关系,决定哪些目标要重新生成
    7. 执行生成命令

    当变量出现在依赖关系的规则中,只有当这条依赖被决定要使用了,那么变量才会在其内部展开。

    //UNDONE

  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/Theffth-blog/p/13340916.html
Copyright © 2011-2022 走看看