Решая одну из задач в варгейме, я столкнулся со странным поведением сигнальной функции в 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]);
}
Что моя задача состоит в том, чтобы выполнить оболочку, которая выполняется из функции-ловушки, что означает, что если я каким-то образом смогу направить свой поток управления для запуска функции-ловушки - я готов. Один из методов, который я обнаружил для этого, заключался в том, чтобы использовать тот факт, что функция atoi принимает целые числа за вычетом минимального 32-битного знакового знака ie-2,147,483,647
, поэтому мы можем предоставить первый аргумент как -2,147,483,649
и второй аргумент как -1
что, наконец, приведет к значению 2,147,483,649
, передаваемому atoi, что приведет к SIGFPE. Этот подход прекрасно работает и на практике.
В чем я сомневаюсь, так это в том, что даже если мы используем описанный выше подход, оператор return выполняется после использования функции signal(). Как же тогда получается, что программа работает в обратном направлении на одну инструкцию и запускает функцию-обработчик catcher(), когда в использовании atoi присутствует SIGFPE?
SIGFPE
является неопределенным поведением. Кроме того,printf
иsystem
не являются безопасными асинхронными функциями и не должны вызываться в обработчике сигналов. - person kaylum   schedule 01.02.2016signal
просто устанавливает функцию, которая будет вызываться позже, когда произойдет сигнал. В основном это делаетsigfpe_handler = &catcher;
(гдеsigfpe_handler
на самом деле является некоторой переменной, к которой вы не можете получить прямой доступ) - person user253751   schedule 01.02.2016signal()
устанавливает функцию, которая будет вызываться при появлении указанного сигнала отправляется в программу. Когда этот сигнал поднимается, текущий поток прерывается и вызывается обработчик сигнала, который был установлен при вызовеsignal()
. - person Andrew Henle   schedule 01.02.2016