Переполнение буфера — печать имени хоста/пользователя

Я пытаюсь выполнить атаку переполнения буфера на простой программе C, чтобы получить немного знаний о том, как это работает. Пока что у меня есть скрипт Python, который имеет кучу \ x90 и адрес возврата, который указывает на один из адресных слотов, который содержит часть салазок NOP. У меня есть код, который печатает имя хоста, но он написан не мной, и я не понимаю самого кода.

У меня была идея написать программу на C, которая выводит имя хоста с помощью uname -a, которую я мог бы разобрать на ассемблер, а затем преобразовать в шестнадцатеричный, но это дает мне много ассемблерного кода. Это дало бы мне больше информации о том, что на самом деле происходит, но с выводом в отношении кажется, что я делаю что-то не так.

Как мне создать/сгенерировать код оболочки, который делает именно это, печатает имя моего хоста? Я работаю над 32-битной системой Kali Linux.


person niyz    schedule 11.12.2018    source источник
comment
Знаете ли вы о команде linux 'hostname'?   -  person newbie    schedule 11.12.2018


Ответы (3)


Вам не нужно писать целую программу на C, а затем дизассемблировать ее.

Вы можете написать простую функцию C, которая делает только то, что вам нужно, а затем попросить GCC скомпилировать, но не ассемблировать и связать ее с помощью параметра -S.

Вы также можете включить флаг отладки -g, чтобы в сборке были некоторые отладочные данные, которые облегчат чтение.

Возьмите этот пример кода:

#include <unistd.h>

void get_hostname() {
    char buffer[100];
    gethostname(buffer, 100);
}

Если это полное содержимое файла hn.c, вы можете использовать следующую команду для создания файла hn.asm:

gcc -S -g hn.c -o hn.asm

В этом файле по-прежнему будет куча всего, что вам не нужно, но в нем также будет легко найти и наглядную сборку нужной вам функции:

.Ltext0:
    .globl  get_hostname
    .type   get_hostname, @function
get_hostname:
.LFB0:
    .file 1 "hn.c"
    .loc 1 3 0
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $112, %rsp
    .loc 1 3 0
    movq    %fs:40, %rax
    movq    %rax, -8(%rbp)
    xorl    %eax, %eax
    .loc 1 5 0
    leaq    -112(%rbp), %rax
    movl    $100, %esi
    movq    %rax, %rdi
    call    gethostname
    .loc 1 6 0
    movq    -8(%rbp), %rax
    xorq    %fs:40, %rax
    je  .L2
    call    __stack_chk_fail
.L2:
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

Затем вы можете передать это ассемблеру для генерации машинного кода, который вы хотите.

Обратите внимание на директивы .loc: они используются для сопоставления ассемблерного кода с номером строки исходного кода C. Вы можете использовать их так же, как это делает отладчик, чтобы узнать, какие строки сборки представляют какую строку кода C.

person Lev M.    schedule 11.12.2018

Вы можете просто использовать простой шелл-код /bin/sh и выполнить любую команду, которую захотите. Вот простой шеллкод для этого. Если вам все еще нужна именно эта команда, вы можете изменить строку команды, которую вы вставляете в шеллкод (uname -a вместо /bin/sh).

person user3725519    schedule 11.12.2018

Вот шеллкод, который я написал для x86 машины.

Шеллкод /bin/hostname :

"\x31\xc0\x50\x6a\x65\x68\x74\x6e\x61\x6d\x68\x2f\x68\x6f\x73\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x31\xc0\x50\x89\xe3\xb0\x01\xcd\x80"

Сборка :

global _start
section .text

_start:

xor     eax, eax  
push    eax
push    byte 0x65
push    dword 0x6d616e74
push    dword 0x736f682f
push    dword 0x6e69622f
mov     ebx, esp
push    eax
push    ebx
mov     ecx, esp
mov     al, 0xb
int     0x80

xor     eax, eax
push    eax
mov     ebx, esp
mov     al, 0x1
int     0x80
person VIII    schedule 10.01.2020