Как я могу вызвать переполнение буфера?

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

#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 (), но я не уверен, как получить доступ к нему. Так или иначе подсказки будут большими.

31
задан jww 12 September 2014 в 13:03
поделиться

5 ответов

DBI + DBD:: mysql

LWP:: UserAgent

WWW:: Механизировать

XML:: LibXML

HTML:: TreeBuilder

CGI:: FormBuilder

Шаблон:: Набор инструментов

: Предметы, отмеченные выше как Питон, STL включены как часть Библиотеки Стандарта Питона, как перечислено в документация Питона v2.6.4 .

-121--4103932-

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

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

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

13
ответ дан 27 November 2019 в 22:38
поделиться

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

Следующий код сделает то, что вы хотите для 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
11
ответ дан 27 November 2019 в 22:38
поделиться

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

Я научился этой технике, прочитав отличную (хотя и немного устаревшую) статью/учебник по эксплуатации уязвимостей переполнения буфера Smashing The Stack For Fun And Profit.

8
ответ дан 27 November 2019 в 22:38
поделиться

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

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;
}
3
ответ дан 27 November 2019 в 22:38
поделиться

Хотя это решение не использует метод переполнения для перезаписи адреса возврата функции в стеке, оно по-прежнему вызывает вызов 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
ответ дан 27 November 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: