Как я могу вызвать переполнение буфера? - PullRequest
31 голосов
/ 25 февраля 2010

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

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

void g()
{
    printf("now inside g()!\n");
}


void f()
{   
    printf("now inside f()!\n");
    // can only modify this section
    // cant call g(), maybe use g (pointer to function)
}

int main (int argc, char *argv[])
{
    f();
    return 0;
}

Хотя я не уверен, что делать дальше. Я думал об изменении адреса возврата для счетчика программы, чтобы он перешел непосредственно к адресу g (), но я не уверен, как получить к нему доступ. В любом случае, советы будут отличными.

Ответы [ 5 ]

13 голосов
/ 25 февраля 2010

Основная идея состоит в том, чтобы изменить адрес возврата функции, чтобы при возврате функция продолжала выполняться по новому взломанному адресу. Как это сделал Нильс в одном из ответов, вы можете объявить часть памяти (обычно массив) и переполнить ее таким образом, чтобы адрес возврата также был перезаписан.

Я бы посоветовал вам не принимать вслепую ни одну из программ, представленных здесь, без реального понимания того, как они работают. Эта статья очень хорошо написана, и вы найдете ее очень полезной:

Пошаговое руководство по уязвимости переполнения буфера

11 голосов
/ 25 февраля 2010

Это зависит от компилятора, поэтому ни один ответ не может быть дан.

Следующий код сделает то, что вы хотите для gcc 4.4.1. Компиляция с отключенными оптимизациями (важно!)

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

void g()
{
    printf("now inside g()!\n");
}


void f()
{   
  int i;
  void * buffer[1];
  printf("now inside f()!\n");

  // can only modify this section
  // cant call g(), maybe use g (pointer to function)

  // place the address of g all over the stack:
  for (i=0; i<10; i++)
     buffer[i] = (void*) g;

  // and goodbye..
}

int main (int argc, char *argv[])
{
    f();
    return 0;
}

Выход:

nils@doofnase:~$ gcc overflow.c
nils@doofnase:~$ ./a.out
now inside f()!
now inside g()!
now inside g()!
now inside g()!
now inside g()!
now inside g()!
now inside g()!
Segmentation fault
7 голосов
/ 25 февраля 2010

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

Я изучил эту технику, прочитав превосходную (хотя и немного устаревшую) статью / руководство по использованию уязвимостей, связанных с переполнением буфера Уничтожение стека для удовольствия и получения прибыли .

3 голосов
/ 19 июня 2010

Хотя это решение не использует метод переполнения для перезаписи адреса возврата функции в стеке, оно все равно заставляет g() вызываться из f() при его возвращении в main() только путем изменения f() и не звонить g() напрямую.

Функция эпилога -подобная встроенная сборка добавлена ​​к f() для изменения значения адреса возврата в стеке, так что f() вернется через g().

#include <stdio.h>

void g()
{
    printf("now inside g()!\n");
}

void f()
{   
    printf("now inside f()!\n");
    // can only modify this section
    // cant call g(), maybe use g (pointer to function)

    /* x86 function epilogue-like inline assembly */
    /* Causes f() to return to g() on its way back to main() */
    asm(
        "mov %%ebp,%%esp;"
        "pop %%ebp;"
        "push %0;"
        "ret"
        : /* no output registers */
        : "r" (&g)
        : "%ebp", "%esp"
       );
}

int main (int argc, char *argv[])
{
    f();
    return 0;
}

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

3 голосов
/ 25 февраля 2010

Попробуйте это:

void f()
{   
    void *x[1];
    printf("now inside f()!\n");
    // can only modify this section
    // cant call g(), maybe use g (pointer to function)
    x[-1]=&g;
}

или это:

void f()
{   
    void *x[1];
    printf("now inside f()!\n");
    // can only modify this section
    // cant call g(), maybe use g (pointer to function)
    x[1]=&g;
}
...