R0 CREW

Exploit Development Course [Additional Materials]: More space on the stack (Перевод: klaus)

Источник: expdev-kiuhnm.rhcloud.com

More space on the stack

Если вы не можете получить рабочий эксплойт из-за странной ошибки, по причине которой падает ваша программа внутри fread, или же другой ошибки доступа, это может быть вызвано недостатком места в стеке для полезной нагрузки (payload). Наиболее легким способом решить данную проблему будет изменения кода с:

#include <cstdio>
 
int main() {
    <содержание функции main>
}

на:

#include <cstdio>
 
_declspec(noinline) int old_main() {
    <contents of main>
}
 
int main() {
    char moreStack[10000];
    for (int i = 0; i < sizeof(moreStack); ++i)
        moreStack[i] = i;
 
    return old_main();
}

К примеру, данный код:

#include <cstdio>
 
int main() {
    char name[32];
    printf("Reading name from file...\n");
 
    FILE *f = fopen("c:\\name.dat", "rb");
    if (!f)
        return -1;
    fseek(f, 0L, SEEK_END);
    long bytes = ftell(f);
    fseek(f, 0L, SEEK_SET);
    fread(name, 1, bytes, f);
    name[bytes] = '\0';
    fclose(f);
 
    printf("Hi, %s!\n", name);
    return 0;
}

примет следующий вид:

#include <cstdio>
 
_declspec(noinline) int old_main() {
    char name[32];
    printf("Reading name from file...\n");
 
    FILE *f = fopen("c:\\name.dat", "rb");
    if (!f)
        return -1;
    fseek(f, 0L, SEEK_END);
    long bytes = ftell(f);
    fseek(f, 0L, SEEK_SET);
    fread(name, 1, bytes, f);
    name[bytes] = '\0';
    fclose(f);
 
    printf("Hi, %s!\n", name);
    return 0;
}
 
int main() {
    char moreStack[10000];
    for (int i = 0; i < sizeof(moreStack); ++i)
        moreStack[i] = i;
 
    return old_main();
}

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

Как всегда, используйте свою голову. Иногда, вам нужно что бы функция fread() дошла к концу стека и возбудила исключение ради эксплойта типа SEH based exploit. Важный момент – всегда существует достаточно памяти в стеке для вашего payload. Если вам надо больше памяти, чувствуйте себя свободно и измените размер переменной moreStack.

В функции main цикл «for» нужен, иначе moreStack будет оптимизирован и мы не достигнем нашей цели. Также, если f встраиваемая функция, буфер name будет выделен после moreStack (т.е. по направлению конца стека) что теряет весь смысл. Во избежание этого нам надо использовать _declspec(noinline).

Изображение должно всё прояснить:

© Translated by klaus (r0 Crew)