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

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

AnGel

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

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!


Продолжаем, очень плавно повышая сложность изучаемых упаковщиков. В этой главе мы рассмотрим два распакуй-меня – crunch (или bitatrs 5.0) и telock 0.98, которые послужат нам для освоения темы переадресовочных элемент IAT. Оба распакуй-меня приложены к данному туториалу, поэтому у вас не должно быть проблем, где их взять.

Начнём с самого простого – с BITARTS. Загрузим его в OllyDbg.

6c0aefe51fc9a6dea67658610c3910ca.png

Видим, что начального PUSHAD нет, так что потрассируем немного с помощью F7.

0a657e65e2530ca057a3115346001fb1.png

Доходим до PUSHAD, проходим его с помощью F7 и делаем ESP – FOLLOW IN DUMP.

f785d75df7ba330b16d37d0aae15082b.png

И устанавливаем точку аппаратного останова (hardware breakpoint) на доступ к первым байтам.

b62c7082254007d7101cdf35ab3da4b3.png

Теперь нажимаем F9 и после прохода через другое исключение останавливаемся на точке аппаратного останова.

30d1b9b19e760ebb91c9c3e196883a66.png

Трассируем строки дальше и оказываемся в OEP.

d718e445caec28ebc987dbc43d354930.png

Также оказаться в OEP можно с помощью поисковика OEP OllyDbg, если последняя пропатчена для этого, или почти любым другим методом, рассмотренным в предыдущих главах «Введения…».

Как видим, указанный адрес находится в первой секции после заголовка.

ff740fe0019faee1913050a1ab85a345.png

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

49c6de45dea6c198b494af69bb13dc14.png

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

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

Значит, 460ADC – это элемент IAT, соответствующий GetVersion. Идём в DUMP и сверяемся с IAT.

1b6d5cabac45740db649ae4d849153f3.png

Она довольно большая, хе-хе.

f54a5eba237e6454612396a90aa9068b.png

Первый элемент в IAT – это GetVersion, который соответствует Kernel32.dll, можно посмотреть в карте памяти, куда ведёт указанный адрес 7Cxxxxxx.

166ec2ed10b5374eed093df4bcb9e2d7.png

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

Хорошо, после этого спускаем ниже и находим группу API-функций с адресами вида 77xxxxxx.

Если есть какие-то сомнения относительно того, к какой DLL принадлежит элемент, то кроме анализа карты памяти, можно отметить его в IAT, нажать правую кнопку мыши и выбрать FIND REFERENCES.

4e66a00284023afc81887f1b2eecf0d7.png

Так что ищем в списке все инструкции, использующие данный элемент (это будет работать всегда: и когда список показывает секцию программы, где собственно выполняется работа, в данном случае первая секцию, если будем искать в ней ссылки, и в списке, отображающем другую секцию, поищем в ней, вероятно, что ничего не найдём, так что нужно проверять перед использованием данного метода, находимся ли мы в правильной секции, где исполняется распакованная программа, или рядом с областью OEP, что одно и то же),

1386c41619fb3347ed96f259d7c6dbe0.png

Здесь видимы CALL’ы, которые есть в первой секции и соответствующие указанному элементу. Та, которая относится к API-функции VariatClear из OleAut32.dll:

08421d4b16b29c339e1e9bd05b72e6be.png

Смотрим в карте памяти, видим, что, конечно, следующая группа попадает в секцию кода OleAut32.dll.

d6e2e7ed59a52b3d6d0bd6b183f5e90f.png

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

866f02a92e281bfc2c693e0a8c3d537f.png

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

2f36d8c04cde9c950858de83cd32cc42.png

57197522f1285a1d940fe14ac674ff1f.png

Видим, что есть элемент IAT, который приводит нас в данном случае к OleUiBusyA из oledlg.dll. Проверим через карту памяти.

c072bfa43cb5596d3a4d92c4fd5a072f.png

Логично, что элемент ведёт в секцию кода указанной DLL, поэтому это элемент IAT, единственный для данной DLL. Далее видим разделение, а после него группу множества переходов, которые ни сгруппированы так, чтобы указывать на последовательные адреса, ни сами эти адреса не указывают на какую-либо DLL.

19d6ec1a8bc0d56e95ed9515ef2b766a.png

Если отметим какой-нибудь из них и сделаем FIND REFERENCES:

0c7b8c145f960b6a2658b19dd0ec7588.png

aed53c1f7591b02f254be215618b70fa.png

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

КОНЕЦ: 460F28

37d3d85903b9efea65e5488f922bc4a1.png

Теперь проверим, откуда начинается IAT-схема.

c5949d5e141ab4c287c16efa5266ae35.png

Идём вверх и видим, что схема повторяется, пока не доходим до сюда. Лазурным отмечены разделения, группа, отмеченная жёлтым, опознаётся как ведущая в одну и ту же DLL, далее есть одно разделение, а затем элемент, ведущий в 80000008. Так как не знаем, соответствует ли он какой-либо DLL, то проверяем это с помощью FIND REFERENCES.

e7da92b3b2c6ba2ca35f2f9d66509328.png

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

e68f50fb875b2332a252fcf658ca08e2.png

Теперь у нас есть начало и конец IAT. Вычисляем размер:

НАЧАЛО – КОНЕЦ = 460F28 – 460818

abe3618836e1d2b688387395685644df.png

То есть размер равен 710.

Данные для IMP REC (от OEP и НАЧАЛА надо отнять базу образа):



OEP = 271B0
НАЧАЛО или RVA = 60818
РАЗМЕР = 710
Хорошо, теперь сделаем дамп с помощью OllyDump.

32c131041c199493f9d4fad20da822ea.png

2ec784869e60d503fe8d24e536263a58.png

Убираем галочку с Rebuild Import и дампим.

e2a9a9fc58a1e4b56bb3dc9f0c4a76c5.png

Далее открываем IMP REC без закрытия OllyDbg, в котором загружен исходный файл, остановленный на OEP.

7a470e88c8d55666db59781c94ec2e4e.png

Ищем процесс в выпадающем меню и устанавливаем найденные значения.

2c2a24b46e38fa677c56076521c90b4e.png

И нажимаем GET IMPORTS.

a23630ea98478787b030d5208f3ac2af.png

Видим, что упаковщик не делает ничего особенного, чтобы затруднить нам работу здесь, все DLL правильны, так что нажимаем FIX DUMP и ищем дамп для починки.

c0b7fabdd674ed37f08426309b21d3ab.png

Починенный файл сохраняется под именем unpacked_.exe, смотрим, работает ли он.

1ba31594ee4a07b99341cf180f2c16e7.png

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

Следующая жертва – это telock 0.98, которая послужит нам для того, чтобы открыть тему о переадресовочных элементах IAT.

0cdad4fbde2474960b05b4a4232ef544.png

Пробуем метод PUSHAD, трассируем немного, чтобы понять, есть ли здесь какой-нибудь PUSHAD.

b3fb87529c56f580d5b1a70d4be55b27.png

Проходим его с помощью F7, затем ESP-FOLLOW IN DUMP.

96eb758037eec6ba0e4c6913c1905882.png

4e9c5dd087a84ef696fe8140f8677a8e.png

Убираем анализ, чтобы посмотреть код.

ca390de6d8bbeaf1177d7032c58a6b71.png

Видим, что метод PUSHAD не работает, а также есть защита от точек аппаратного останова, потому что при их использовании возникнет ошибка, так что убираем их.

caf55b842beaa6d00aca592b6192feb7.png

13a0cf0b7e2cb3dbd0ea67320efc0e59.png

И перезапускаем OllyDbg.

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

9ff735d82b7343cdd2d86ca2401e933d.png

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

dfbbf0b84a814a046e1d50f371e26701.png

После прохода через несколько исключений с помощью SHIFT+F9, доходим до 4666f1.

7650a07809b3dca6d3f83181420bdc85.png

Теперь устанавливаем MEMORY BREAKPOINT ON ACCESS на первую секцию.

c746760c39f7357cc3b0ea13debe0b6c.png

Помним, что нужно нажать SHIFT+F9, чтобы миновать исключение, на котором остановились, без ошибок.

Ок, останавливаемся на паре исключений типа SINGLE STEP и прибываем в OEP в первой секции, где оказываемся на MEMORY BREAKPOINT ON EXECUTION.

9ecd4769c21e32a77a3e98c7848da92b.png

Значит, OEP равен 4271B0, такой же, как и у предыдущего примера CRUNCH, поэтому похоже, что это та же программа, упакованная другим пакером, но всё равно будем работать с ней, как если бы мы ничего не знали о ней.

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

Если сделаем

db377bedb4f2cbaecf4206241375079a.png

для того, чтобы увидеть вызовы на другие секции и выяснить, есть ли вызовы каких-либо API-функций.

6b3d0673003d682acda6bb3fc196180d.png

Видим, что множество косвенных вызовов, которые вместо того, чтобы указывать на API-функции, ведут на моей машине в секцию 9fxxxx. Очевидно, что на других машинах эти адреса могут меняться и иметь другие значения.

Если посмотрим, что в этом списке ниже:

1de13c251fedf488617cc66036d291cc.png

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

f789865a840b68ec5199f8dc6b8a03ba.png

Тут у нас один – это CALL 435CDE, который точно выведет нас на косвенные переходы к API-функциям, отмечаем его, нажимаем правую кнопку мыши и выбираем FOLLOW.

0d5a0a56b191e39eff736390f0cf66a0.png

Видим косвенные переходы на API-функции, поэтому знаем, что берутся значения из IAT, т.е. 460ED4 – это элемент IAT. Идём в DUMP, чтобы посмотреть на него.

6f66dbe1520cd2863e129b6168b661ec.png

Видим, что заключительная часть IAT корректна и совпадает с той, что в примере CRUNCH. Конец IAT здесь также 460F28. Здесь конец легко определить, так как потом идут одни нули. Теперь идём вниз.

936176d4cf62762a00e8a62038f9fb1f.png

Видим, что следующая группа конфликтует, элемент, непосредственно стоящий до разделения соответствует 76B1A8F7. Если отметим его, нажмём правую кнопку мыши и выберем FIND REFERENCES:

f0750776e9b78ab0d499754bde631074.png

Видим, что он относится к API-функции PlaySoundA из WINMM.dll, больше других значений, ведущих в DLL не встречается, однако если поищем ссылки:

25360bb9fa99fcb2939db943a11ef384.png

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

Это как раз то, что называется переадресовочными элементами. При запуске упаковщик перезаписывает некоторые элементы IAT значениями, указывающими на его собственные процедуры. В случае с предыдущим изображением:



004038A6 CALL DWORD PTR DS:[460E48]

Comment=DS:[00460E48]=00A00B61
Вместо сохранения правильного на моей машине адреса API-функции распаковщик заменяет его адресом собственного секции, им же созданной, во время выполнения, и там находится процедура, которая в результате выполняет правильную API-функцию.

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

ac3aae615302a2bb0b940d07ae785e0b.png

На самом деле мы не знаем, что оно ведёт на GetVersion, мы знаем только, что в предыдущем примере, где была запакована такая же программа с помощью CRUNCH. Здесь находится косвенный CALL, доходим до него с помощью F7 и входим внутрь, чтобы посмотреть, что там находится.

f7709ea0c8a9d45931412274c12378c6.png

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

be429ce09db4474e2701591bf7bf4c43.png

Поэтому программа при запуске CALL идёт сюда, на моей машине это адрес 9F06F7, на ваших оно может быть другим.

Это адрес не принадлежит какой-либо секции программы.

fc3dd34a049bc25cd2a969c53d4d6dfd.png

Здесь видим секции программы (выделены лазурным цветом), а ниже секцию без имени, где находится процедура, куда переходит программа.

Если перезапустим программу, то увидим, что эта секция в начале не существует.

0f7acaadccf1ad64fd9ada14032a1427.png

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

Можем поставить BP на API-функцию VirtualAlloc, которая используется для создания виртуальных секций.

e3ec815db33eb4c606382ad1663552d9.png

Теперь делаем RUN и, если все галочки в исключениях были отмечены, то увидим, что программа завершилась и более не выполняется. Очевидно, что она обнаружила установленный BP, попробуем поставить его на RET из вышеуказанной функции.

703538753042b08761663931bb7f0f57.png

Теперь делаем RUN.

c5020d4429afcdc96a1230d44d4ac366.png

Когда выполнение останавливается на возвращении из API-функции, в EAX содержится адрес созданной секции.

2f294ee9a23ca347caf5a9511c8c91c3.png

Созданные секции можно посмотреть в карте памяти.

bf8ae89a8d7c9bca9fffb84aba477704.png

Нам может помочь то, что когда программа создаёт секции для собственного использования, они помечаются как PRIV (т.е. private или собственная), это означает, что этих секций не было в начале до распаковки, так что точно знаем, что они были созданы распаковщиком.

Поэтому убираем BP и прибываем в OEP, как и раньше убрав галочки с исключений, и дойдя до последнего, устанавливая BPM ON ACCESS на первую секцию. Последнее исключение проходим с помощью SHIFT+F9.

45a5b598e5f88325384bcf2974069b17.png

Теперь снова прибываем в OEP и посмотрим в карту памяти:

59405fce0a1cf798f499e1b154a70322.png

Видим созданные секции, которые будут использоваться программой, отмеченные как PRIV, и сюда будут перенаправляться косвенные вызовы. К ним мы и возвратимся, используя F7.

af1a50f1cb56a467e38964a091736dc7.png

Трассируем, чтобы узнать, куда приведёт данная процедура.

e879a3317242ec350c7a0d2b60f04d88.png

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

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

Это и есть переадресовочный элемент.

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

Поэтому возвращаемся в IAT, который мы уже смотрели, чтобы найти НАЧАЛО и КОНЕЦ.

df1e53d46ec9aac9205e429543b4cc5a.png

Все элементы, которые ведут в секцию 0Axxxxxx (на моей машине) являются переадресовочными элементами. Идём в код, созданный распаковщиком, который не существует при запуске программы с OEP, поэтому идём ниже, чтобы увидеть, найдётся ли НАЧАЛО IAT.

ecbc5062f23826b88d2ed83513e07c68.png

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

960b73e3859d99d46236359b62c95f42.png

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

64ff8d154902c23f4c904434cc631b03.png

Далее видим элементы, которые на моей машине ведут в A1xxxx – это ещё одна секция, созданная упаковщиком.

a143b70b296aa933feb4c12ff8c7da36.png

Также, если поищем, то найдём в них ссылки.

528f9d0681bb9a4c711be0c44e7be6e9.png

Значит, это элементы IAT, и продолжаем спускаться дальше, видим, что оказались здесь:

a5c530adc87245a5114e84b971d2860b.png

Где есть элементы, ведущие в какую-то DLL, затем разделения, а выше никакие элементы не содержат ссылки.

56cb950b41fc5df20d754b6202cc93a8.png

Как и в случае с CRUNCH’ем началом IAT является 460818, размер 710, и OEP равен 4271B0. Отнимаем от него базу образа.



OEP = 271B0
НАЧАЛО или RVA = 60818
РАЗМЕР = 710
Поэтому открываем IMP REC, не закрывая OllyDbg.

68d038973b94d70ddc3879e3ff9c86cb.png

И устанавливаем найденные значения.

cb834c2555cb7c40d2243ca8ce70f16c.png

Теперь нажимаем GET IMPORTS.

78cffacded65080192b9298891c6e10b.png

Как видим, IMP REC обнаружил, что есть переадресовочные элементы и пометил их как NO, посмотрим их, нажав SHOW INVALIDS.

613fac369935ed5cdec493ddba6cf32b.png

IMP REC показал нам элементы IAT, которые не указывают на какую-либо API-функцию и которые ведут в секции, созданные упаковщиком.

Конечно, мы не будем трассировать все эти неправильные элементы вручную, есть несколько методов, чтобы их починить. IMP REC предоставляет несколько возможностей, также есть другие «ручные» методы, но без трассировки, хе-хе.

Все эти методы мы рассмотрим в 37 главе, поэтому вы должны хорошо уяснить рассмотренную тему о переадресовочных элементах, так как в следующей главе будут изложены несколько методов, чтобы их починить. Пока что мы не можем починить дамп, так как IMP REC’у требуется, чтобы все элементы были отмечены как YES, то есть указывали на API-функции из DLL, и не было никаких переадресовочных элементов, так что эту проблему на надо будет решить.
 

О нас

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

    Dark-Time 2015 - 2022

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

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

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