# Глава 35

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

Следующим упаковщиком на шкале сложности является aspack, очень похожий на UPX, и для которого у нас есть крэкми UnPackMe\_ASPack2.12.exe [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/32/UnPackMe_ASPack2.12.7z), использовавшийся в главе 32.

Для практики установим OllyDump [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/35/OllyDump%20v3.00.110.7z) в директорию с плагинами, чтобы сделать дамп с его помощью.

Открываем OllyDbg, защищённый плагинами от обнаружения, и находим OEP с помощью метода PUSHAD.

![](/files/-LmvTv_eHR35809mDxHK)

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

![](/files/-LmvTv_rskPIWcUS8Xlh)

Видим начальный PUSHAD, который проходим с помощью F7, а затем делаем

![](/files/-LmvTva2HKaKtZ7xRGVO)

ESP-FOLLOW IN DUMP, чтобы установить в DUMP’е железную (hardware) точку останова на доступ к значениям двух регистров, которые сохраняются инструкцией PUSHAD.

![](/files/-LmvTvaFoOV61kRc0isb)

Затем нажимаем F9.

![](/files/-LmvTvaOTsKuWgyQrdae)

И останавливаемся прямо после POPAD, который восстанавливает сохранённые в эти регистры значения. Трассируем с помощью F7, пока не прибудем в OEP.

![](/files/-LmvTvaW9oFWN73nZwNZ)

Как видим, код был не понят, выходим из анализа.

![](/files/-LmvTvae7VIrwJ2lXqkt)

И видим, что если проанализировать его ещё раз, всё становится гораздо лучше.

![](/files/-LmvTvar6ftHgIJELi1b)

Затем приступаем к дампу файла. Идём в меню PLUGINS и ищем там OllyDump.

![](/files/-LmvTvazdlLOtmlK4cqv)

![](/files/-LmvTvb6euNQ2NJsn5NM)

Нам открывается окно плагина, в котором уже отображено то, что можно модифицировать. Можно исправить базу кода без необходимости потом править её в заголовке. В окне видим, что база кода равна 4000, а если помним, то aspack выполняется не в первой секции, поэтому не меняем это значение, которое соответствует 404000, где находится OEP и выполняется программа.

Ещё одна важная фишка – это опция "REBUILD IMPORT", находящаяся внизу окна. OllyDbg пытается сделать работу IMP REC’а, для чего ему служат METHOD1 и METHOD2, которые могут работать для простых упаковщиков. Вы можете сделать два дампа, используя каждый из этих методов, и посмотреть, работает ли хотя бы один из них. Это не всегда срабатывает, но иногда может.

Мы снимаем галочку с "REBUILD IMPORT", так как мы будем использовать IMP REC для большей надёжности.

![](/files/-LmvTvbGx-iru7oOexv8)

Ок, сейчас сделаем дамп и посмотрим, что из этого выйдет.

![](/files/-LmvTvbOoYUJ8_woegvB)

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

![](/files/-LmvTvbYYFwa9FTLgvQO)

Ок, не закрывая упакованный архив, который остановлен на точке входа, открываем IMP REC [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/34/ImportReconstructor16f.7z) и выбираем вышеуказанный процесс в выпадающем меню.

Возвращаемся в OllyDbg, чтобы найти значения начала IAT, её размера и OEP.

OEP равна 404000, то есть в IMP REC это будет 4000, так как нужно отнять базу образа, равную 400000.

Ищем начало и конец IAT, для этого нам нужно найти вызов какой-нибудь API-функции. Прямо под OEP есть вызов GetModuleHandleA.

![](/files/-LmvTvbh29uOl3oXWT-W)

Отмечаем данную строку, затем правая кнопка мыши и FOLLOW.

![](/files/-LmvTvbqm0lER0rbkI1K)

![](/files/-LmvTvbzjRiqm6FtUZp0)

Видим, что идём напрямую на API-функцию без посредничества косвенного JMP, по крайней мере в этом вызове (хотя если поищем, то увидим, что косвенные переходы есть, значит, используются они не всегда, как в данном случае).

Это значит, что здесь используется косвенный вызов для перехода на функцию, поэтому выяснить, откуда считывается адрес API (а он считывается из IAT), легко.

Легко видеть, что 4011F4 – это элемент IAT, где сохраняется адрес API-функции GetModuleHandleA.

Те, кто хочет увидеть косвенные переходы, могут поискать FF 25, чтобы их найти.

![](/files/-LmvTvc6dtLdYIc9PMvU)

И получаем тот же результат, так как JMP к GetModuleHandleA читает значения из того же элемента IAT.

Идём в DUMP, чтобы посмотреть данный элемент в частности и IAT в общем.

![](/files/-LmvTvcCGa2hEhcoNdaC)

Здесь видим, что все элементы соответствуют тем, что мы видели в начале, все идут в секцию кода той же DLL. Посмотрим с помощью VIEW-M, какой DLL они соответствуют.

![](/files/-LmvTvcKmeWGBwXsEnYK)

![](/files/-LmvTvcS_4oIi1R5k3XI)

Все находятся внутри указанной секции, поэтому видим, что эти элементы, относящиеся к Kernel32.dll, указывают на секцию CODE.

Здесь же можем посмотреть конец IAT. Снизу от 401218 особенно ничего нет, так что конец IAT – это 401218, и теперь нам осталось найти начало.

![](/files/-LmvTvcbYd9YqMX1bZtm)

Видим разделяющие нули, а после них другую группу элементов.

![](/files/-LmvTvclPunaYcByg-86)

Которые точно являются элементами, смотрим адреса, куда на которые они указывают (10xx или 11xx), Это не DLL, ни что-нибудь ещё, так как самый нижний адрес в карте памяти – это 10000.

![](/files/-LmvTvcy7X0UjtzFt0By)

Так что здесь находятся элементы, которые не ведут ни в какую-либо DLL, ни в какую-то реальную секцию. Так же они могли бы указывать на секцию, созданную упаковщиков, но не в данном случае. Это мусор, разбросанный для того, чтобы заставить нас думать, для чего он нужен. Спускаемся дальше.

![](/files/-LmvTvd9Uhp8HDnIA-B8)

Видим, что среди нулей есть другая группа элементов, указывающих на адреса 77Dxxxxx. Смотрим в карте памяти, какой DLL они соответствуют.

![](/files/-LmvTvdN0jpZ76Ew6lbN)

Видим, что они принадлежат User32.dll.

Также видим, что в карте памяти есть много других DLL, таких как GDI32 и Ntdll, которые могут загружаться упаковщиком для собственного использования, а не для использования программой. Чтобы проверить это, сделаем в этом же списке SEARCH FOR – ALL INTERMODULAR CALLS.

![](/files/-LmvTvdYmBWMUBDt--st)

![](/files/-LmvTvdrDbiSm-O19s2N)

Видим, что есть вызовы 3-х DLL, две из них – те, которые мы нашли, и другая – это Ntdll. Смотрим.

Если, например, перейдём к вызовам этой DLL.

![](/files/-LmvTvdxKlVjZNnvWB8y)

Видим, что соответствующий элемент находится в 401200, то есть это смешение (mezclada – чего-то я не совсем понял, о чём он толкует, кто понял – отпишитесь – прим. пер.) с kernel32.dll.

![](/files/-LmvTve32N3Vke2nZUb4)

То же самое относится и к другой из указанных DLL, которая смешана с kernel32.dll. Мы не заметили, что эти две секции кода находятся рядом друг с другом, но это так.

![](/files/-LmvTveC7hOfpjXSUAOx)

![](/files/-LmvTveK0WpdcQwGvAgj)

Ок, посмотрим какие проблемы могут быть из-за подобного начала IAT. Вот все эти элементы:

![](/files/-LmvTveUUyEdJbDGj_WI)

Начала IAT находится в 40119C, которое совпадает с меньшим значением, найденным в таблице переходов.

![](/files/-LmvTvedsLSVLTdEPdYc)

Видим, что оно самое маленькое из всех этих значений, так что у нас получается:

`OEP=4000`

`RVA или НАЧАЛО IAT=119C`

`РАЗМЕР = КОНЕЦ МИНУС НАЧАЛО = 401218-40119c = 7C`

![](/files/-LmvTvenchUNoqwcd5jm)

Задаём эти значения в IMP REC, чтобы посмотреть, что получится, видим, что оба смешанных элемента относятся к ntdll и kernel32.

![](/files/-LmvTvewPgykxSjtXJHS)

Видим, что указанная часть не та, которая соответствует мусорным элементам, и внизу видим, что у нас есть только элементы для kernel32, и если посмотрим редко встречающиеся элементы, соответствующие 401200 b 401210, то увидим, что:

![](/files/-LmvTvf57-SYI6gUdjiN)

Заменяем его на похожие элементы, соответствующие kernel32.dll, и что это будет означать?

![](/files/-LmvTvfFNidw0JijDnXE)

Видим, что теперь в логе нам говорят, что эти элемент похожи на элементы из kernel32.dll, и пакер может свободно менять их, что всё запутать и усложнить.

Хорошо, теперь нам осталось убрать мусор из середины. Проверяем эти элементы и смотрим, если написано NO, то это мусор. Чтобы убедиться в этом, идём к одному из них.

![](/files/-LmvTvfOYgz6ALYFpTub)

Отмечаем первый, нажимаем правую кнопку мыши и выбираем DISASSEMBLE-HEX VIEW.

![](/files/-LmvTvfXFHsUQ_F99P1r)

![](/files/-LmvTvfhdV5d4CYSRPZ2)

Здесь видим, что это не приводит нас к реально существующему месту, так что отмечаем все элементы как мусор.

![](/files/-LmvTvfqNHN-ObsvJdx4)

Нажимаем SHOW INVALID, а затем, держа все эти элементы отмеченными, нажимаем на правую кнопку мыши и выбираем CUT THUNKS.

![](/files/-LmvTvfzcAWB90tRQ2PK)

![](/files/-LmvTvg7WUB08pUKSdBY)

Таким образом мы аннулировали все эти неверные элементы, чтобы система при загрузке не выдавала ошибку, пытаясь загрузить несуществующие API-функции.

Теперь можно нажать FIX DUMP, так как все элементы отмечены как YES, то есть как правильные.

![](/files/-LmvTvgGm11qDrwpMvy2)

И создаётся dumpaspack\_.exe, файл, который предположительно должен быть починен, запускаем и смотрим, так ли это.

![](/files/-LmvTvgPOYFqAlZxxFZS)

Работает превосходно, поэтому на этот раз здесь и остановимся. Сложность нужно повышать постепенно.

\[C] Рикардо Нарваха, пер. Aquila


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://backoftut.gitbook.io/intro-cracking-with-ollydbg-2/ch-35.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
