2012-02-16 63 views
4

我試圖用動態生成的代碼做一些令人討厭的hacky事情,並且我希望操作系統在它到達未知操作碼時向我發送SIGILL。這可以讓我添加一層關於我的程序的元信息等等。如何強制將SIGILL發送到我的程序?

但是,對於我的小測試程序,似乎OS不發送SIGILL,而是發送SIGBUS或SIGSEGV。我猜這意味着內存所在的頁面上有一個NX位。

有關如何使內存可執行的任何提示?

供參考,這是我的測試程序:

#include <stdio.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <string.h> 

void SIGILL_handler(int sig) 
{ 
    printf("Handling SIGILL\n"); 
} 

typedef void(*FUNC)(void); 

int main() 
{ 
    signal(SIGILL, SIGILL_handler); 

    int *bad = malloc(16); 
    memset(bad, 255, 16); 
    ((FUNC)bad)(); 

    printf("Returning like it's no big deal\n"); 

    return 0; 
} 

回答

6

mprotect這裏是你的朋友。它是POSIX兼容的(SVr4,POSIX.1-2001),所以它應該在OS X和Linux下工作。

int pagesize = sysconf(_SC_PAGE_SIZE); 
if (pagesize == -1) { 
    perror("sysconf"); 
    exit(1); 
} 

/* allocate 16 aligned pages */ 
void *bad = memalign(pagesize, 16 * pagesize); 
if (NULL == bad) { 
    fprintf("aah, out of mem :-(\n"); 
    exit(1); 
} 

if (-1 == mprotect(bad, 16 * pagesize, PROT_READ | PROT_WRITE | PROT_EXEC)) { 
    perror("mprotect"); 
    exit(1); 
} 

應該這樣做。

2nd編輯:memalign的兼容性似乎並不那麼容易。我想在OS X和Linux下嘗試memalign,valloc,如果兩者都不工作,只需使用常規的malloc並將足夠的字節添加到返回的指針,以便它與:-)對齊。

+3

還可以考慮使用[ 'mmap(3)'](http://linux.die.net/man/3/mmap),它允許您在一次系統調用中爲相應的保護位分配內存,並避免無意中更改保護位在恰好位於同一頁面的其他內存上。 – 2012-02-16 15:59:54

+0

@AdamRosenfield,好點!聽起來更好:-) – 2012-02-16 16:02:59

+0

我很想知道它是否工作。我在mmap中使用這種方法,但只獲取SIGSEGV。 'addr = mmap(NULL,8,PROT_EXEC,MAP_ANONYMOUS,0,0); ((FUNC)addr)();' – 2016-03-04 16:16:13

0

我意識到這是舊的,但如果其他人試圖迫使SIGILL一代那麼另一種選擇是使用內聯彙編如下所示:

asm(".byte 0x0f, 0x0b"); 

asm("ud2"); 
相關問題