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

  • 相关阅读:
    【事件类】雅思口语
    【人物类】雅思口语
    【物品类】雅思口语
    Cassandra (二)Java | scala操作
    rpm安装在哪里了?
    用IDEA创建springboot项目遇到的问题Plugin 'org.springframework.boot:spring-boot-maven-plugin:' not found
    JDBC连接mysql出现The server time zone value '�й���׼ʱ��' is unrecognized
    Java反射、注解
    Junit单元测试
    Java-线程池、匿名内部类、Lambda表达式
  • 原文地址:https://www.cnblogs.com/Theffth-blog/p/13340916.html
Copyright © 2011-2022 走看看