# Глава 43

В предыдущей части мы сосредоточились на починке украденных байт, а сейчас нашей задачей является IAT. Снова открываем распакуй-меня [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/42/UnPackMe_ACProtect1.09g.f.7z) в OllyDbg и доходим до фальшивой OEP с помощью скрипта.

![](/files/IIJJlZN9YQSp0N0UsYwq)

Сейчас находимся в начале программы. Теперь, поскольку у нас есть скрипт [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/42/HBP%20\(42\).7z) для того, чтобы попасть в OEP, который остался нам с прошлой главы, устанавливаем две необходимые точки останова и используем их.

![](/files/2ONMB7aAVpyBCbAxywM8)

![](/files/U0cyne8yklYwxNEDHSEi)

![](/files/m7wwZ5SrPwNxf39fDSEx)

И сейчас находимся на OEP. Ниже рассмотрим, как улучшить скрипт, чтобы автоматически устанавливать две точки останова, и чтобы запрашивался адрес HBP. Пока редактировать не будем, послужит нам как есть.

![](/files/yKJDyvIKk55mcFiQS4Lg)

Ищем вызов API-функции, для чего можем использовать SEARCH FOR INTERMODULARS CALLS.

![](/files/hNneksLb8mQQrqBEte11)

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

![](/files/5BExwRlrCnSaVQSCftdm)

Здесь видим вызов, который берёт значение 460e80, что является элементом IAT. Смотрим IAT в дампе.

Видим ворох элементов, которые, в данном случае, являются переадресовочными не в секцию, созданную упаковщиком. Может в ту же секцию, где исполняется сам упаковщик? Смотрим карту памяти.

![](/files/yrGS4yFyF4sqUVoMToc7)

![](/files/qEmR6CxCYMRPnLUc12Gq)

Вот эта секция. Если спустимся ниже и посмотрим образ точки входа, где запускается упаковщик, то вспомним, что это был адрес 46b000, поэтому упаковщик не заморачивался сильно с созданием новой секции, чтобы скрыть в ней API-функции.

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

![](/files/xaUeDhorLhnH00oxKmIt)

Используем указанный переход 460aDC, чтобы попытаться найти волшебный переход. Чтобы не пришлось менять скрипт из OEP, скопируем его в другую папку, переименуем его в OEP и скопируем обратно.

![](/files/0stto4cvLZwhFAJTMg72)

Таким образом, мы сохранили под именем "OEP" скрипт, который используем для нахождения OEP, а теперь можем модифицировать HBP, чтобы найти волшебный переход.

Здесь меняем HBP на плохие элементы, а затем меняем тип на W, то есть на запись или WRITE.

Теперь стираем HBP, установленные ранее, и делаем перезапуск.

![](/files/rK9hRJFVAsqLhMDjmmVX)

Остановились тут, смотрим в DUMP плохой элемент, за которым мы будем наблюдать после того, как решим, тот ли это момент, чтобы прервать выполнение скрипта.

![](/files/mmAqY5mjEzyRLzVFhFmX)

Вот здесь находится плохое значение, тут и происходит HBP ON WRITE. Останавливаемся на следующей инструкции после того места, где сработало исключение, так что смотрим предыдущую.

![](/files/vtNXQnPuLcpz8sShOABl)

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

Проверим, происходит ли запись в переадресовочную зону, для чего нам не нужно идти до OEP, смотрим 46b492:

![](/files/pU9g2x8ey9jwdpRGWBQH)

![](/files/oZ81Mcku6PPMl9Zm7Ylf)

Видим, что переадресация довольно дурацкая – здесь помещается в стек 5bf11a9, а затем это значение XOR'ится с 793e0502. Результат этой операции становится первым значением стека, и когда доходит до выполнения RET'а, возврат произойдёт по этому адресу.

Смотрим, может ли посчитать адрес API-функции, куда, в итоге, произойдёт переход.

5bf11a9 XOR 793e0502 = 7C8114AB

Это адрес API-функции, куда ведёт переадресация. Возвращаемся обратно в OllyDbg, и смотрим, найдём ли мы здесь что-нибудь.

![](/files/eE3iw7ZMXH3hXXbkZ6Dg)

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

![](/files/z0dPFiLOskcLw7f3t6gA)

И смотрим, что произойдёт, если установим BPM ON WRITE на плохие элементы, которые ещё не заполнены из таблицы.

![](/files/LUjIUEOfosxw1z5uRd4R)

Делаем RUN и останавливаемся, чтобы остановиться на следующем элементе.

![](/files/m6mYyHANhxMoclKey4QP)

И видим, что это API-функция MulDiv. Если нас не затруднит пойти в переадресовочную область и сделать XOR, что ведёт сюда, так что мы видим возможность починки. Хорошая API-функция расположена в стеке, а точнее в \[ebp-0c].

![](/files/biTM2gYNCmuoJEZpJmPZ)

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

![](/files/HmCm3ohjAMM7v9z55dEc)

Так что устанавливаем BPM ON WRITE на него.

![](/files/5tMDICltJmdaWCY2EYnD)

Делаем RUN и останавливаемся здесь.

![](/files/1C4tXsNFlndgUMMIfQYa)

Видим, что это тот же адрес, где сохраняются плохие элементы. Также в случае хороших элементов смотрим \[ebp-0c], где находится правильный адрес.

![](/files/M0m5wZvypzFD0wfXIhHR)

Видим, что в случае с хорошими API-функциями правильного адреса здесь не сохраняется, что очень жалко, так как иначе было бы очень легко сделать скрипт, который был смотрел значение \[esp-0c], но решить эту проблему также легко.

Ничего сложного, сделаем скрипт, используя тот же HBP.

Что мы сделаем? Установим HBP ON EXECUTION на то место, где сохраняются значения IAT, и когда скрипт определит, что остановились здесь, проверим, содержит ли EAX хорошее значение или плохое. В последнем случае сохраним значение \[esp+0c] в \[EDI], которое указывает на заполняемый элемент таблицы.

Смотрим скрипт.

```
var aux
var aux2

inicio:

bphws 4743d5, "x"

trabajo:

eob pirulo
run

pirulo:
log eip
cmp eip, 7c91eaec
je quitar
cmp eip, 7c91eb03
je restaurar
cmp eip, aux
je restaurar2
cmp eip, 4743d5
je reparar
jmp final

quitar:
bphwc 4743d5
jmp trabajo

restaurar:
mov aux, esp
mov aux, [aux]
add aux, 0b8
mov aux, [aux]
log aux
bp aux
jmp inicio

restaurar2:
bc aux
jmp inicio

reparar:
cmp eax, 500000
ja inicio
mov aux2, esp
sub aux2, 0c
mov aux2, [aux2]
log aux2
mov [edi], aux2
jmp inicio

final:
MSGYN "Continuar?"
cmp $RESULT, 1
je inicio
ret
```

Вот скрипт. Первое, что нужно пояснить – устанавливаем HBP ON EXECUTION на следующую инструкцию, то есть на 4743d5. Раз HBP ON EXECUTION, то остановка будет происходит точно в тот момент, когда происходит выполнение, чего не было бы с HBP ON WRITE или ON ACCESS.

Скрипт прост и основывается на том, что мы делали раньше, только устанавливаем HBP ON EXECUTION на 4743d5 – следующей строке после сохранения плохого значения.

```
cmp eip, 4743d5
je reparar
```

В части pirulo, где скрипт получает контроль по нахождению исключения, добавляем к ней сравнение EIP с 4743d5, чтобы узнать, действительно ли находимся в желаемом месте, и оттуда прыгаем к reparar, где и творится магия.

```
reparar:
cmp eax, 500000
ja inicio
mov aux2, esp
sub aux2, 0c
mov aux2, [aux2]
log aux2
mov [edi], aux2
jmp inicio
```

В reparar мы делаем следующее: проверяем, содержит EAX хорошее значение или плохое, и как видим, все переадресовочные значения ведут в секцию упаковщика. Его адрес меньше 500000, поэтому если видим, что EAX больше 500000, то потому что это хорошая API-функция. В этом случае мы ничего не чиним и возвращаемся в начало. В противном случае у нас плохое значение, и используем переменную aux2, чтобы найти значение ESP, от которого отнимаем 0c, а затем находим его содержимое. Его записываем в лог, а затем сохраняем в \[EDI], который указывает на элемент, откуда загружается плохое значение на предыдущей строке программы. Вот мы и разобрались с этим, затем возвращаемся и пробуем скрипт.

Перезапускаем программу. Обращаем внимание, чтобы не было старых HBP (есть ли есть, то стираем их) и убеждаемся, что уставлены два необходимых BP для правильной работы, и запускаем.

![](/files/Raz0RRLBQ04D2NHl4CGZ)

Запускается программа, смотрим, что осталось в IAT.

![](/files/qPIACXzhBPPqvpXtrwqY)

Красота, хе-хе. С помощью запущенной программы с починенным IAT можем починить дамп. Уже видели, что нет необходимости останавливаться на OEP, чтобы использовать процесс в IMP REC’е, когда есть правильная таблица, так что без проблем починим дамп.

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

![](/files/KZUetB6zp7pCdeAnYcOS)

Единственное, что осталось, связанное с IAT – это найти начало и размер таблицы, которые необходимо указать в IMP REC’е.

![](/files/AbPGWnIpjXGLAAn1LezL)

Поднимаясь по IAT, ясно видим, что IAT начинается в 460818, конец в 460f28, и его также несложно найти:

![](/files/Fv0dm3LRTsuSv9FGMprN)

OEP = **271b5**

НАЧАЛО = **60818**

РАЗМЕР = 460f28 - 460818 = **710**

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

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

\[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/ch-43.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.
