安全編碼實踐之五地址空間格局隨機化ASLR

來源:互聯網
上載者:User

1.     概述: http://blog.csdn.net/chengyun_chu/article/details/4644227

在前面安全編碼實踐中我們介紹過GS編譯選項和緩衝溢出,以及資料保護DEP。首先,緩衝溢出的直接後果就是可能導致惡意代碼的遠程執行,於是編譯器提供了GS保護。但是,GS選項有自身的局限,存在若干方法可以繞過GS選項的保護。於是進一步,作業系統提供了資料執行防止,即DEP,以及與之對應的NXCOMPAT編譯選項。

那麼是不是現在我們就可以高枕無憂了?在安全領域中,系統的攻防是一個不斷髮展進化的過程。DEP提出後,就出現了針對DEP的Ret2libc攻擊手段。這一點我們曾在介紹DEP的安全編碼實踐文章的最後簡單提及過。

ASLR(Address Space Layout Randomization),地址空間格局的隨機化,就是用來防範Ret2libc攻擊手段的另一個重要的安全特性。那麼,什麼是Ret2libc攻擊,ASLR的原理是什麼,開發人員如何使用這個安全特性,就是我們這篇文章要探討的內容。

2.     DEP和Ret2libc攻擊

2.1 DEP對堆疊溢位的保護

在棧溢出介紹中提及到Windows體繫結構下函數堆棧布局(地址從高向低)如下:

調用參數

返回地址

EBP上層函數堆棧基址

異常處理代碼入口地址

(如果函數設定異常處理)

局部變數

表1:Windows系統的函數堆棧結構

 

如果發生堆疊溢位,惡意代碼通過覆蓋在堆棧(stack)上的局部變數,從而修改函數的返回地址,而導致惡意代碼執行。下面是這類攻擊方式的堆棧結構的一個典型例子。

調用參數

覆蓋方向—>

惡意代碼

返回地址

惡意代碼的入口地址

EBP上層函數堆棧基址

溢出的變數覆蓋地區,往往包括必要的填充位元組

異常處理代碼入口地址

(如果函數設定異常處理)

局部變數

表2:堆疊溢位時的堆棧結構

當DEP保護機制被使用後,由於惡意代碼是存放在系統的資料頁面(堆棧頁面上),那麼函數返回時,指令寄存器EIP將跳轉到惡意代碼的入口地址。此時該頁面是非可執行檔(non-executable),於是DEP就會觸發系統異常而導致程式中止。

2.2 Ret2libc攻擊

 

在上述的DEP保護機制中,可以看到關鍵是在函數返回時EIP跳轉到了非可執行頁面時被DEP檢測到。那麼Ret2libc的攻擊原理是,攻擊者設定的函數的返回地址並不直接指向惡意代碼,而是指向一個已存在的系統函數的入口地址。由於系統函數所在的頁面許可權是可執行檔,這樣就不會觸發DEP異常。

 

那麼,攻擊者應該將EIP控制指向那個特殊的系統入口函數?一個例子是在Unix 系統下,libc是一個共用的C動態執行庫,裡面有許多非常有用的函數,例如system函數。它的定義如下:

int system(const char *string);

 

函數system()可通過運行環境來執行其它程式,例如啟動Shell等等。那麼,攻擊者就可以通過構造以下的堆棧結構【1】:

 

調用參數

覆蓋方向—>

/bin/sh

虛假的返回地址

返回地址

system函數的入口地址

EBP上層函數堆棧基址

溢出的變數覆蓋地區,往往包括必要的填充位元組

異常處理代碼入口地址

(如果函數設定異常處理)

局部變數

表3:Ret2libc攻擊的堆棧結構

 

這樣,當發生堆疊溢位的函數返回時,EIP跳轉到system函數。因為system函數本身就是可執行檔,這時不會產生DEP異常。攻擊者通過構造system函數的調用參數來可以啟動其它程式。在攻擊過程中,函數返回到libc庫(return to libc)是關鍵,這也就是Ret2libc名字的來由。

細心的讀者也許已經發現,在表3中,沒有任何惡意代碼被插入。攻擊者雖然可以通過system或者其它系統函數來執行很多敏感的操作,但在多數情況下,還是更希望可以執行自身定製的惡意代碼。如何可以做到這一點?於是在最初的Ret2libc的攻擊方式的基礎上,又發展出特別針對Windows系統攻擊的手段。它的原理是通過VirtualProtect函數來修改惡意代碼所在記憶體頁面的執行許可權,然後再將控制轉移到惡意代碼。

VirtualProtect是Windows系統kernel32.dll提供的函數,其功能是修改調用進程所在虛擬位址空間(virtual  address)的記憶體地區的保護許可權。它的定義如下:

 

BOOL WINAPI VirtualProtect(

  __in   LPVOID lpAddress,

  __in   SIZE_T dwSize,

  __in   DWORD flNewProtect,

  __out  PDWORD lpflOldProtect

);

 

攻擊者構造以下的堆棧結構【2】來調用VirtualProtect:

 

 

調用參數

覆蓋方向—>

惡意代碼

lpflOldProtect值

設定可執行許可權參數

惡意字碼頁面的大小

惡意代碼所在記憶體頁面的基址

惡意代碼的入口地址

返回地址

VirtualProtect函數的入口地址

EBP上層函數堆棧基址

溢出的變數覆蓋地區,往往包括必要的填充位元組

異常處理代碼入口地址

(如果函數設定異常處理)

局部變數

表4:使用VirtualProtect攻擊的堆棧結構

 

首先,當發生堆疊溢位的函數返回時,EIP跳轉到VirtualProtect函數。注意到這裡攻擊者特別構造將惡意代碼的入口地址作為VirtualProtect函數退出時的返回地址。由於在VirtualProtect的執行過程中,惡意代碼所在的頁面被修改為可執行許可權,這樣當VirtualProtect返回時,EIP再跳轉到惡意代碼時就不會觸發任何DEP異常。

除了使用VirtualProtect函數,攻擊者還可以使用其它函數,例如NtSetInformationProcess等等。

3.     ASLR和/dynamicbase連結選項

在上面對Ret2libc攻擊方式的介紹中,我們看到最為關鍵的一點是攻擊者事先預知了特定函數,如system或VirtualProtect的入口地址。在Windows XP或Windows 2000上,這些函數的入口地址是固定的,即攻擊者事先可以確定的。

 

在Windows Vista中引入了ASLR安全特性。它的原理就是在當一個應用程式或動態連結程式庫,如kernel32.dll,被載入時,如果其選擇了被ASLR保護,那麼系統就會將其載入的基址隨機設定。這樣,攻擊者就無法事先預知動態庫,如kernel32.dll的基址,也就無法事先確定特定函數,如VirtualProtect,的入口地址了。

ASLR是系統一級的特性。系統動態庫,如kernel32.dll,載入地址,是在系統每次啟動的時候被隨機設定的。

 

下面是一個簡化的ASLR示範程式【3】。

 

// aslr.cpp : Demo the dynamic base of DLLs due to ASLR

//

 

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

 

void foo( void )

{

      printf( "Address of function foo = %p/n", foo );

}

 

int _tmain(int argc, _TCHAR* argv[])

{

      HMODULE hMod = LoadLibrary( L"Kernel32.dll" );

      // Note—this is for release builds

      HMODULE hModMsVc = LoadLibrary( L"MSVCR90.dll" );

 

      void* pvAddress = GetProcAddress(hMod, "LoadLibraryW");

      printf( "Kernel32 loaded at %p/n", hMod );

      printf( "Address of LoadLibrary = %p/n", pvAddress );

      pvAddress = GetProcAddress( hModMsVc, "system" );

      printf( "MSVCR90.dll loaded at %p/n", hModMsVc );

      printf( "Address of system function = %p/n", pvAddress );

 

      foo();

 

      if( hMod ) FreeLibrary( hMod );

      if( hModMsVc ) FreeLibrary( hModMsVc );

      return 0;

}

 

這段程式的目的是輸出kerner32.dll和msvcr90.dll的基址,loadlibrary和system函數的入口地址,以及應用程式本身一個函數foo()的入口地址。

使用ASLR非常簡單。從Visual Studio 2005 SP1開始,增加了/dynamicbase連結選項。/dynamicbase選項可以通過Project Property -> Configuration Properties -> Linker -> Advanced -> Randomized Base Address,或直接修改linker的命令列編譯選項即可。見。

 

圖1:/dynamicbase連結選項配置

在Visual Studio 2008環境,用Win32 Console Application類型,編譯連結示範程式。注意,如果使用Visual Studio 2005 SP1的話,需要將msvcr90.dll更改為msvcr80.dll。

如果程式沒有使用ASLR功能的話,在Windows Vista下運行。輸出的結果是:

Kernel32 loaded at 763F0000

Address of LoadLibrary = 7641361F

MSVCR90.dll loaded at 671F0000

Address of system function = 6721C88B

Address of function foo = 00401800

 

重啟系統

 

Kernel32 loaded at 76320000

Address of LoadLibrary = 7634361F

MSVCR90.dll loaded at 6A340000

Address of system function = 6A36C88B

Address of function foo = 00401800

 

我們看到,即使程式本身沒有使用ASLR,Kernel32.dll和MSVCR90.dll的載入地址也發生了變化。這是因為這兩個庫都已經選擇了被ASLR保護。但是應用程式自身foo()函數的地址是固定的。

如果程式使用ASLR功能的話,在Windows Vista下運行。輸出的結果是:

Kernel32 loaded at 763F0000

Address of LoadLibrary = 7641361F

MSVCR90.dll loaded at 671F0000

Address of system function = 6721C88B

Address of function foo = 003B1800

 

重啟系統

 

Kernel32 loaded at 76320000

Address of LoadLibrary = 7634361F

MSVCR90.dll loaded at 697A0000

Address of system function = 697CC88B

Address of function foo = 00871800

 

應用程式自身函數foo()的載入地址也隨著系統重啟發生了變化。即一旦使用了/dynamicbase選項,產生的程式在運行時候就會受到ASLR機制的保護。

4.     ASLR的局限

首先,ASLR安全特性只在Windows Vista和其後的Windows版本(如Windows Server 2008)中實現。

 

其次,ASLR是需要和DEP配合使用的。如果CPU不提供對於DEP的硬體支援,或者應用程式沒有選擇被DEP保護的話,惡意代碼一旦可以執行,就可以通過程式進程表結構來獲得特定DLL的載入基址。

 

就效能和相容性而言,ASLR的實現上都做了考慮,沒有太多的影響。一個範例是Microsoft Office 2007。Office 2007的程式全面使用ASLR功能,並沒有發現對其效能和相容性帶來太大的影響【4】

 

5.     總結

ASLR安全特性在Windows Vista和其後的Windows版本(如Windows Server 2008)中實現。它可以防範基於Ret2libc方式的針對DEP的攻擊。ASLR和DEP配合使用,能有效阻止攻擊者在堆棧上運行惡意代碼。建議開發人員使用/dynamicbase連結選項讓開發的應用程式或動態連結程式庫使用ASLR功能。

 

6.     參考文獻

【1】      Bypassing non-executable-stack during exploitation using return-to-libc,http://www.infosecwriters.com/text_resources/pdf/return-to-libc.pdf,c0ntex

【2】      A Brief History of Exploitation Techniques & Mitigations on Windows,

http://hick.org/~mmiller/presentations/misc/exploitation_techniques_and_mitigations_on_windows.pdf
Matt Miller

【3】      Writing Secure Code for Windows Vista, Michael Howard, David LeBlanc

【4】      Use of ASLR, NX, etc,http://blogs.msdn.com/david_leblanc/archive/2008/03/14/use-of-aslr-nx-etc.aspx,David LeBlanc

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.