Как использовать уязвимость printf для разных методов ввода?

Я пытаюсь использовать уязвимость printf с помощью следующего кода C:

#include <stdio.h>
#include <stdlib.h>

/*
gcc -fno-stack-protector -z execstack -o test test.c
*/
void attack(){
    printf("Dropping to shell...\n");
}

int main(int argc, char **argv){
    char buf[100];

    printf("Enter user name:");

    gets(buf);  // what if using: scanf("%s",buf); ?

    printf("buffer (%d): %s\n",strlen(buf), buf);

    return 0;
}

Затем я пытаюсь изменить printf @ plt, чтобы перейти к функции атаки, переписав значение в 0x804a00c

08048370 <printf@plt>:
 8048370:   ff 25 0c a0 04 08       jmp    *0x804a00c
 8048376:   68 00 00 00 00          push   $0x0
 804837b:   e9 e0 ff ff ff          jmp    8048360 <_init+0x28>

Я использовал следующую команду для тестирования в GDB, я пытаюсь изменить значение в 0x804a00c на 0x00000041, чтобы убедиться, что я могу его изменить. Затем я могу изменить его на адрес атаки ().

gdb-peda$ r
Starting program:
Enter user name:$(printf "\x0c\xa0\x04\x08").%60x%5\$n

Однако у меня это не работает, адрес не меняется, я проверил значение в стеке (обрыв на адресе printf ()) и получил:

[------------------------------------stack-------------------------------------]
0000| 0xbffff070 --> 0x80485c6 ("buffer (%d): %s\n")
0004| 0xbffff074 --> 0x26 ('&')
0008| 0xbffff078 --> 0xbffff08c ("$(printf \"\\x0c\\xa0\\x04\\x08\").%60x%5\\$n")
0012| 0xbffff07c --> 0x0 
0016| 0xbffff080 --> 0xbffff134 --> 0x4a91b2bc 
0020| 0xbffff084 --> 0xbffff0a8 (".%60x%5\\$n")
0024| 0xbffff088 --> 0xbffff0a0 ("04\\x08\").%60x%5\\$n")
0028| 0xbffff08c ("$(printf \"\\x0c\\xa0\\x04\\x08\").%60x%5\\$n")

Думаю, я не передал правильное значение, так как оно изменилось на другой формат. Я предполагаю, что это из-за gets (), потому что я могу передать его правильно, когда использую argv для передачи: $ (printf "\ x0c \ xa0 \ x04 \ x08").% 60x% 5 \ $ n.

Так кто-нибудь знает, как решить проблему? и, кроме того, что, если ввод использует scanf (% s, buf), поскольку я получаю в стеке следующее, что также неверно.

[------------------------------------stack-------------------------------------]
0000| 0xbffff070 --> 0x80485f9 ("buffer (%d): %s\n")
0004| 0xbffff074 --> 0x8 
0008| 0xbffff078 --> 0xbffff08c ("$(printf")
0012| 0xbffff07c --> 0x0 
0016| 0xbffff080 --> 0xbffff134 --> 0x4f936a87 
0020| 0xbffff084 --> 0xbffff0a8 --> 0xb7e21c34 --> 0x2aad 
0024| 0xbffff088 --> 0xbffff0a0 --> 0xffffffff 
0028| 0xbffff08c ("$(printf")

person Eudaemon    schedule 19.09.2016    source источник


Ответы (1)


У вас есть пара заблуждений.

Во-первых, $(cmd) - это подстановка команд оболочки. Это полезно при передаче аргументов: например, ./foo $(python -c 'print "A"*4') эквивалентно ./foo AAAA. Если ваша программа принимает ввод из стандартного ввода, вы должны использовать канал: например, python -c 'print "A"*4' | ./foo эквивалентно запуску ./foo и вводу AAAA на клавиатуре.

Во-вторых, в вашем коде на самом деле нет уязвимости строки формата. Однако происходит переполнение буфера стека (на gets или scanf). Уязвимость строки формата возникает, когда вы вызываете такие функции, как printf of scanf, со строкой формата, управляемой пользователем. Если хотите, можете поменять последний printf на:

printf("buffer (%d): ", strlen(buf));
printf(buf); // <-- this is vulnerable
printf("\n");

Что касается разницы между gets(buf) и scanf("%s", buf): оба будут останавливаться на новой строке / EOF, но scanf также остановится на пробеле (что можно увидеть в вашем выводе, где читается только $(printf).

person Andrea Biondo    schedule 19.09.2016
comment
Большое спасибо, но могу ли я как-нибудь протестировать это в GDB? поскольку я не могу запустить python для печати этих значений внутри gdb. - person Eudaemon; 19.09.2016
comment
@Eudaemon Поместите свой ввод в файл (скажем, он называется input), затем используйте перенаправление из GDB: run < input. - person Andrea Biondo; 19.09.2016
comment
вы можете сделать это и без другого файла. reverseengineering.stackexchange.com/a/20542/27340 - person yehuda corsia; 03.02.2019