R0 CREW

Neffarion :: 0xs1 :: Code Inj:: Инъекция кода в откомпиленную программу (Перевод: Heroin)

0xs1 :: Code Inj:: Инъекция кода в откомпиленную программу
Code Inj - процесс ручного добавления кода в скомпилированную программу и его выполниния. Этот туториал полностью описывает процесс успешной сессии инъекции кода.

Инфо

Filename… injectme.exe [ download ]
Developer… Xylitol
Toolz… OllyDbg, XVI32, Windows API Reference [ download ]

Adficio

1 - a. Открытие программы OllyDbg

Рисунок 1. Целевая программа

Сложность внедрения кода зависит от ваших намерений. Некоторые инструкции, такие как API, очень легко осуществить - другие, такие как эмуляция, очень сложно. Мы будем использовать пустое место в программе чтобы внедрить наши инструкции и сделаем вызов новых инструкций из начальной.
Для начала прост давай внедрим окно сообщения и изменим EP, чтобы вызвать наш новый код. Затем программа возобновит работу в обычном потоке:)

2 - a. Открываем W32API и ищем "MessageBox"

Рисунок 2. W32API

Функция Message Box объявлена так:

int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box 
LPCTSTR lpCaption, // address of title of message box 
UINT uType // style of message box 
);

Есть 4 флага, которые мы должны пройти для вызова функции. Помни, что функции API сначала должен быть передан флаг параметров перед вызовом фактической функции. В 0xg3 мы узнали, как окно сообщения было объявлено в инструкции, поэтому мы будем использовать те же инструкции, но немного изменим их:

push 0 [ handle ] 
push (x) [ address of text ] 
push (x) [ address of caption, will be the same address as text ] 
push 0 [ style ] 
call MessageBoxA

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

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

3 - a. Находим 0x404382

Рисунок 3. Сode cave

Инструкция DB означает “Определить Байт”, каждый в 1 символ по размеру. Так как мы будем проводить инъекцию в окно сообщения, в первую очередь нам необходимо определить текст и заголовок, потому что функция окна сообщения не принимает значения для флага. Вместо этого, эти значения являются указателями - так что мы должны определить эти значения в отдельных адресах памяти .

4 - a. Выбираем адреса от 0x404385 до 0x4043A9

Рисунок 4. Наше поле

Я всегда выбираю большую часть code cave’a, потому что наличие свободного места не проблема - проблема в его нехватке :slight_smile:

5 - a. Правый клик на выбранном и Binary > Edit b. В поле "ASCII" пишем "Hello Hell" и жмем ok

Рисунок 5. Внедрение строки

Рисунок 6. “Hello Hell” как собственная инструкция

7 - a. Жмем CTRL + A

Рисунок 7. Проанализированная строка

Мы будем использовать эту строку для текста и заголовка, но если ты хочешь, чтобы они были различными, просто выбери code cave несколько раз и повтори шаги 5-7:)

8 - a. Выбираем адреса от 0x404391 до 0x404395

Рисунок 8. Секция мессаджбокса

9 - a. Правый клик на выделенном и выбираем Assemble
Для последующих пяти шагов делаем все за раз, потому что когда ты нажмешь Assemble диалоговое окно станеат открытым для набора инструкций
9 - b. Assemble “PUSH 0”
c. Assemble “PUSH 00404385”
d. Assemble “PUSH 00404385”
e. Assemble “PUSH 0”
f. Assemble “CALL MessageBoxA”

Рисунок 9. Инструкция

Рисунок 10. Внедренное окно сообщения

Пока мы внедрили окно сообщения успешно, но нам все равно надо менять программу таким образом, чтобы она показывала наше сообщение, а затем, после запуска, возвращалась к оригинальным процедурам. Для этого мы должны изменить EP (которая 0x4010000 - ты можешь перейти к EP, нажав клавишу [*]). Когда ты посмотришь на EP, то увидишь, что она принадлежит к блоку кода (черная линия, которая показывает, где он начинается и где заканчивается). Это означает, что нам нужно прописать первую строку - которая будет являться OEP.

11 - a. Правый клик на адресе 0x401000 и выбираем Assemble b. Копируем куда-нибудь эту инструкцию (например Notepad)

Рисунок 11. OEP инструкция

Для вызова исходного кода, нужно перейти к первой инструкции кода, которая, в этом случае, находится по адресу 0x404391:slight_smile:

12 - a. Изменяем значение EP на "JMP 00404391"

Рисунок 12. Новая EP

13 - a. Правый клик на адресе 0x4043A4 (инструкция после вызова функции) и выбираем Assemble
b. Изменяем значение на “CALL 004015D6”

Рисунок 13. OEP

После вызова окна сообщения программа будет выполнять функции InitCommonControls (типа инструкции OEP), но нам необходимо восстановить первоначальный поток программы (в противном случае программа будет делать ошибку доступа к памяти). Вторая команда после ЕР по адресу 0x401005.

14 - a. Правый клик на адресе 0x4043A9 и выбираем Assemble b. Изменяем значение на "JMP 00401005"

Рисунок 14. Исходный поток

Сохраняем изменения в exe:

15 - a. Правый клик и выбираем [i]Copy to Executable > All Modifications[/i] b. Жмем [i]Copy all[/i] c. Появляется новый диалог, который мы закрываем d. Жмем [i]Yes[/i] e. Сохраняем под другим именем

Рисунок 15. Крякнутая целевая программа

© +Neffarion
http://www.0xNeff.eu

© Translated by Ex0rcist a.k.a. Heroin from GR TeaM
© Resident of r0 Crew

Это не верно, т.к тогда оно будет ссылается на адрес MessageBoxA в user32.dll, а это в свою очередь приведёт к тому, что патченый файл не будет запускаться на других осях отличных от той на которой патчилось.

Нужно вызывать через таблицу импорта.

call 401594