Атака переполнения буфера, выполнение невызванной функции

Итак, я пытаюсь использовать эту программу, которая имеет уязвимость переполнения буфера, чтобы получить/вернуть секрет за заблокированным .txt (read_secret()).

уязвимый.c // здесь нет правок

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

void read_secret() {
    FILE *fptr = fopen("/task2/secret.txt", "r");
    char secret[1024];
    fscanf(fptr, "%512s", secret);
    printf("Well done!\nThere you go, a wee reward: %s\n", secret);
    exit(0);
}

int fib(int n)
{
   if ( n == 0 )
      return 0;
   else if ( n == 1 )
      return 1;
   else
      return ( fib(n-1) + fib(n-2) );
} 

void vuln(char *name)
{
    int n = 20;
    char buf[1024];
    int f[n];
    int i;
    for (i=0; i<n; i++) {
      f[i] = fib(i);
    }
    strcpy(buf, name);
    printf("Welcome %s!\n", buf);
    for (i=0; i<20; i++) {
      printf("By the way, the %dth Fibonacci number might be %d\n", i, f[i]);
    } 
}


int main(int argc, char *argv[])
{
    if (argc < 2) {
        printf("Tell me your names, tricksy hobbitses!\n");
        return 0;
    }

    // printf("main function at %p\n", main);
    // printf("read_secret function at %p\n", read_secret);
    vuln(argv[1]);
    return 0;
}

Attack.c //будет редактироваться

#!/usr/bin/env bash
/task2/vuln "$(python -c "print 'a' * 1026")"

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

Но я довольно застрял здесь. Я знаю, что мне придется использовать GDB, чтобы получить адрес функции read_secret, но я немного запутался. Я знаю, что мне придется заменить адрес main() адресом функции read_secret, но я не знаю, как это сделать.

Спасибо


person Anon Li    schedule 20.03.2019    source источник


Ответы (1)


Если вы хотите выполнить функцию через уязвимость переполнения буфера, вы должны сначала определить смещение, при котором вы можете получить segfault. В вашем случае я предполагаю, что это 1026. Вся игра заключается в том, чтобы перезаписать eip (что говорит программе, что делать дальше), а затем добавить свою собственную инструкцию.

Чтобы добавить свою собственную инструкцию, вам нужно знать адрес указанной инструкции, а затем в gdb откройте вашу программу и введите:

x function name

Затем скопируйте адрес. Затем вам нужно преобразовать его в формат с прямым или прямым порядком байтов. Я делаю это с помощью модуля struct в python.

import struct
struct.pack("<I", address) # for little endian for big endian its different

Затем вы должны добавить его к вашему входу в двоичный файл, например: python -c "print 'a' * 1026 + 'the_address'" | /task2/vuln # в оболочке bash, а не в скрипте

Если все это не работает, просто добавьте еще несколько символов к смещению. Может быть что-то, чего вы не ожидали.

python -c "print 'a' * 1034 + 'the_address'" | /task2/vuln

Надеюсь это ответит на твой вопрос.

person james beastly    schedule 07.09.2019