zoukankan      html  css  js  c++  java
  • 栈溢出实践

     1 #include <stdio.h>
     2 #define PASSWORD "1234567"
     3 int verify_password (char *password)
     4 {
     5     int authenticated;
     6     char buffer[8];
     7     authenticated=strcmp(password,PASSWORD);
     8     strcpy(buffer,password);//over flowed here!    
     9     return authenticated;
    10 }
    11 void main(void)
    12 {
    13     int valid_flag=0;
    14     char password[1024];
    15     FILE * fp;
    16     if(!(fp=fopen("password.txt","rw+")))
    17     {
    18         exit(0);
    19     }
    20     fscanf(fp,"%s",password);
    21     valid_flag = verify_password(password);
    22     if(valid_flag)
    23     {
    24         printf("incorrect password!
    ");
    25     }
    26     else
    27     {
    28         printf("You have passed the verification!
    ");
    29     }
    30     fclose(fp);
    31 }

    编译成debug版本后,用ollydbg打开,

    由图可知通过验证的程序分支的指令地址是0x00401122  如果把返回地址覆盖成这个地址。则程序将直接跳转到验证通过分支。

    buffer[0~3]

    buffer[4~7]

    authenticated

    前栈帧EBP

    返回地址

    在password.txt中,将4321作为一个输入单元,buffer[8]需要2个单元,第三个单元将authenticated覆盖,第四个将EBP覆盖,第五个单元将返回地址覆盖。

    用十六进制编辑器UltraEdit将第五个修改为0x00401122即可实现跳转。

    代码植入:

    将以上程序稍加修改:

     1 #include <stdio.h>
     2 #include <windows.h>
     3 #define PASSWORD "1234567"
     4 int verify_password(char *password)
     5 {
     6     int authenticated;
     7     char buffer[44];
     8     authenticated = strcmp(password, PASSWORD);  // = ,return 0
     9     strcpy(buffer, password);
    10     return authenticated;
    11 }
    12 void main(void)
    13 {
    14     int valid_flag = 0;
    15     char password[1024];
    16     FILE *fp;
    17     LoadLibrary("user32.dll");    //for messagebox
    18     if(!(fp = fopen("password.txt","rw+")))
    19     {
    20         exit(0);
    21     }
    22     fscanf(fp,"%s",password);
    23     valid_flag = verify_password(password);
    24     if(valid_flag)
    25         printf("incorrect password !
    ");
    26     else
    27         printf("You have passed the verification !
    ");
    28     fclose(fp);
    29     getchar();
    30 
    31 }

    将在password.txt植入用来调用Win API函数MessageBoxA的二进制机器码。

    buffer[44]需要11个4321单元....第14个将返回地址覆盖。

    先在password.txt写入44个字符,则第45个隐藏的截断符null将冲掉authenticated低字节中的1,从而通过验证,此时运行程序可通过。

  • 相关阅读:
    年轻人的第一个 Spring Boot 应用,太爽了!
    面试问我 Java 逃逸分析,瞬间被秒杀了。。
    Spring Boot 配置文件 bootstrap vs application 到底有什么区别?
    坑爹的 Java 可变参数,把我整得够惨。。
    6月来了,Java还是第一!
    Eclipse 最常用的 10 组快捷键,个个牛逼!
    Spring Cloud Eureka 自我保护机制实战分析
    今天是 Java 诞生日,Java 24 岁了!
    厉害了,Dubbo 正式毕业!
    Spring Boot 2.1.5 正式发布,1.5.x 即将结束使命!
  • 原文地址:https://www.cnblogs.com/ht-beyond/p/4334930.html
Copyright © 2011-2022 走看看