当我在战争游戏中解决其中一个问题时,我在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。这种方法实际上也很好。
我怀疑的是,即使我们使用上述方法,也会在使用signal()函数之后执行return语句。那么当atoi的使用中存在SIGFPE时,程序是如何通过一条指令向后运行并启动catcher()处理函数的呢?
答案 0 :(得分:1)
当atoi的使用中存在SIGFPE时,程序如何通过一条指令向后运行并启动catcher()处理函数?
没有。 signal(SIGFPE, catcher);
告诉Linux内核,“嘿,如果我得到SIGFPE
,请致电catcher
,好吗?”
然后当你的程序获得SIGFPE
时,就像你问的那样,内核确保调用catcher
- 而不是杀死你的程序,这是你通常会做的事情,如果你没有要求它致电catcher
。