> For the complete documentation index, see [llms.txt](https://backoftut.gitbook.io/intro-cracking-with-ollydbg-2/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://backoftut.gitbook.io/intro-cracking-with-ollydbg-2/ch-48.md).

# Глава 48

Если вы загрузили главы 46 и 47 сразу после их появления, то, возможно, не читали добавленное к ним позднее примечание:

> После того, как была написана 46 глава и еще не было завершено решение Patrick’а, я заметил, что эти туториалы слишком сложны для уровня, до которого мы дошли, так что если вам главы 46 и 47 покажутся очень сложными, то советую оставить их до тех времен, когда вы будете более подготовлены, а сейчас сразу перейти к 48 главе, соответствующей тому уровню, на котором мы остановились.
>
> ***Рикардо Нарваха***

Так уж вышло, что когда я занялся Patrick’ом, то сначала решил его простым методом (упомянутым в конце 47-й главы) и посчитал, что он легок до неприличия. Как следствие, данные главы оказались труднее прежних и пришлось добавить процитированное выше примечание.

В этой главе мы рассмотрим упаковщик PeSpin 1.304 Full [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/UnPackMe_PeSpin1.3.04.f.7z), о котором уже существуют достаточно хорошие туториалы. На самом деле, написать еще не существующий туториал практически невозможно, так как ресурс CracksLatinoS содержит очень хорошие статьи почти обо всех упаковщиках.

В PeSpin дойти до OEP очень просто.

![](/files/-LmvTvcokALxNkIJz9iF)

Сейчас анпэкми остановлен на его EP. Мы будем пользоваться Parcheado 5 [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/26/olly_parcheado_para_vb.7z) — версией OllyDbg, которая предназначена для поиска OEP’ов.

![](/files/-LmvTvd7d9wFrQVtQdSL)

Открыв карту памяти, установим MEMORY BREAKPOINT ON ACCESS в первой секции после заголовка. Этот брейк равнозначен ON EXECUTION, поскольку, как помните, пропатченная для поиска OEP’ов версия отладчика в данном случае останавливается только при выполнении, а не при чтении или записи.

![](/files/-LmvTvdHLjYTJbqTmrr1)

Следует убедиться, что все галки во вкладке Exceptions окна Debugging options установлены:

![](/files/-LmvTvdTjxq3BZiQwozP)

После нажатия на RUN можно пойти спокойно пить кофе:

![](/files/-LmvTvddkmFCNRZra-y8)

Как следует напившись кофе, хе-хе, обнаружим, что остановка произошла на непохожем на OEP месте, а значит, от команд исходной OEP ничего не осталось из-за украденных байтов:

![](/files/-LmvTvdp4jsjhzehCkEt)

Посмотрим стек:

![](/files/-LmvTvdy6Q8yB7MmxmD9)

Можно заметить, что перед прибытием в ложную OEP было выполнено много кода, и это свидетельствует о том, что байты OEP были украдены.

![](/files/-LmvTve6RXX10wPFAhKd)

Кроме того, если сделаем Search for –> All intermodular calls, то найдем очень мало вызовов API-функций:

![](/files/-LmvTveLjCFC9I44l4Kl)

Посмотрим один из них:

![](/files/-LmvTveU3nTPD-OPVm7V)

![](/files/-LmvTvef72hKSA7usolg)

Дойдя до косвенных переходов на API-функции, заглянем в IAT:

![](/files/-LmvTveqalgW1bZQKsEm)

Здесь виден конец IAT’а — 460F28. Теперь поднимемся выше:

![](/files/-LmvTvf3AuomT9g4xPX8)

Похоже, это переадресовочные элементы. Чтобы проверить, принадлежат ли они IAT’у, посмотрим их референсы:

![](/files/-LmvTvfFpNQfNFZ2u9gY)

Поиск ничего не дает, но если подняться еще выше, то станет ясно, что это всё-таки часть IAT’а. Таким образом, в PeSpin используется и переадресация.

![](/files/-LmvTvfScC-EBeFUyGfk)

Начало IAT’а находится по адресу 460818. Мы еще вернемся к этому месту, когда будем исправлять IAT, а сейчас займемся возвращением украденных байтов; чуть выше ложной OEP для них как раз есть подходящая нулевая область:

![](/files/-LmvTvfeY3iCTwy7dikO)

Перезагрузим программу и посмотрим состояние стека:

![](/files/-LmvTvfvJn6dxDoMFZin)

Здесь видно, что перед запуском анпэкми адрес вершины стека равен 12FFC4 (так на моем компьютере). Это означает, что при прибытии к истинной OEP вершина стека должна находиться по тому же адресу, то есть в 12FFC4. Обычно первой командой программы является PUSH EBP, которая записывает значение в следующую ячейку стека (12FFC0), поэтому найдем ее в дампе и установим на ней HARDWARE BPX ON WRITE. Такое рассуждение логично, но оно может и не дать результатов, если упаковщик обнаруживает аппаратные брейкпоинты или, для осложнения поиска OEP, меняет адреса стека.

![](/files/-LmvTvg8z675LRUA4OAh)

После установки брейка нажмем RUN:

![](/files/-LmvTvgKz5HGAL-W31x0)

Первая остановка произошла здесь, но данная инструкция скорее всего принадлежит распаковщику. Нажмем F9 еще раз:

![](/files/-LmvTvgXWbEWo4m2irP8)

Теперь остановились на PUSH EBP, что весьма похоже на команду из OEP. Чтобы проверить это предположение, воспользуемся, хе-хе, трассировкой. Конечно же, JMP’ы нас не интересуют, так как они не влияют на состояние регистров или стека.

![](/files/-LmvTvghJSLPnr0y2R0v)

![](/files/-LmvTvgutRqdXOPwdqrX)

![](/files/-LmvTvh4nhav45Hv1sGB)

Здесь встречается необычная комбинация команд: сначала выполняется PUSH, а затем только что записанное в стек значение суммируется с константой:

![](/files/-LmvTvhHVVyCLF_Zrgim)

После выполнения инструкции ADD значение в стеке оказывается 450E60, поэтому данная комбинация равнозначна PUSH 450E60.

![](/files/-LmvTvhU6WNg92znDLjA)

Затем этот трюк повторяется, но уже вместо PUSH 4292C8:

![](/files/-LmvTvhfDybe3r3NwMon)

Далее идет еще одна подходящая инструкция:

![](/files/-LmvTvi4j0kFmSdQuneg)

И еще парочка:

![](/files/-LmvTviMbLUaksTYlLQL)

![](/files/-LmvTviZmXWCds5QLUNV)

Продолжим:

![](/files/-LmvTvimcNfogi_14v3Z)

![](/files/-LmvTvizm5qQkh7ouyvv)

![](/files/-LmvTvj8aHnOQKRwSDr5)

![](/files/-LmvTvjIHv1k4IvHt0gR)

![](/files/-LmvTvjSoJ2txMVKPoM_)

![](/files/-LmvTvjd2MZU4UihobFa)

Сейчас мы просто скопируем этот CALL, а потом, при восстановлении IAT’а, посмотрим, относится ли он к какой-нибудь API-функции.

![](/files/-LmvTvjq2FCxufs6Gzl-)

![](/files/-LmvTvk0bA8uYXfA8rmH)

![](/files/-LmvTvkCBe1ur3Qzgfmm)

![](/files/-LmvTvkNFtZZuWFDFXjo)

![](/files/-LmvTvkZKH2XHNX7dJM1)

![](/files/-LmvTvkhmu68EaPjiMso)

![](/files/-LmvTvkt08K_LuIRG4dC)

![](/files/-LmvTvl3Fo4NDNMYSwCB)

Переход на ложную OEP завершает трассировку, а мы тем временем узнали список украденных байтов, хе-хе.

![](/files/-LmvTvlE2XE25uId70u6)

Скопируем их в область OEP:

![](/files/-LmvTvlPDbXYu2NMMrNC)

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

До встречи в 49-й главе!

\[C] Рикардо Нарваха, 17.07.06 пер. Рома Стремилов, 01.2010
