zoukankan      html  css  js  c++  java
  • 20169212《Linux内核原理及分析》第十二周作业

    格式化字符串漏洞实验

    格式化字符串漏洞是由像 printf(user_input) 这样的代码引起的,其中 user_input 是用户输入的数据,具有 Set-UID root 权限的这类程序在运行的时候,printf 语句将会变得非常危险。

    • 实验一:

    找出 secret[1]的值

    输入命令:

    ls
    vi test.c
    gcc -z execstack -fno-stack-protector -o djw test.c
    

    其中test.c的代码为

    include <stdlib.h>
    include <stdio.h>
    
    define SECRET1 0x44
    define SECRET2 0x55
    
    int main(int argc, char *argv[])
    {
      char user_input[100];
      int *secret;
      long int_input;
      int a, b, c, d; /* other variables, not used here.*/
    
      /* The secret value is stored on the heap */
      secret = (int *) malloc(2*sizeof(int));
    
      /* getting the secret */
      secret[0] = SECRET1; secret[1] = SECRET2;
    
      printf("The variable secret's address is 0x%8x (on stack)
    ", &secret);
      printf("The variable secret's value is 0x%8x (on heap)
    ", secret);
      printf("secret[0]'s address is 0x%8x (on heap)
    ", &secret[0]);
      printf("secret[1]'s address is 0x%8x (on heap)
    ", &secret[1]);
    
      printf("Please enter a decimal integer
    ");
      scanf("%d", &int_input);  /* getting an input from user */
      printf("Please enter a string
    ");
      scanf("%s", user_input); /* getting a string from user */
    
      /* Vulnerable place */
      printf(user_input);  
      printf("
    ");
    
      /* Verify whether your attack is successful */
      printf("The original secrets: 0x%x -- 0x%x
    ", SECRET1, SECRET2);
      printf("The new secrets:      0x%x -- 0x%x
    ", secret[0], secret[1]);
      return 0;
    }
    

    编译后进行执行,如图

    首先定位 int_input 的位置,这样就确认了%s 在格式字符串中的位置(由于与文档上000000000000000C不一致,所以要进一步确定位置)
    用%08x进行显示,如图

    输入 secret[1]的地址,记得做进制转换,同时在格式字符串中加入%s,如图

    U 的 ascii 码就是 55。

    修改 secret[1]的值

    如果只要求修改,不要求改什么,可以利用%n进行修改,修改如下:

    修改 secret[1]为期望值

    要改成自己期望的值,可以进行填充:

    %n可以进行计数,0x3e8 = 1000。

    • 实验二:

    include <sys/types.h>
    include <sys/stat.h>
    include <fcntl.h>
    int main()
    {
        char buf[1000];
        int fp, size;
        unsigned int *address;
        /* Putting any number you like at the beginning of the format string */
        address = (unsigned int *) buf;
        *address = 0x113222580;
        /* Getting the rest of the format string */
        scanf("%s", buf+4);
        size = strlen(buf+4) + 4;
        printf("The string length is %d
    ", size);
        /* Writing buf to "mystring" */
        fp = open("mystring", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
        if (fp != -1) {
            write(fp, buf, size);
            close(fp);
        } else {
            printf("Open failed!
    ");
        }
    }
    

    现在让我们把第一个实验中的 scanf 语句去掉,并去掉与 int_input 变量相关的所有语句,同时设置关闭地址随机化选项。操作如下:


    在这里,刚开始碰到了问题,权限不够。后来用sudo进行提权,要输入密码,根据以往设计者的情况,密码为dees,进行提权后指令即可执行成功。

    修改 secret[0]的值

    修改 test.c 后编译 test.c 与 write_string.c 然后通过 write_string 程序将内容输入进 mystring 文件中,文件内容包括代码中加入的头四个字节和你之后输入的内容。实验过程如下:

    在这里试验了好多次,由于刚开始没有找准位置,以为./test不需要,./write_string之后直接按之前的位置安放%n进行输入就好。导致The original secrets和The news secret内容一致,甚至出现segmentation fault的情况。后来总结了一下,重新对test进行测试,找准了位置,再进行上面命令的输入,就得到了准确的结果。
    0x31=49=5*8+5个逗号+开头4个字节。

  • 相关阅读:
    14 微服务电商【黑马乐优商城】:day06-使用nginx反向代理并掌握cors解决跨域
    Docker容器化【Docker安装与启动&Docker镜像与容器相关命令】
    [LeetCode]Palindrome Number 验证回文数
    C++结构体定义构造函数
    C++中explicit关键字的使用
    C++ const关键字
    图像梯度(Image Gradient)
    ORB特征点匹配
    c++:internal compiler error:killked(program cclplus) 解决办法
    最小二乘通俗解释
  • 原文地址:https://www.cnblogs.com/Jarvan210/p/6160643.html
Copyright © 2011-2022 走看看