Введение в крэкинг с нуля, используя OllyDbg - Глава 37

  • На форуме работает ручное одобрение пользователей. Это значит, что, если Ваша причина регистрации не соответствует тематике форума, а также Вы используете временную почту, Ваша учётная запись будет отклонена без возможности повторной регистрации. В дальнейшем - пожизненная блокировка обоих аккаунтов за создание мультиаккаунта.
  • Мы обновили Tor зеркало до v3!
    Для входа используйте следующий url: darkv3nw2...bzad.onion/
  • Мы вновь вернули telegram чат форуму, вступайте, общайтесь, задавайте любые вопросы как администрации, так и пользователям!
    Ссылка: https://t.me/chat_dark_time

AnGel

Администратор
Команда форума

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
В этой части мы рассмотрим несколько методов, с помощью которых можно починить переадресовочные элементы, но наша задача не переутомиться – так как, как и в случае с нахождением OEP, методов столько же, сколько существует упаковщиков, и когда будем рассматривать какие-нибудь другие упаковщики, то там могут встречаться новые методы как для нахождения OEP, так и для починки IAT.

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

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

a0a85283665a9015e90ca5f4a7a329fc.png

Ок, мы находимся на OEP telock’а, и как и в предыдущей главе, тут есть переадресовочные элементы на разные секции, созданные упаковщиком во время выполнения.

0d7cf3f49a55d2efd1087bbb05ee18eb.png

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

Возьмём элемент, который мы трассировали вручную и знаем, что он в итоге приводит к GetVersion.

147ea6e6dc1bc350a90f8dd98ca18574.png

Здесь есть CALL, а в DUMP’е – элемент IAT 460ADC, чьё содержимое на моей машине указывает на 9F06F7. Также у нас должен быть открыт IMP REC со всеми значениями, RVA, РАЗМЕРа и OEP, которые были найдены вручную, и если глянем на плохие элементы:

f286c185c30ca96138e55e33e223903e.png

Раскрываем, чтобы увидеть эти элементы.

acda03942439437ac14fa5f78c602df2.png

60ADC соответствует элементу IAT 460ADC.

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

acd71a1f7d4f4b9004858a7e5093b5e1.png

До начала трассировки устанавливаем BP на возврат из API-функции, чтобы не случилось так, что мы ошиблись и не оттрасировали до самого конца без остановки.

В DEBUG-SET CONDITION можно выбрать опции, при которых OllyDbg остановит трассировку.

59ad8963916390524083eb7535ec3211.png

Видим окошко под названием «Условия остановки трассировки», посмотрим, что за условия и какие из них можно использовать в нашем случае.

EIP IS IN RANGE означает, что если поставить здесь галочку, OllyDbg остановится, когда EIP окажется в границах интервала значений, заданного справа, например:

64c12a22122dcfdc2057701eb2dfc67e.png

Этот пример означает, что OllyDbg будет трассировать, пока не увидит, что EIP содержит значение между 401000 и 500000. Конечно, это всего лишь пример, и в нашем случае он не помощью, так как мы хотим, чтобы остановка произошла на API-функции. Для нахождения нужных нам значений, посмотрим карту памяти.

6246220730a5b17dc70c449aaf0845dc.png

Здесь видим область, отмеченную лазурным цветом, которая может представлять для нас интерес, так как здесь остановился OllyDbg при трассировке, то есть отсюда пойдёт первая DLL. Мы не хотим останавливаться ни в секциях exe-файла, ни в секциях, созданных упаковщиком, так как это промежуточный код, и нам нужно останавливаться в DLL, поэтому отметим первый столбец и установим, что EIP должен быть между 58000000 и 7FFFFFF, то есть будет содержать адрес, максимально гарантирующий, что остановимся в какой-либо DLL (пояснение: не обязательно задавать точный адрес первой DLL, так как мы видели, что между 58000000 и 58C30000 (началом первой DLL) нет кода, так что мы там не остановимся, и во избежание необходимости задавать точные цифры можем без всяких проблем их слегка округлить).

3e44fea07e38cbd74fd60df9dfa43c14.png

Это всегда означает, что OllyDbg запустит построчную трассировку, и в каждой будет проверять, что выполняется указанное условие, то есть содержит ли EIP значение в пределах секции данной DLL, и если да, то остановит выполнение.

ddfb053b2be183362b4f0420b56d4dd1.png

Доходим до CALL и устанавливаем на него BP.

96bdd7ca51f90e00dca85c85fa3baa93.png

Если до этого был установлен MEMORY BREAKPOINT, использовавшийся для нахождения OEP, то убираем его и доходим до CALL.

В случае, если нет CALL’а в начале, и не знаем, где может находиться он или JMP, можно отметить байты соответствующего элемента и установить на них MEMORY BREAKPOINT ON ACCESS, после чего нажать RUN. Остановка произойдёт, когда элемент будет прочитан, то есть сработает соответствующий JMP или CALL.

1d0d896a2bf7dbd9ef9733df5a83d7e5.png

Хорошо, дошли до CALL’а с помощью любого из этих двух методов.

6cffacb5aebc58a35e9a904e4b694c3d.png

Входим в режим трассировки в OllyDbg.

accf52031cb7f7a4893fc99d1a5aa43b.png

Важно выбрать TRACE INTO, чтобы трассировать строку за строкой. Если выберем TRACE OVER, не будем входить в CALL’ы и можем потерпеть неудачу в задуманном нами.

20865444607248825cf07aa6638c7734.png

Теперь останавливаемся на условии, установленном нами. Если глянем в нижнюю часть OllyDbg:

23638dc0fbc5b605863bc4c1b4984ecf.png

Остановились, так как EIP находится в диапазоне 58000000-7FFFFFFF. Давайте проверим и убедимся, что остановка не произошла из-за исключения или по какой другой причине.

d09c90b1db422047283a850fd676c0ae.png

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

5f458a22ff166831057a247f9b1c7198.png

782de03a11641cbba1645d38ee34fa8f.png

Возвращаемся в 4271DC, как и должно быть.

Ок, сейчас нам не удалось увидеть, что это за API-функция, так как OllyDbg ничего не сказал, и перво-наперво нужно проанализировать код из этой DLL.

2524090a4544ba1755038d7770fffbe8.png

301d7c0f329cf0043bfa23461063a9df.png

Видим непосредственно внизу пояснение, в котором OllyDbg отображает имя API-функции, которой соответствует значение EIP.

0536e0847490a2390f4555cbf9dd7572.png

Другая возможность оттрасировать CALL, чтобы дойти до API-функции – это:

228393b00dc2c78e6dab39e35ed40c95.png

Данный случай – это противоположность предыдущего. OllyDbg проверяет, что EIP выходит за рамки секций EXE-файла и секций, идущих до первой DLL.

Другая возможность:

12b37dd9ecacedd4dcca7ecb0c0c8122.png

В редких случаях, когда упаковщик создаёт смешанные секции внутри DLL, можно использовать комбинированный метод: сначала остановиться при нахождении RET, а затем – когда первая строка стрека будет равна 4271DC, то есть возврату из API-функции. Этот метод имеет целью остановку на возврате из API-функции, и во многих случаях он эффективен для многих упаковщиков, которые эмулируют первые строки функции и прыгают на третью или четвёртую, обычно RET всегда соблюдается и остановка происходит на нужной строке. Если рестартуем OllyDbg и снова остановимся на CALL’е, то можем его быстренько опробовать.

То есть здесь нужно указать два условия за раз с помощью объединения их, используя “&&”, который указывает, что оба условия должны выполняться, то есть “&&” эквивалентно “И”.

В случае, если захотим остановиться на том месте, где выполняется одно из условий, используем “||”, что эквивалентно “ИЛИ”.

То есть

[ESP]==4271dc && byte [eip]==0C3

означает, что выполняются одновременно два условия, то есть

[ESP]==4271dc (первая строка стека, являющаяся точкой возврата из API-функции)

byte [eip]==0C3 (байт, на который указывает EIP и который запускается – RET, то есть C3)

Если от CALL запустим трассировку с данным условием, то увидим, что произойдёт остановка на RET’е API-функции.

c26e0028786aa0b21dde9b337d017d5d.png

240fda39d709f94a6402b6956ac6daff.png

При срабатывании обоих условий за раз, трассировка останавливается. Сейчас, находясь на RET’е, нам сложнее узнать имя выполняющейся API-функции, так как не находимся в её начале. То же самое случается, когда упаковщик имитирует две-три первые строки API-функции и находимся на 4-ой или 5-ой – тогда OllyDbg не показывает имя, но есть различные способы, чтобы его узнать.

Смотрим список того, что мы трассируем, для чего нажимаем на кнопку с тремя точками.

7a9052d0c4070b37733df0aad5b2c7a8.png

d8e06c47824bc1a42dc6dbced2584a21.png

Видим, что первая оттрасированная строка DLL отмечена стрелкой. Имя API-функции нам не показывается, так что сделали анализ кода, а затем – двойной щелчок, отмеченный стрелкой.

05754ea6b7f84f7736e13296e0293592.png

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

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

В любой части после RET введём CALL (используя “Assemble” или нажав на клавишу пробела на строке), который должен вести в место, являющееся, как мы подозреваем, началом API-функции. В данном случае:

CALL 7C8114ab

Похоже на начало API-функции на моей машине, ввожу адрес:

3a19f1041dc51199c987e9736f318609.png

5007eaf134458520221e90ac47b9ad4b.png

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

ef1c6d59bd2c72afa63fbec5c47cd30e.png

И так делаем в области, где должно располагаться начало API-функции, пока OllyDbg нам не покажет имя API-функции. Обычно довольно легко предположить, где находится начало,

0d91784a6b0a387949ac237ec60f5c50.png

Убираем введённую нами строку с помощью UNDO SELECTION.

50d7e8d6acf419db79e40ae251c87208.png

Ок, мы научились вручную определять имя API-функции, так что можем пойти в IMP REC, сделать двойной щелчок на неправильном элементе, который нужно починить, и ввести правильное имя.

4e56e6569ee7edf340c5d1bd894b5167.png

6b5a0dd2df636f90da2ce596da7f1a65.png

Теперь нажмём SHOW INVALID и увидим, что указанный элемент уже отмечен как правильный, что для нас очень хорошо.

Другой способ, которым можно починить элемент – это написать в данном элементе с помощью OllyDbg правильный адрес API-функции на нашей машине.

68292772871d6c79f44e72108f261bcd.png

Элемент, который мы исследуем, находится по адресу 460ADC. Перезапишем его значение найденным адресом API-функции на нашей машине (мы ранее узнали, что API-функция начинается на моей машине по адресу 7C81114AB).

6f759ea6466c177556cd5fb791bd299b.png

Теперь видим, что элемент починен. Если сейчас очистим в IMP REC’е все элементы, нажав на кнопку CLEAR IMPORTS, а потом снова нажмём GET IMPORTS, то увидим, что элемент отмечен как правильный.

e0f18323780260c98446ac3d2c809513.png

972756f87f907eb25f037cd2d5dc6f08.png

8a2e42825ee2d776ca9c01da8b3c1b4f.png

Как видим, указать правильный адрес API-функции в соответствующем элемент напрямую в IAT с помощью OllyDbg или указать имя API-функции в IMP REC’е для данного элемента – это одно и то же.

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

В IMP REC’е есть функция для помощи фанатикам ручного метода – он позволяет сохранить таблицу с исправлениями с помощью нажатия на кнопку “SAVE TREE”, а потом, если прервали работу, можем вернуться на OEP программы, открыть IMP REC, установить данные OEP, RVA и SIZE, а затем загрузить сохранённый ранее IAT, используя кнопку “LOAD TREE”.

f5c8107bf2967d29197eb9b711d936ba.png

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

Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!


Видим, что есть плагин для telock, который нужно скопировать в папку плагинов для IMP REC’а. Посмотрим, как он работает.

caa721d60ba0188832fcd154a661acb3.png

Копируем DLL в папку PLUGIN.

e7119776524bd480f4c35e70632269d0.png

Теперь перезапускаем IMP REC, и возвратившись к вводу данных, нажимаем SHOW INVALID, делаем щелчок правой кнопкой мыши, выбираем PLUGIN TRACERS и ищем telock. После трассировки видим, что исправны все элементы, кроме четырёх, поэтому видим важность ручной трассировки, так как плагин пропустил несколько элементов, которые можно починить вручную.

4f1f814e4d2789261d89d6a18856cfb4.png

Здесь видим, что IMP REC сообщает нам об оставшихся 4 элементах, которые нужно починить. Их можно оттрассировать вручную, как мы это делали в начале. Таким образом, использование плагина имеет свои ограничения, так что всё зависит от того, существует ли плагин для упаковщика, который применяется в данном случае.

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

86befd3252517abb7ba281cee071a67d.png

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

4212f6e507373f78422c20068f41cb3e.png

Неудача, пробуем с помощью остальных двух, после второго IMP REC виснет, поэтому несмотря на то, что эти методы существуют, в данном случае они не работают, а обычно приводят к зависанию. Срабатывают они только для самых простых упаковщиков.

Следующий метод – это «JMP-CALL MAGICO», который стал популярен в туториалах CRACKSLATINOS о различных упаковщиках.

Этот метод основывается на попытке найти момент, когда упаковщик сохраняет значения в IAT, и сравнить, что происходит, когда сохраняется правильное значение, и что, когда неправильное.

Используем в качестве примера элемент, которые мы исследовали ранее – GetVersion, являющийся переадресовочным или плохим. Перезапустим крэкми, упакованный telock’ом, и поищем указанный элемент в начале до запуска программы.

467335c9d071bfffbd2b26281392fea0.png

В DUMP’е смотрим адрес 460ADC, куда при запуске крэкми в некоторый момент до прибытия в OEP записывается плохое значение переадресовочного элемента, которое на моей машине равно 9F06F7, и это означает, что в этот момент упаковщик записывает данное значение в элемент.

9e28dfdf3bb901cf58f4fe9ae3bad5e5.png

Для того, чтобы перехватить момент, в который происходит запись данного значения, обычно вначале на элемент устанавливается HARDWARE BPX ON WRITE, но так как этот упаковщик обнаруживает HARDWARE BPX, устанавливаем MEMORY BREAKPOINT ON WRITE

19b42dea005105ade1f133d6cbda2a87.png .

Нажав RUN, видим, что в первый раз MEMORY BREAKPOINT срабатывает здесь:

fba7a7285c9257a2b56df8899d68494b.png

Видим, что это не то место, которое мы ищем, потому при выполнении строки с помощью F8 плохое значение не сохраняется в элементе, так что жмём RUN снова.

В следующий раз останавливаемся здесь:

1471b55d7e347a464ae8d906fc8f1bda.png

Видим, что здесь также не происходит сохранение плохого значения, опять жмём RUN.

38249af2236b511a759f436ca2ad22eb.png

Следующее место также не содержит нужного нам.

bd085ca563185d5869267c4e4be1e729.png

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

e26a5f30087ac78a2abd3263c3831f78.png

При проходе через «REP MOVS, IAT» IAT содержит эти значения, но плохого среди них нет, нажимаем RUN и продолжаем.

51ba0ea973f90c9e1d9527a4cb9dbc2b.png

Когда прибываем сюда, видим, что ECX содержит плохое значение, которое сохраняется в элемент.

781eee00fb29374cddaff036a298b399.png

ECX равен 9F06F7, и это значение сохраняется по адресу, содержащемуся в EAX, то есть в 460ADC, в исследуемый нами элемент, и это и есть место, которое мы хотели найти.

aa51ec4292509af721d7c6a85be791ec.png

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

334cc6234068122296a3d0526a5d17b5.png

Как видим, дойдя до данного JE, чуть ниже в регистрах отображается имя API-функции (GetVersion), которая отвечает за данный элемент, загруженный плохим значением.

e83d76272539b49874ba761cb8c5938d.png

Далее видим, что дошли до вызова GetProcAddress для нахождения адреса GetVersion на моей машен, так как параметры следующие:

f5bc0073e24faa8e96d2b4161553188e.png

Заходим в API-функцию, чтобы посмотреть параметры, хотя это не обходимо. Проходим CALL с помощью F8.

d0c04dd1b30eea2f2affc0da52f21e2a.png

А в EAX нам возвращается адрес GetVestion на нашей машине. Продолжаем трассировку.

ebf61ee7deb7f05bba213a6700382abe.png

Мы у перехода. Посмотрим, куда он ведёт без трассировки. Нажимаем кнопку мыши и FOLLOW.

ca4e71ea626d9d67771de62cf1a76cdc.png

Видим, что здесь сохраняется адрес, но не в IAT, а в другое место, так как EDI равен:

77bed48f1de24693a71be2d306e4c32b.png

После сохранения данных значений идёт следующий JMP:

b69b21f8688573cbf424535ed5e8a486.png

Который нас возвращает в начало процесса.

Смотрим с помощью FOLLOW, куда мы придём.

b4616e5f011e3e8eeffb4059fedc7a85.png

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

Много раз я составлял себе табличку, которая сильно мне помогала, и где я отмечаль, что в данном чикле происходит с такими переходами у хороших элементов и что у плохих.

ДЛЯ ПЛОХИХ ЭЛЕМЕНТОВ (помещаю изображения всех переходов по мере их появления в трассировка вплоть до момента, когда происходит сохранение значения)

498708717329e9e7a031d7a9acf85033.png

2f1020cbfe0d9286b90450fa16927a0e.png

fefee2c58e016e074bda0ed7e22f7c5a.png

23423a664aa1031af3ea4bb90aed427e.png

aa864a9a9abba599852b81969da108e8.png

bdb153ec5aa05a7f2b26786e6a7f2cfc.png

1084c1413ba15e66b3286037dd8488b2.png

Это миницикл сразу после выхода из него:

ef12e36fbf4c5ec46c273e7ebfd45079.png

02c05786651a074e9ccf79ba085b4c07.png

55a05ae14b3695e3be0366e239abb316.png

5779c8affabb7ce7dc3bc7837c207d67.png

Здесь доходим до GetProcAddress, а затем делаем переход туда, где он сохраняется.

bb7ad5ebb600bfcb478a38c2bc3880f5.png

26df11fb57c8e389da73189a186f0305.png

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

Идём в OEP.

5280bdeeca095457586e511ea72a1243.png

В качестве хорошего элемента выбираем 460BAC, теперь повторяем тот же процесс, что и с плохим.

Рестартуем и ищем элемент до запуска самой программы.

023e3e9ae93ab8d86d63fed751b6cd38.png

Теперь устанавливаем MEMORY BREAKPOINT ON WRITE, чтобы попытаться перехватить момент, в который упаковщик сохрняет хороший элемент.

352cba3c6923b91b2ea358f5e17bb5de.png

90735d733337eb69a57b3f78973d8bb9.png

Видим, что EAX содержит значение возможной API-функции, хотя её имя нам сообщается, однако если посмотрим с помощью GOTO EXPRESSION-EAX.

518bbee97c7d4624d17299b91580d052.png

56743664ae84cf109116fdc22dead3e9.png

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

a477e5012b1674c7f7a50a8e5e8a03bd.png

Теперь сделаем ту же процедуру, что проделали с плохим элементом, ожидаем, что всё будет идти в том же порядке.

ДЛЯ ХОРОШИХ ЭЛЕМЕНТОВ

Доходим до начала цикла и начинаем трассировку.

860604d685d6864ecc8d6b81668e9c04.png

552469415c69e752a3d37f174a0304c9.png

Этот переход такой же как и в плохом элементе.

1eb98d32d1a4219d27d12219f2faa158.png

В плохих элементах перехода не происходило, но переход очень маленький, не думаю, что он решающий.

13b3311e56b76375cd59d6b92b02cdda.png

Этот переход не равен тому, что в плохом элементе.

98aa952079c91ff309d8962b627183b2.png

Здесь видим значительное отличие: этот переход в плохих элементах не срабатывает, а здесь – да, и видим, что перепрыгиваемый код велик по объёму.

ca8c6f6d68d84caf4831f84adeb39991.png

Здесь видим, что переход достаточно велик, что может приводить к значительной разнице в обработке элемента в зависимости от того, является ли он хорошим или плохим, то есть если всё идёт, как мы считаем, то это может быть волшебный переход, который решает, будет ли элемент сохранён как хороший или плохой. Это значит, что для сохранения элемент как правильный, переход должен сработать, так что в данном случае есть значительная вероятность, что будет сделан прыжок.

Но этот переход не встречается в начале программы, поэтому мы должны быть очень внимательны, если рестартуем OllyDbg и будем искать этот переход.

b5c80e4ccf44da7d8f515e386558c5fc.png

Видим, что в начале идёт чистый мусор, так что упаковщик создаёт этот переход гораздо позже.

a582241ea3df06e4d177701fa4bf420c.png

Дело в том, что так как останавливаемся здесь, HBP использовать нельзя, а BP будет обнаружен, так что нам нужно напрячь воображение.

Устанавливаем BPM ON WRITE, который охватывает весь IAT, чтобы остановиться, когда туда будет записано первое значение.

IAT начинается в 460818, а заканчивается в 460F28. Охватываем всю эту область с помощью BPM ON WRITE.

d466cc2756951eb606f68dc0b4840062.png

Весь IAT охвачен BPM ON WRITE, теперь продолжаем, пока не будет сохранено первое значение.

3227f476edb59b96c38603f2ba82a1d2.png

На STOS’ах останавливаемся множество раз, так как BPM охватывает весь IAT, так что сейчас мы узнаем, виден ли уже в этот момент возможный волшебный переход.

da72af5db35d935a1b8412d2557148c2.png

Так, он есть, мы проходим через него, и если заменить на JMP, снимем BPM и пойдём в OEP:

11ac6353bffeebed0db2c24f4e15cef0.png

Есть две возможности: упаковщик обнаружит изменения и прекратит выполнение, или всё пройдёт нормально и мы окажемся в OEP, так что делаем RUN.

4111017bd21d381f668bcb49d5f2a364.png

Прибываем в OEP, смотрим IAT:

b235939cfaa42eef02001ff089cb7b99.png

Все значения верны, хе-хе, наша IAT починена, теперь делаем дамп.

ce2a9c375fb69ca86ac690731c44ac23.png

d02f25c97dfcd29b33e45686ea917eaa.png

Снимаем галочку с REBUILD IMPORT.

И дампим. Потом открываем IMP REc и снова устанавливаем значения RVA, SIZE и OEP.

624f643ac81144265b12390e7a0f19c0.png

Видим, что сейчас всё в порядке, волшебный переход сделал своё волшебство, хе-хе.

Теперь чиним дамп, нажимая FIX DUMP.

b10bb7a36688c2cbaa64b88097816cd8.png

Сохраняем его как dumped_.exe и запускаем, чтобы убедиться, что он работает.

f14e7dd413262e1741619265305b04d7.png

Работает прекрасно, хе-хе.

Отлично, мы рассмотрели метод для нахождения волшебного перехода, который всегда различается у разных упаковщиков, но сравнив, что происходит при заполнении хороших и плохих элементов, всегда можем легко найти решение. В главе 38 мы продолжим рассмотрение упаковщиков.
 

О нас

  • Наше сообщество существует уже много лет и гордится тем, что предлагает непредвзятое, критическое обсуждение различных тем среди людей разных слоев общества. Мы работаем каждый день, чтобы убедиться, что наше сообщество является одним из лучших.

    Dark-Time 2015 - 2022

    При поддержке: XenForo.Info

Быстрая навигация

Меню пользователя