博客
关于我
缓冲区溢出基本C程序的控制台和Win32版本
阅读量:110 次
发布时间:2019-02-26

本文共 3332 字,大约阅读时间需要 11 分钟。

缓冲区溢出是计算机安全领域中的一个经典问题,许多开发者在编写C程序时都曾遇到过类似的挑战。本文将通过实际代码示例,详细解释缓冲区溢出的基本原理,并探讨如何在Win32窗口程序中避免这一问题。

缓冲区溢出的基本原理

在C语言中,缓冲区溢出通常发生在字符串拷贝操作中。假设程序中有一个固定大小的缓冲区(如char buff[8] = {0}),而源字符串的长度超过了缓冲区的容量。例如:

char *p = "012345678912345";strcpy(buff, p);

在这种情况下,p 指向的字符串长度为15,超过了缓冲区 buff 的大小(8字节)。当 strcpy 函数尝试将整个字符串拷贝到缓冲区时,会导致缓冲区溢出,程序崩溃。

Win32窗口程序中的缓冲区溢出

在Win32程序中,缓冲区溢出的情况与上述C程序类似,但由于其窗口模型,现象可能有所不同。以下是一个经典的缓冲区溢出示例:

char buff[8] = {0};char *p = "012345678912345";lstrcpy(buff, p);

在这个代码中,lstrcpy 是Win32中用于字符串拷贝的低层函数。同样,由于目标缓冲区的大小不足以容纳源字符串,拷贝操作会导致缓冲区溢出。然而,与C程序不同的是,Win32窗口程序的崩溃可能不那么直观,实际上可能只会输出部分数据。

为什么会这样?

在Win32程序中,缓冲区溢出的表现取决于具体的环境和代码结构。使用lstrcpy时,如果目标缓冲区的大小不足以容纳源字符串,系统会自动截断并输出已拷贝的部分内容,而不会抛出错误。这种行为与传统的C程序不同,可能让开发者误以为程序没有崩溃。

如何防止缓冲区溢出

为了避免缓冲区溢出,应严格控制字符串的拷贝长度,确保目标缓冲区的大小大于等于源字符串的长度。在C程序中,可以使用strncpy函数:

char buff[8] = {0};char *p = "0123456789";strncpy(buff, p, sizeof(buff));

在Win32程序中,可以采用类似的方法,例如使用strcpylstrcpy,并明确指定拷贝的长度。

Win32窗口程序的实际演示

以下是一个完整的Win32窗口程序示例,用于演示缓冲区溢出的现象:

#include 
#include
/* buffer over demo,by bobo,2020-01-19 */LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc; PAINTSTRUCT ps; char buff[8] = {0}; char *p = "012345678912345"; switch (message) { case WM_CREATE: return 0; case WM_LBUTTONDOWN: hdc = GetDC(hwnd); lstrcpy(buff, p); TextOut(hdc, 100, 100, buff, 15); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam);}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("buffer over demo"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("buffer over demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;}

在这个程序中,缓冲区 buff 的大小为8字节,而源字符串的长度为15字节。当用户点击窗口时,程序会尝试将整个字符串拷贝到缓冲区,导致缓冲区溢出。然而,Win32窗口程序的表现与传统C程序不同:窗口不会立即崩溃,而是可能会输出部分字符串内容。

问题的本质

缓冲区溢出的本质是利用程序中的内存空间进行攻击。攻击者可以通过覆盖返回地址、函数表指针等关键位置,改变程序的执行流程。然而,缓冲区溢出的主要目的是提供一个攻击入口,而不是直接导致程序崩溃。

在实际应用中,缓冲区溢出攻击通常需要精确的条件,例如目标地址的位置和攻击向量的长度。如果攻击者能够掌握这些条件,就可以通过缓冲区溢出手段实现远程代码执行。

总结

缓冲区溢出是计算机安全中的一个重要概念,理解其原理对于开发安全程序至关重要。在编写C程序或Win32窗口程序时,始终应注意字符串拷贝的长度,避免因缓冲区溢出导致程序崩溃或被攻击。通过合理使用安全字符串函数和定位较小的目标缓冲区,可以有效防止这一问题。

转载地址:http://jouy.baihongyu.com/

你可能感兴趣的文章
Nio ByteBuffer组件读写指针切换原理与常用方法
查看>>
NIO Selector实现原理
查看>>
nio 中channel和buffer的基本使用
查看>>
NIO基于UDP协议的网络编程
查看>>
NISP一级,NISP二级报考说明,零基础入门到精通,收藏这篇就够了
查看>>
Nitrux 3.8 发布!性能全面提升,带来非凡体验
查看>>
NI笔试——大数加法
查看>>
NLog 自定义字段 写入 oracle
查看>>
NLog类库使用探索——详解配置
查看>>
NLP 基于kashgari和BERT实现中文命名实体识别(NER)
查看>>
NLP 项目:维基百科文章爬虫和分类【01】 - 语料库阅读器
查看>>
NLP_什么是统计语言模型_条件概率的链式法则_n元统计语言模型_马尔科夫链_数据稀疏(出现了词库中没有的词)_统计语言模型的平滑策略---人工智能工作笔记0035
查看>>
NLP学习笔记:使用 Python 进行NLTK
查看>>
NLP的神经网络训练的新模式
查看>>
NLP问答系统:使用 Deepset SQUAD 和 SQuAD v2 度量评估
查看>>
NLP:使用 SciKit Learn 的文本矢量化方法
查看>>
Nmap扫描教程之Nmap基础知识
查看>>
Nmap端口扫描工具Windows安装和命令大全(非常详细)零基础入门到精通,收藏这篇就够了
查看>>
NMAP网络扫描工具的安装与使用
查看>>
NMF(非负矩阵分解)
查看>>