信号处理函数调用歧义

Signal handler function call ambiguity

当我在解决兵棋中的一个问题时,我遇到了 C 中信号函数的奇怪行为。据我了解,

void (*signal(int sig, void (*func)(int)))(int)

sig是这里遇到调用处理函数func的信号编号。 我试图在其中找到漏洞利用的代码是

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

void catcher(int a)
{
    setresuid(geteuid(),geteuid(),geteuid());
    printf("WIN!\n");
    system("/bin/sh");
    exit(0);
}

int main(int argc, char **argv)
{
    if (argc != 3 || !atoi(argv[2]))
            return 1;
    signal(SIGFPE, catcher);
    return abs(atoi(argv[1])) / atoi(argv[2]);
}

我的任务是执行从捕手函数执行的 shell,这意味着如果无论如何我能够将我的控制流引导到 运行 捕手函数 - 我是完毕。我发现的一种方法是使用 atoi 函数接受整数减去最小 32 位带符号整数,即 -2,147,483,647,所以我们可以做的是将第一个参数提供为 -2,147,483,649 和第二个参数为 -1 最终将导致值 2,147,483,649 被传递给 atoi 并将导致 SIGFPE。这种方法在实践中也很有效。

这里我怀疑的是,即使我们使用上面的方法, return 语句是在使用 signal() 函数之后执行的。那么程序是如何运行在atoi的用法中出现SIGFPE时,向后执行一条指令并启动catcher()处理函数的呢?

How is it then that the program is running backwards by one instruction and launching the catcher() handler function when there is SIGFPE in the usage of atoi?

没有。 signal(SIGFPE, catcher); 告诉 Linux 内核,"Hey, if I ever get a SIGFPE, call catcher, okay?"

然后当你的程序得到一个 SIGFPE 时,就像你问的那样,内核确保 catcher 被调用 - 而不是杀死你的程序,如果你没有,它通常会这样做'要求它调用 catcher.