2015-09-04 4 views
-2

Моя цель - написать бесконечный цикл. Я должен бесконечно печатать эту строку «Hello World% s», и я могу просто использовать ROP (ориентированное на возвращение программирование).Как сделать бесконечную петлю

gcc -fno-stack-protector loop.c -o loop 

Я могу скомпилировать, как показано. Как я могу сделать ROP?

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

main(char argc, char ** argv){ 
    char buffer[80]; 
    strcpy(buffer,argv[1]); 
    printf("Hello World %s",buffer); 
    return 1; 
} 
+1

Разве это не вопрос вашей домашней работы, чтобы узнать, как это сделать? –

+1

Когда вы говорите, что ваша цель - «бесконечная петля», что это значит? Какая часть кода вам нужна в бесконечном цикле? В любом случае 'while (1)', вероятно, самый простой способ сделать это. –

+1

Кроме того, почему вы 'возвращаете 1'? Необязательный код выхода указывает, что программа завершена с ошибкой. –

ответ

1

Так, грубый подход:

buffer находится в стеке, где обратный адрес main function -callee находится. В связи с тем, что стеки растут в обратном направлении, вы можете перезаписать обратный адрес, так как он был добавлен ранее. Стек должен выглядеть следующим образом:

[buffer data][ebp save][callee return address]...anything 

Это не совсем уверен, но вполне вероятно, что обратный адрес вызываемого абонента находится после ebp сохраненного значения, который расположен после буфера данных, так что вам нужно будет дать массив длиной в 84 байта (не содержащий 0x00, потому что это прекратит строку), за которым следует обратный адрес. Адрес должен указывать где-то, где ваш «хак» находится в памяти. Одним из возможных мест для этого может быть сам стек, поэтому вы можете захотеть добавить машинный код бесконечного цикла после обратного адреса.

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

[84 byte data][return address][machine code] 

Это должно работать на старых Linux ядра. Кроме того, предполагается, что вы работаете с 32-разрядной системой, поэтому указатели имеют длину 4 байта. В 64-битной системе это будет 8 байтов.

+0

Хм. OP хочет использовать ROP, и поэтому я предполагаю, что DEP активен. Это означало бы, что невозможно выполнить * собственный * код. – splotz90

+0

@ splotz90 В этом случае вы можете переопределить адрес main, который будет работать до тех пор, пока стек не будет полностью исчерпан. К сожалению, это не будет действительно бесконечным и будет работать только в том случае, если компилятор делает аргументы передатчика через регистры, а 'argv' не выделяется в стеке где-то рядом. – qwertz

+0

Да, у меня была такая же идея. Но я не писал его здесь, так как он (как вы сказали) не бесконечен. К сожалению, у меня нет других идей. – splotz90

0

Я не опытен с этим, но (теоретически) ваша конечная цель состоит в том, чтобы вернуться в код запуска (либо _start или, например, Glibc-х __libc_start_main), который в свою очередь, вызовет ваш main() снова с теми же аргументами. Поскольку аргументы будут одинаковыми, код вводит бесконечный цикл.

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

Обновите нас своими результатами.