如何强制将SIGILL发送到我的程序?

时间:2012-02-16 15:43:07

标签: c linux macos signals

我尝试使用动态生成的代码做一些讨厌的hacky事情,我希望操作系统在遇到未知的操作码时向我发送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;
}

2 个答案:

答案 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);
}

应该这样做。

第二次编辑:memalign的兼容性似乎并不那么容易。我在OS X和Linux下尝试memalignvalloc,如果两者都不起作用,只需使用常规malloc并为返回的指针添加足够的字节,使其对齐:-)。

答案 1 :(得分:0)

我意识到这是旧的,但如果其他人试图强制生成SIGILL,那么另一种选择是使用内联汇编,如下所示:

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

asm("ud2");