2012-12-11 45 views
0

關於同一條消息有other問題,但是當我嘗試執行一系列調用某些函數的機器代碼時,我似乎碰到了這個問題。在我的情況下,我打電話退出(0),在同一個程序中用C語言調用時可以正常工作。但是,如果作爲練習,我將EIP設置爲某些機器代碼的地址(你可以稱之爲「shellcode」),例如機器指令中出口(0)處的「訪問衝突讀數」?

const char code[] = 
"\x6A\x00"  // push  0" 
"\xFF\x15\x00\x00\x00\x00" //system call, 'read access violation': call dword ptr [__imp__exit] 
"\x5D" //pop ebp  
"\xC3"; //ret 

我會得到消息「Access violation reading location 0x00000000。」。 「\ x6A \ x00」指令將運行,但對exit(0)的調用將拋出此異常。

這是在VS2010中用/ GS-編譯的C,並且還運行帶有執行權限的「shellcode」,但是仍然存在某種不可執行的內存或堆棧保護嗎?爲什麼這條指令會導致錯誤?

int main() 
{ 

    void *exec = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
    memcpy(exec, code, sizeof(code)); 
//EIP = exec in debug->immediate 
    exit(0); 

} 
+1

你的字節值中顯然有很多零。這不會奇蹟般地被加載器重定位到__imp_exit,它不知道你的char []應該是代碼。你必須自己做。 –

回答

1

如果你拆開你的shellcode,你會得到這樣的事情(AT & T語法):

00000000 <_code>: 
    0: 6a 00     push $0x0 
    2: ff 15 00 00 00 00  call *0x0 
    8: 5d      pop %ebp 
    9: c3      ret 

call指令是通過地址0做一個內存間接跳轉:這是加載目標從內存地址0跳轉到該位置。由於內存地址0是無效的(極少數情況下它可以是有效的,但這也不例外),會導致訪問衝突。

通常,當您編譯C代碼時,跳轉到外部函數被佔位符替換,並且這些佔位符在鏈接時被鏈接器填充。當你在運行時生成shellcode時,你沒有鏈接器的幫助,所以你必須自己做。你需要弄清楚你想要的目標地址是什麼,並直接將其填入shellcode中,如果你不確切知道shellcode將要執行的地址,可能使用一些與位置無關的技巧。

+0

不,當他談論eip和ebp時,這不是x64代碼。 –

+0

@Hans:哎呀謝謝,修正。 –

+0

這就是改變地址的整個想法。 :-) –