Поток выполнения ЦП после успешного завершения переполнения буфера execve? ..после успешного завершения int 0x80?

Я изучаю методы шеллкода переполнения буфера в Linux. https://seedsecuritylabs.org/Labs_16.04/Software/Buffer_Overflow/

Шеллкод, который я использовал, заканчивается на movb $0x0b, %a1 и затем на int $0x80. Шелл-код выполняется, и я получаю командную строку. Я читал много мест, где execve и int 0x80 «не возвращаются». Хорошо.. хорошо, но куда ~ идет ~ поток выполнения программы, когда процесс execve завершается успешно и завершается (иначе я ввожу «выход» в командной строке)?

Я думал, что вызывающая программа заменяет свой кадр стека информацией о новом коде execve. Сохраняет ли новый исполняемый код адрес возврата перезаписанного процесса и возвращает ли он этот адрес, как если бы он был его собственным? (Значит, это своего рода возврат .. на заимствованный адрес?) Что касается int $0x80, разве выполнение не продолжается со следующего байта после инструкции int 0x80? Если нет, то какой следующий байт?

В контексте проблемы переполнения буфера и int 0x80, скажем (например), 517-байтовый хак перезаписывает 24-байтовый буфер. Байты заменят значения в адресах памяти стека за пределами буфера, включая адрес возврата, указывающий на его собственный исполняемый код выше в стеке. Но преднамеренный код топчет сотни других байтов стека выше в памяти, уничтожая кадры стека несвязанных процессов внешней области. Что происходит с этими уничтоженными кадрами стека, когда...

1) когда оболочка возвращается из int 0x80 и выполняет больше данных стека, что не является частью хака. Теперь есть неуказанные байты, которые, вероятно, являются недопустимыми кодами операций ЦП.

2) контекст фреймов внешнего стека был уничтожен, так как же система продолжает работу после того, как я ввожу «выход» в командной строке оболочки?

Любая помощь приветствуется!


person Brian    schedule 13.08.2019    source источник


Ответы (1)


Я думаю, вы поймете, что происходит, если мы обсудим, что такое execve и как он работает.

Я читал много мест, где execve и int 0x80 «не возвращаются». Хорошо.. хорошо, но куда ~ идет ~ поток выполнения программы, когда процесс execve завершается успешно и завершается (иначе я ввожу «выход» в командной строке)?

Следующее взято из справочной страницы execve.

execve() executes the program pointed to by filename.  filename must be
       either a binary executable, or a script starting with  a  line  of  the
       form:

           #! interpreter [optional-arg]

execve — это системный вызов, который выполняет указанную программу.

Продолжая,

execve() does not return on success, and the text, data, bss, and stack
       of the calling process are overwritten by that of the program loaded.

Это утверждение относится к вашему вопросу.

У каждого процесса своя структура памяти. Структура памяти состоит из текстового сегмента, сегмента данных, стека, кучи, зависимых библиотек и т. д. Обратитесь к /proc/PID/maps любого процесса, чтобы получить четкое представление о структуре памяти.

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

Таким образом, когда вы пытаетесь выполнить exit в своей командной строке, вы просто завершите /bin/sh, который вы запустили с помощью execve. Сегментов нет, ошибок нет.

Сохраняет ли новый исполняемый код адрес возврата перезаписанного процесса и возвращает ли он этот адрес, как если бы он был его собственным? (Значит, он как бы возвращается... на заимствованный адрес?)

Нет. Такого не бывает. Новый процесс, запущенный execve, ничего не знает о старом процессе.

Что касается int $0x80, разве выполнение не продолжается со следующего байта после инструкции int 0x80? Если нет, то какой следующий байт?

int 0x80 присутствует инструкция для запроса ОС на выполнение указанного системного вызова. Таким образом, продолжится ли выполнение позже, когда int 0x80 полностью вернет, зависит от того, что такое системный вызов.

В общем, читаешь, пишешь, открываешь, создаешь и т.д., все выполняешь и возвращаешься обратно. Но класс функций exec (перейти к man exec) отличается. Каждая из этих функций никогда не возвращается в случае успеха. Они возвращаются только в случае неудачи.

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

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

person adwait1-g    schedule 12.11.2019
comment
Спасибо. Итак, да, вы подтвердили, что все перезаписывается загруженной программой. Хорошо, но когда эта программа заканчивается, вы не ответили на вопрос, куда действительно переходит выполнение. Каким-то образом управление упорядоченным образом переходит к ОС. Счетчик программ никуда не денется. Если стек уничтожен, по какому адресу возвращается? Как предоставляется этот адрес? - person Brian; 19.11.2019