各種內存攻擊技術簡介

除了基本的棧溢出利用,還有堆溢出、off by one、虛函數、格式化串等漏洞利用技術,下面進行簡單介紹。

1.off by one的利用

只溢出一個字節,,配合上特定的溢出場景, off by one 就有可能演化為安全漏洞。

void off_by_one(char * input)
{
  char buf[200];
  int i=0,len=0;
  len=sizeof(buf);
  for(i=0; input[i]&&(i<=len); i++)
  {
    buf[i]=input[i];
  }
}

“ i<=len”正確的使用應該是“ i<len”,給了一個字節的攻擊機會。當緩沖區后面緊跟著 EBP 和返回地址時,溢出數組的那一個字節正好“部分”地破壞了EBP。
當能夠讓 EBP 恰好植入可控制的緩沖區時,是有可能做到劫持進程的。此外, off by one問題有可能破壞重要的鄰接變量,從而導致程序流程改變或者整數溢出等更深層次的問題。

2.攻擊C++虛函數

C++虛函數的入口地址被統一保存在虛表( Vtable)中,虛表指針保存在對象的內存空間中,緊接著虛表指針的是其他成員變量。

#include "windows.h"
#include "iostream.h"
char shellcode[]="xxx";////set fake virtual function pointer
class Hacktest
{
public:
    char buf[200];
    virtual void test(void)
    {
        cout<<"Class Vtable::test()"<<endl;
    }
};
Hacktest overflow, *p;
void main(void)
{
    char * p_vtable;
    p_vtable=overflow.buf-4;//point to virtual table
    //reset fake virtual table to 0x004088cc
    //the address may need to ajusted via runtime debug
    p_vtable[0]=0xCC;
    p_vtable[1]=0x88;
    p_vtable[2]=0x40;
    p_vtable[3]=0x00;
    strcpy(overflow.buf,shellcode);//set fake virtual function pointer
    p=&overflow;
    p->test();
}

( 1)虛表指針位于成員變量 char buf[200]之前,程序中通過 p_vtable=overflow.buf-4 定位到這個指針。
( 2)修改虛表指針指向緩沖區的 0x004088CC 處。
( 3)程序執行到 p->test()時,將按照偽造的虛函數指針去 0x004088CC 尋找虛表,這里正好是緩沖區里 shellcode 的末尾。在這里填上 shellcode 的起始位置 0x0040881C 作為偽造的虛函數入口地址,程序將最終跳去執行 shellcode,如下圖所示。

由于虛表指針位于成員變量之前,溢出只能向后覆蓋數據,所以有一定局限性。對象的內存空間位于堆中,如果內存中存在多個對象且能夠溢出到下一個對象空間中去,“連續性覆蓋”還是有攻擊的機會的,如下圖所示。

3.Heap Spray:堆噴射

在針對瀏覽器的攻擊中,常常會結合使用堆和棧協同利用漏洞。
(1)當瀏覽器或其使用的 ActiveX 控件中存在溢出漏洞時,攻擊者就可以生成一個特殊的 HTML文件來觸發這個漏洞。
( 2)不管是堆溢出還是棧溢出,漏洞觸發后最終能夠獲得 EIP。
( 3)有時我們可能很難在瀏覽器中復雜的內存環境下布置完整的 shellcode。
( 4)頁面中的 JavaScript 可以申請堆內存,因此,把 shellcode 通過 JavaScript 布置在堆中成為可能。

在使用 Heap Spray 的時候,一般會將 EIP 指向堆區的 0x0C0C0C0C 位置,然后用 JavaScript申請大量堆內存,并用包含著 0x90 和 shellcode 的“內存片”覆蓋這些內存。

通常, JavaScript 會從內存低址向高址分配內存, 因此申請的內存超過 200MB( 200MB=200 × 1024× 1024 = 0x0C800000 > 0x0C0C0C0C)后, 0x0C0C0C0C 將被含有 shellcode 的內存片覆蓋。只要內存片中的 0x90 能夠命中 0x0C0C0C0C 的位置, shellcode 就能最終得到執行。

var nop=unescape("%u9090%u9090");
while (nop.length<= 0x100000/2)
{
    nop+=nop;
}//生成一個 1MB 大小充滿 0x90 的數據塊
nop = nop.substring(0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2 );
var slide = new Arrary();
for (var i=0; i<200; i++)
{
    slide[i] = nop + shellcode
}

Java 會為申請到的內存填上一些額外的信息,為了保證內存片恰好是 1MB,我們將這些額外信息所占的空間減去。nop = nop.substring(0, 0x100000/2 - 32/2 - 4/2 - shellcode.length - 2/2 )將一個內存片恰好湊成 1MB 大小。

4.格式化串漏洞

4.1 printf中的缺陷

#include "stdio.h"
main()
{
    int a=44,b=77;
    printf("a=%d,b=%d\n",a,b);
    printf("a=%d,b=%d\n");
}

第二個printf并不會編譯報錯,運行輸出如下:

雖然函數調用時沒有給出“輸出數據列表”,但系統仍然按照“格式控制符”所指明的方式輸出了棧中緊隨其后的兩個 DWORD。現在應該明白輸出“ a=4218928,b=44”的原因了:4218928 的十六進制形式為 0x00406030,是指向格式控制符“ a=%d,b=%d\n”的指針。

4.2 用printf讀取內存數據
如果傳入的字符串中帶有格式控制符時, printf 就會打印出棧中“莫須有”的數據。
例如,輸入“ %p,%p,%p……”,實際上可以讀出棧中的數據。

#include "stdio.h"
int main(int argc, char ** argv)
{
  printf(argv[1]);
}

4.3 用printf向內存寫數據
在格式化控制符中,有一種鮮為人知的控制符%n。這個控制符用于把當前輸出的所有數據的長度寫回一個變量中去。

#include "stdio.h"
int main(int argc, char ** argv)
{
    int len_print=0;
    printf("before write: length=%d\n",len_print);
    printf("hacktest:%d%n\n",len_print,&len_print);
    printf("after write: length=%d\n",len_print);
}

第二次 printf 調用中使用了%n 控制符,它會將這次調用最終輸出的字符串長度寫入變量len_print 中。“hacktest:0”長度為 10,所以這次調用后 len_print 將被修改為 10。

4.4 格式化串漏洞的檢測
當輸入輸出函數的格式化控制符能夠被外界影響時,攻擊者可以綜合利用前面介紹的讀內存和寫內存的方法修改函數返回地址,劫持進程,從而使 shellcode 得到執行。
比起大量使用命令和腳本的 UNIX 系統, Windows 操作系統中命令解析和文本解析的操作并不是很多,再加上這種類型的漏洞發生的條件比較苛刻,使得格式化串漏洞的實際案例非常罕見。
格式化串漏洞的起因非常簡單,只要檢測相關函數的參數配置是否恰當就行。通過簡單的靜態代碼掃描,一般可以比較容易地發現這類漏洞。

int printf( const char* format [, argument]... );
int wprintf( const wchar_t* format [, argument]... );
int fprintf( FILE* stream, const char* format [, argument ]...);
int fwprintf( FILE* stream, const wchar_t* format [, argument ]...);
int sprintf( char *buffer, const char *format [, argument] ... );
int swprintf( wchar_t *buffer, const wchar_t *format [, argument] ... );
int vprintf( const char *format, va_list argptr );
int vwprintf( const wchar_t *format, va_list argptr );
int vfprintf( FILE *stream, const char *format, va_list argptr );
int vfwprintf( FILE *stream, const wchar_t *format, va_list argptr );
int vsprintf( char *buffer, const char *format, va_list argptr );
int vswprintf( wchar_t *buffer, const wchar_t *format, va_list argptr );

5.SQL 注入原理

SQL 命令注入的漏洞是 Web 系統特有的一類漏洞,它源于 PHP、 ASP 等腳本語言對用戶輸入數據和解析時的缺陷。
當攻擊者把用戶名輸入為 admin’#的時候,輸入字串中的單引號將和腳本中的變量的單引號形成配對,而輸入字串中的“ #”號對于 My SQL 的語言解釋器來說是一行注釋符。通過這樣的輸入,攻擊者可以輕易繞過身份驗證機制,沒有正確的密碼也能看到管理員的信息。

注入攻擊的檢測與防范:

  • 檢測:
    SQL注入掃描:NGSSQuirreL
  • 防范:
    一種十分有效的防止 SQL 注入的方法是使用參數化查詢( Parameterized Query)的方法。參數化查詢就是在訪問數據庫時,將查詢語句中要填入的數據通過參數的方式傳遞,這樣數據庫不會將參數的內容視為 SQL 語句的一部分,因此即便參數中含有攻擊者構造的查詢指令,也不會被執行。
string sql = "select * from users where username=? and password=?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1,username);
pstmt.setString(2,password);//username 和 password 兩個變量的值是由用戶輸入的

6.XSS攻擊

XSS 是跨站腳本(Cross Site Script)的意思,由于網站技術中的 Cascading Style Sheets 縮寫為 CSS,為了不至于產生概念混淆,故一般用 XSS 來簡稱跨站腳本。

在很多 Web 應用中,服務器都將客戶端輸入或請求的數據“經過簡單的加工”后,再以頁面文本的形式返回給客戶端。

當用戶進行正常的請求,"http://testapp.com/test.php?input=this is a test",服務器將簡單地把“ this is a test”返回給客戶端的瀏覽器。
當請求"http://testapp.com/test.php?input=<script>alert(‘xss’);</script>",服務器也會把“<script>alert(‘xss’);</script>” 當字符串返回給客戶端瀏覽器,瀏覽器在解析這次反饋的頁面時,發現頁面中的是腳本命令,而不是數據,因此會把“ <script>alert(‘xss’);</script>”當做腳本命令進行解析,進而執行,彈出一個警告消息框。

<?php
echo $input
?>

XSS 攻擊的目標是客戶端的瀏覽器,因此受影響的范圍要遠遠大于攻擊服務器的 SQL 注入攻擊;獨立的 XSS 漏洞攻擊并不是非常嚴重,但是配合上其他攻擊技術往往能產生非常嚴重的后果。

7.路徑回溯漏洞

windows中“ ../”或者“ ..\”,Linux中的“ ../”,在路徑中表示“上一級”,當足夠多的“ ..”使得路徑跳轉到根目錄時,多余的“ ..”將被忽略掉。
例如有這樣一個URL:http://www.testsite.com/download.asp?file=document.pdf
如果沒有回溯檢查,可構造URL獲取敏感文件:http://www.testsite.com/download.asp?file=../../../../etc/passwd

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容

  • 概說 前面的文章演示的攻擊都是在關閉了linux的各種防御機制的情況下進行的,下面我們探討一下更高級的linux漏...
    讀書郞閱讀 4,091評論 2 7
  • 緩沖區溢出(Buffer Overflow)是計算機安全領域內既經典而又古老的話題。隨著計算機系統安全性的加強,傳...
    Chivalrous閱讀 1,342評論 0 5
  • 什么是XSS? 跨站腳本(Cross-Site Scripting,XSS)是一種經常出現在 Web 應用程序中的...
    lokisteven閱讀 1,550評論 0 2
  • 0. 引言 如果你學的第一門程序語言是C語言,那么下面這段程序很可能是你寫出來的第一個有完整的 “輸入---處理-...
    pandolia閱讀 14,181評論 13 27
  • 可以認錯,但不能認輸。可以追求勝利,但不要否定失敗,可以信奉真理,但更不應看低謬論。 錯得,為什么就一定是錯的...
    痞子的幸福白羊閱讀 238評論 0 0