当我在解决战争游戏中的一个问题时,我在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 位有符号 interger 的事实,即 -2,147,483,647
,所以我们能做的是提供第一个参数作为-2,147,483,649
,第二个参数作为-1
,最终将导致值2,147,483,649
传递给 atoi 并将导致 SIGFPE。这种方法实际上也很好用。
我在这里怀疑的是,即使我们使用上述方法,return 语句也会在使用 signal(( 函数后执行。那么,当 atoi 的使用中有 SIGFPE 时,程序如何通过一条指令向后运行并启动 catcher(( 处理程序函数?
那么,当 atoi 的使用中有 SIGFPE 时,程序如何通过一条指令向后运行并启动 catcher(( 处理程序函数?
其实不然。 signal(SIGFPE, catcher);
告诉Linux内核,"嘿,如果我得到SIGFPE
,打电话catcher
,好吗?
然后当你的程序得到一个SIGFPE
,就像你问的那样,内核确保catcher
被调用 - 而不是杀死你的程序,如果你没有要求它调用catcher
,它通常会这样做。