2012-12-10 64 views
0

我在C一個簡單的程序,與編譯器開關:/ GS-訪問衝突在Visual C++ 2010

這僅僅是一個改變EIP的機器代碼串的位置的概念驗證。

比方說,我們設置EIP = 0x012f5000,這使該EIP在下面的數組的地址:

char code[] = "\x00\x00\x8B\x00\x00";

我不知道究竟這些指令會做,但X00的指令出現成爲noops。將EIP切換到程序中的任何其他位置似乎會導致問題,但是當我將EIP指向此陣列的地址時,在EIP的該位置會出現一些「訪問衝突」異常。

爲什麼我會收到此錯誤?這是因爲某種Windows保護機制?還是Windows不能以這種字符串形式運行intructions?你如何讓程序執行這些指令?

+0

其中底層CPU執行的機器代碼?如果x86然後0x00不是'NOP'。 'NOP'具有操作碼'0x90'。 –

+0

@ Fermat2357:有很多有效的操作碼是'NOP',而不僅僅是單字節操作碼'0x90'。 – 0xC0000022L

+0

是的,我的錯,如果你發現所有可能的指令都是「NOP」,你就是對的。 –

回答

2

我你使用的x86 32位機的代碼,如果沒有我的答案是不正確的猜測。

你的機器代碼提供了以下

0000   ADD BYTE PTR DS:[EAX],AL 
8B00   MOV EAX,DWORD PTR DS:[EAX] 
00XX   ADD BYTE PTR ??? ; depends on the next byte 

正如你可以看到,如果你試着執行這一點,嘗試任何在eax是地址來訪問內存。它也不會以ret或別的東西結束,所以它會直接前進而無需關心接下來的內容。在大多數情況下,這會崩潰。無論如何,您也可能無法執行DATA段中定義的代碼。

如果你想執行的shellcode,你可以嘗試像下面這個簡單的模板。這個想法是在堆棧上創建代碼並在那裏執行代碼。給定的機器代碼函數沒有很好地實現,但至少是正確的,不會導致崩潰。它相當於C代碼

void f(void) { return; }; 

由調試模式下的VC++編譯。

#include <stdio.h> 

int main() 
{ 
    const char code[] = "\x55\x8B\xEC\x81\xEC\xC0\x00\x00" 
    "\x00\x53\x56\x57\x8D\xBD\x40\xFF" 
    "\xFF\xFF\xB9\x30\x00\x00\x00\xB8" 
    "\xCC\xCC\xCC\xCC\xF3\xAB\x5F\x5E" 
    "\x5B\x8B\xE5\x5D\xC3"; 

    printf("Start execution\r\n"); 
    ((void (*)())code)(); 
    printf("End execution\r\n"); 
    _getch(); 
} 

如果上述不工作,你可以嘗試。

#include "stdafx.h" 
#include <stdio.h> 
#include <Windows.h> 

int main() 
{ 
    const char code[] = "\x55\x8B\xEC\x81\xEC\xC0\x00\x00" 
    "\x00\x53\x56\x57\x8D\xBD\x40\xFF" 
    "\xFF\xFF\xB9\x30\x00\x00\x00\xB8" 
    "\xCC\xCC\xCC\xCC\xF3\xAB\x5F\x5E" 
    "\x5B\x8B\xE5\x5D\xC3"; 

    void *exec = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
    memcpy(exec, code, sizeof(code)); 

    printf("Start execution\r\n"); 
    ((void(*)())exec)(); 
    printf("End execution\r\n"); 
    //_getch(); 
} 

這個想法是使用分配的內存頁與標誌PAGE_EXECUTE_READWRITE

+0

你也應該確保你沒有在這個程序中啓用DEP。或者如果您這樣做,則需要使用VirtualProtect將內存更改爲可執行文件。 – jcopenha

+0

@Fermat這是一個很好的答案,但我使用/ NXCOMPAT編譯了VS2010中的確切源代碼:NO,並且仍然出現「訪問衝突」異常。 –

+0

是的,我看到,我在VS2010和Win7下有相同的行爲。在這種情況下,這是一項安全功能。我不知道一個編譯器標誌去除這個,所以我更新了我的答案更安全的方法。 –

0

費馬的回答是不錯,但我喜歡這個更好一點

__asm { jmp [exec] }