【问题标题】:Signal handler function call ambiguity信号处理函数调用歧义
【发布时间】:2016-02-01 00:44:54
【问题描述】:

当我在一个兵棋推演中解决一个问题时,我遇到了 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]);
}

我的任务是执行从 catcher 函数执行的 shell,这意味着如果我能够引导我的控制流运行 catcher 函数 - 我已经完成了。我发现的一种方法是使用 atoi 函数接受小于最小 32 位有符号整数的整数的事实,即-2,147,483,647,所以我们可以做的是提供第一个参数为-2,147,483,649,第二个参数为@ 987654325@ 最终将导致值 2,147,483,649 传递给 atoi 并将导致 SIGFPE。这种方法实际上也很有效。

我这里的疑问是,即使我们使用上述方法,return 语句也是在使用 signal() 函数之后执行的。那么,在atoi的使用中有SIGFPE的情况下,程序是如何反向运行一条指令并启动catcher()处理函数的呢?

【问题讨论】:

  • Posix 声明在 SIGFPE 之后继续是未定义的行为。此外,printfsystem 不是异步安全函数,不得在信号处理程序中调用。
  • signal 只是将函数设置为稍后在信号发生时调用。它基本上是sigfpe_handler = &amp;catcher;(其中sigfpe_handler实际上是一些你不能直接访问的变量)
  • @immibis 那么这是否意味着在遇到 signal() 函数时,程序会启动另一个线程,然后等待指定的中断发生?
  • 我想你的意思是使用-2147483648和-1来触发信号。
  • @ShivanshRai 这是否意味着在遇到 signal() 函数时,程序会启动另一个线程,然后等待指定的中断发生? 否。signal() 安装当指定的信号发送到程序时将调用的函数。当该信号发出时,当前线程被中断,并调用与调用 signal() 一起安装的信号处理程序。

标签: c signals atoi


【解决方案1】:

在atoi的使用中有SIGFPE的情况下,程序是如何反向运行一条指令并启动catcher()处理函数的?

它没有。 signal(SIGFPE, catcher); 告诉 Linux 内核,“嘿,如果我得到 SIGFPE,请致电 catcher,好吗?”

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

【讨论】:

  • 我现在明白了,谢谢。 try-catch 块的情况是否相同?即使在那里我们指定了特定的异常,当遇到这些异常时,执行指定的指令而不是杀死程序。
  • @ShivanshRai 它们完全不同,但总体思路相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-11
  • 1970-01-01
  • 1970-01-01
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多