Windows栈溢出原理
1.栈是什么?
栈是一种运算受限的线性表
其限制是仅允许在表的一端进行插入和删除运算
这一端称为栈顶(TOP),相对的另一端称为栈底(BASE)
向一个栈插入新元素,称作进栈、入栈或压栈(PUSH)
它是把新元素放到栈顶元素的上边,使之成为新的栈顶元素;
从一个栈删除元素,又称出栈或退栈(POP)
它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素
进程使用的内存可以分成4个部分
代码区:存储二进制机器码,存储器在这里取指令
数据区:用于存储全局变量
堆区:动态分配和全局变量
栈区:动态存储函数间的调用关系,保证被调用函数返回时恢复到母函数中继续运行
寄存器与函数栈帧
ESP:栈顶指针寄存器,永远指向系统栈顶
EBP:基址指针寄存器,永远指向系统栈最上边一个栈的栈底
ESP和EBP之间的内存空间为当前栈帧
2.栈的溢出
栈溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小
因此当这个数据足够大的时候,将会溢出缓冲区的范围
3.如何利用
通过程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,
从而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的
造成缓冲区溢出的原因是 程序中没有仔细检查用户输入的参数
覆盖邻接变量
例如buffer大小是8字节
输入8个字符,加上字符串截断字符NULL字符,即可覆盖相邻变量,改变程序运行流程
修改函数返回地址
上述覆盖相邻变量的方法虽然很管用,但是漏洞利用对代码环境很苛刻
更通用的攻击缓冲区的方法是,瞄准栈帧最下方EBP和函数返回地址等栈帧的状态值
如果继续增加输入字符,超出buffer[8]字符边界
将依次淹没 相邻变量、前栈帧EBP、返回地址
4.实例
1)创建一个password.txt文件,内容为1234
2)C语言实例代码
#include <stdio.h>
#include <windows.h>
#define PASSWORD "1234567"
int verify_password (char *password) //密码验证函数
{
int authenticated;
char buffer[44];//缓冲区大小
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);//over flowed here!
return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
FILE *fp;
LoadLibrary("user32.dll"); //准备¸messagebox
if(!(fp=fopen("password.txt","rw+")))
{
exit(0);
}
fscanf(fp,"%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!\n");
}
else
{
printf("Good password is OK,You Win!\n");
}
system("pause");
fclose(fp);
}
代码环境
| 操作系统 | Widows XP SP2 |
|---|---|
| 编译器 | Visual C++ 6.0 |
| 编译选项 | 默认编译选项 |
| build版本 | debug版本 |
运行测试一下,更改密码文件对比结果
根据函数栈溢出原理,实现栈溢出需要以下过程
(1) 分析并调试程序,获得淹没返回地址的偏移
(2) 获得buffer的起始地址,根据获得的偏移将其覆盖返回地址,使得函数返回时执行buffer起始地址保存的代码
(3) 提取弹框操作的机器码并保存于buffer的起始地址处,在函数返回时得到执行
为什么会覆盖?
如果在password.txt中写入恰好44个字符,那么第45个隐藏的截断符 null 将冲刷
变量authenticated低字节中的 1,从而突破密码验证的限制
出于字节对齐、容易辨认的目的,我们把"4321"作为一个输入单元
buffer[44]共需要11个这样的单元
第12个输入单元将authenticated覆盖;
第13个单元将前栈帧EBP的值覆盖;
第14个单元将返回地址覆盖;


调试栈的布局
通过动态调试,可以得到以下信息
(1) buffer数组的起始地址为:0x0012FAF0
(2) password.txt 文件中第53~56个字符的ASCII码值,将写入栈帧中的返回地址,成为函数返回后执行的指令地址
也就是说,在buffer的起始地址写入password.txt文件中的第53~56个字节
在 verify_password 函数返回时,会跳到我们输入的字符串开始取指执行
(3) 给password.txt中植入机器码,弹出消息框
MessageBoxA是动态链接库user32.dll的导出函数,本实验中未默认加载
在汇编语言中调用这个函数需要获得这个函数的入口地址。
获取弹窗函数入口参数信息
MessageBoxA的入口参数可以通过user32.dll 在系统中加载的基址和MessageBoxA在库中的偏移得到。
用VC6.0自带的小工具"Dependency Walker"可以获得这些信息(可在Tools目录下找到)
随便把一个有GUI界面的程序扔进去,结果如图所示
user32.dll的基址为:0x77D10000
MessageBoxA 的偏移地址为:0x000407EA
基址+偏移地址=MessageBoxA内存中的入口地址:0x77D507EA


我们要弹窗的字符设成"wintry",用python转换成16进制的ASCII


然后借助OD写汇编代码,获得机器码


将上边的机器码,以十六进制形式逐字写入到 password.txt
第53~56字节填入buffer的起址:0x0012FAF0 ,其余字节用 90(nop) 填充


上边的机器码可能是字符没对齐的原因,会弹出内存读取错误,把字符串改为"wintry00"

成功弹出窗口

Windows栈溢出原理的更多相关文章
- windows编程原理
这里在学网络编程时遇到了讲解windows的编程,稍微整理一下windows编程原理,顺便复习一下. 首先,理解Windows 程序运行原理:Windows应用程序,操作系统,计算机硬件之间的相互关系 ...
- 深入Windows窗体原理及控件重绘技巧
之前有学MFC的同学告诉我觉得Windows的控件重绘难以理解,就算重绘成功了还是有些地方不明白,我觉得可能很多人都有这样的问题,在这里我从Windows窗体的最基本原理来讲解,如果你有类似的疑惑希望 ...
- 初级游戏外挂编程详解 windows运行原理+游戏辅助编程 游戏外挂编程
详解游戏辅助编程 [目录] 1-什么是Windows API 2-Windows进程 3-Windows 的内存的运行原理 4-windows 中句柄的概念 5-Windows的变量类型 6-辅助实现 ...
- 【转载】深入研究Windows内部原理绝对经典的资料
原文:深入研究Windows内部原理绝对经典的资料 另一篇资料:深入研究Windows内部原理系列 (为了方便大家下,我打包了放在一下地址: 1-6:http://download.csdn.net/ ...
- Windows内核原理-同步IO与异步IO
目录 Windows内核原理-同步IO与异步IO 背景 目的 I/O 同步I/O 异步I/O I/O完成通知 总结 参考文档 Windows内核原理-同步IO与异步IO 背景 在前段时间检查异常连接导 ...
- Windows工作原理
Windows工作原理中心思想 Windows工作原理的中心思想就是“动态链接”概念.Windows自身带有一大套函数,应用程序就是通过调用这些函数来实现它的用户界面和在屏幕上显示文本与图形的.这些函 ...
- 逆向工程学习第四天--Windows栈溢出保护机制(GS)原理及绕过测试
GS简介: Windows的缓冲区安全监测机制(GS)可以有效的阻止经典的BOF攻击,因为GS会在函数调用前往函数栈帧内压入一个随机数(canary),然后等函数返回前,会对canary进行核查,判断 ...
- 读书笔记|Windows 调试原理学习|持续更新
关于调试方面的学习笔记,主要来源于<软件调试>的读书笔记和梦织未来论坛的视频教程 1.调试器使用一个死循环监听调试信息. DebugActiveProcess(PID);while(TRU ...
- Windows内核原理系列01 - 基本概念
1.Windows API Windows 应用编程接口(API)是针对WIndwos操作系统用户模式的系统编程接口,包含在WindwosSDK中. 2.关于.NET .NET由一个被称为FCL的类库 ...
随机推荐
- Python远程连接模块-Telnet
Python远程连接模块-Telnet 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 虽然现在主流的python版本还是2.7,相信2020年python程序员都会偏向Python ...
- Python的常用内置函数介绍
Python的常用内置函数介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.取绝对值(abs) #!/usr/bin/env python #_*_coding:utf-8_ ...
- AngularJS总结
因为最近想学习一下ionic框架,了解到ionic是基于AngularJS语法,并且通过SASS构建应用程序,之前自己一直用Vue框架,还有Less,刚刚好趁此机会,学习一下AngularJS与SAS ...
- POJ - 1094 Sorting It All Out(拓扑排序)
https://vjudge.net/problem/POJ-1094 题意 对于N个大写字母,给定它们的一些关系,要求判断出经过多少个关系之后可以确定它们的排序或者排序存在冲突,或者所有的偏序关系用 ...
- bzoj千题计划192:bzoj1569: [JSOI2008]Blue Mary的职员分配
http://www.lydsy.com/JudgeOnline/problem.php?id=1569 dp[i][j][a][b] 表示i个职员,发广告状态为j,已有金钱a,声誉b的最少天数 j= ...
- AngularJS 启程二
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> ...
- 那些年实用但被我忘掉javascript属性.onresize
//获取屏幕宽度并动态赋值 var winWidth = 0; var winHeight = 0; function findDimensions() //函数:获取尺寸 { //获取窗口宽度 if ...
- IOS 与 PHP 通信加密,使用AES 128 CBC no padding
这个网上的资料真实浩如烟海,但是真正有价值的屈指可数 自己尝试了一天多,终于还是搞定了. 再次要感谢网上的前辈么. 比如下面这个关于php和java端的实现: http://my.oschina.ne ...
- ODPS_ele—UDF Python API
自定义函数(UDF) UDF全称User Defined Function,即用户自定义函数.ODPS提供了很多内建函数来满足用户的计算需求,同时用户还可以通过创建自定义函数来满足不同的计算需求.UD ...
- 通俗易懂之Tensorflow summary类 & 初识tensorboard
前面学习的cifar10项目虽小,但却五脏俱全.全面理解该项目非常有利于进一步的学习和提高,也是走向更大型项目的必由之路.因此,summary依然要从cifar10项目说起,通俗易懂的理解并运用sum ...