#include <stdio.h>
#include <string.h>
int main(void)
{
char buff[8] = {0};
char *p = "012345678912345";
strcpy(buff,p);
printf("%s\n",buff);
return 0;
}
这是缓冲区溢出原理演示的基本C程序;
p所指向的字符串长度大于buff的长度,拷贝时发生缓冲区溢出;程序崩溃;
如果p指向字符串的长度不超过,就不会溢出;
对于Win32来说,使用Windows提供的Win32字符串函数,字符串拷贝使用lstrcpy;
#include <stdio.h>
#include <windows.h>
int main(void)
{
char buff[8] = {0};
char *p = "0123456789";
lstrcpy(buff,p);
printf("%s\n",buff);
return 0;
}
一样的,长度超过,运行程序,崩溃;
如果使用安全版的字符串拷贝函数,strncpy(buff,p,sizeof(buff));
就不会溢出;
下面来作一个Win32窗口版本溢出程序;单击鼠标左键执行拷贝并输出;
/* buffer over demo,by bobo,2020-01-19 */
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, 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 ;
}
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) ;
}
buff长度8,p指向内容长度15;
按理程序应该崩溃;但是Win32窗口程序真的没崩溃;还输出了15个长度的字符串;
啥情况?
以上是Win10,VC++6;
此程序仅演示缓冲区溢出最基本原理;
如果真能干这事的人,其目的并不是引起程序崩溃,而是通过覆盖程序返回地址等手段,改变程序的执行流程;