R0 CREW

Malware Analysis Tutorial 14: Retrieve Self-Decoding Key (Перевод: coldfire)

Перейти к содержанию

Цели урока:

  1. Изучить PE манифест
  2. Попрактиковаться в анализе вызова функций, передачи параметров и стеке

1. Введение

В этом уроке, мы продемонстрируем вам как Мах++ извлекает «конкретный экземпляр» ключа для дешифрования с PE манифеста. Внедряя ключ для дешифрования в PE манифест, вирус может узнать копию от другого вируса и таким образом определить какая копия находится на ПК(таким образом ID дается каждой жертве и может сказать вирусному аналитику, что эта копия была отдебажена). Другое известное применение ID состоит в создание каждой копии исполняемого файла значительно другой от друг друга, что делает более тяжелой работы для детектора вирусов для определения сигнатуры вируса.

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

2. Подготовка

(0) Запустите образ WinXP в режиме ОТЛАДКИ. Теперь в вашей основной системе, откройте командую строку Windows и напишите следующее - CD to “c:\Program Files\Debugging Tools for Windows (x86)” ( путь, где WinDBG установлен). Далее напишите “windbg -b -k com:pipe,port=\.\pipe\com_12” (проверьте, что com порт на вашей Vbox установлен). Когда WinDbg запустится, напишите «g»(go) дважды для того, что бы продолжить работу.

(1) Теперь запустите IMM в экземпляре WinXP, очистите все аппаратные и программные точки останова в IMM ( смотрите see View->Breakpoints и View->Hardware Breakpoints).

(2) Перейдите по адресу 0x4012DC и установите там аппаратную точку останову. ( почему не программную точку останова? Потому что эта область —самостоятельно извлекается и перезаписывается и поэтому программная точка останова будет утеряна). Обратите внимание, что когда вы перейдете на адрес 0x4012DC, сразу нажмите на строчке и установите аппаратную точку останова(это пока еще мусорный код).

(3) Нажмите F9 несколько раз, что бы оказаться на адресе 0x4012DC. Вы встретите несколько точек останова перед тем как оказаться на 0x4012DC. Если вы обратите внимание, то причина этому был трюк с командой int 2d (объясненный в уроках 3 — 5). Просто игнорируйте ее и продолжайте (используя F9) пока не прерветесь на 0x4012DC.

Рис. 1 показывает код, который вы должны увидеть. Как вы можете видеть, он находится прямо перед вызовом RtlAddVectoredException, где аппаратная точка остановка установлена для того, что бы прервать вызов LdrLoadDll(смотри Урок 11 для деталей). На данный момент, код по адресу 0x3C24FB не был еще распокован. Если вы перейдете по адерсу 0x3C24FB в этот момент, IMM скажет, что этот адрес не доступен.

Рис. 1. Код по адресу 0x4012DC

(4) Теперь прокрутите вниз около 2 страниц и установите программную точку останова на 0x401417. Это идет сразу после вызова LdrLoadDll(“lz32.dll”), где Мах++ заканчивает загрузку z32.dll.

Рис. 2. код по адресу 0x401407

(6) Теперь мы установили программную точку останова на адрес 0x3C24FB. Перейдите по адресу 0x3C24FB и установите программную точку остановка там. Нажмите SHIFT+F9 что бы оказаться на 0x3C24FB.

(рис. 3 показывает код, который вы должны увидеть. Первая инструкция по адресу 0x3C24FB должна быть CMP DWORD PTR SS:[ESP+8], -2. Вы должны заметить, что сейчас [ESP+8] равно -2, и если мы продолжим выполнение, то окажемся на инструкции CALL 0x003C23DB. Нажмите F7, что бы перейти внутрь функции 0x003C23DB.)

Рис. 3. код по адресу 0x3C24FB

3. Введение в суть: функция 0x003C23DB

Тело функции, находящейся по адресу 0x003C23DB показана на рис. 4. Если вы посмотрите на комментарии, вы должно быть заметили, что эта функция делает много вредоносных действий. Во-первых, она извлекает само декодируемый ключ с PE манифеста. Далее она внедряется в поток текущего процесса и устанавливает таймер, который убивает Max++.exe каждые 10 секунд после завершения процесса. Далее она инфицирует важные системные библиотеки такие как ntdll.dll и также случайно подбирает системный драйвер для заражения. Невозможно описать все вредоносные действия функции, находящейся по адресу 0x003C23DB, в одном уроке. Мы остановимся только на вызову функции по адресу 0x3C23FE (чтение декодируемого ключа).

Рис. 4. Вредоносные действия

4. RtlAdjustPrivilege по адресу 0x3C23F3

Для начала давайте изучим инструкцию “CALL DS:[3D10E8]” по адресу 0x3C23F3 (которая показана на рис. 4 и 5). Заметьте, что перед вызовом функции Max++'ом, устанавливается должным образом регистр DS. Когда мы попадем на адрес 0x003C23F3, значение DS + 0X3D10E8 — будет входным адресом функции ntdll.RtlAdjustPrivilege. IMM достаточно умен, что бы показать соответствующие комментарии в области для комментариев, что есть очень круто!!!(смотри рис. 2.). Наша задача попытаться определить какой смысл всех параметров этого вызова. Запрос в гугле RtlAdjustPrivilege приводит нас к документации, такой как в [1] и [2]. Скоро мы узнаем, что функция RtlAdjustPrivilege принимает 4 параметра:

  1. ULONG Privilege
  2. BOOLEAN Enable
  3. BOOLEAN CurrentThread
  4. OUT Boolean Enabled

Вопрос: каковы соответствующие значения в стеке?

Теперь посмотрите на содержимое стека на рис. 5. Вы можете немедленно сделать вывод, что 0х14 - Privilege, Enable = 0x1(true), CurrentThread = 0x0| и ENABLED = 0x12D6323 (почему? Потому что результирующее значение сохраняется по этому адресу — для проверки этого, изучите исходный код, находящийся на строчке 00174, в [2]).

Задание 1: Что значит значение 0x0 для параметра CurrentThread (подсказка? Посмотри исходный код в [2])

Теперь наиболее интригующая часть для нас: какой смысл значения 0х14 для Privilege? Мы можем проклинать макро определения констант в С (что если бы разработчики WINNT использовали перечисленные типы, это сделало бы работы значительно легче). Если вы изучили [1] хорошо, то должны были узнать, что это значение соответствует SeDebug privilege. (внимание: десятичное значение 0x14 = 20).

Для чего Мах++ нужны привилегии SeDebug? Если вы прочитали объяснение в [1], вы должны были заметить, что если процесс имеет SeDebug, то он может открывать другие процессы в системе, которые превосходно подходят для выополнения задач, таких как внедрение в другой процесс в текущем запущенном процессе(смотри рис. 1 в пункте 3).

Рис. 5. RtlAdjustPrivilege

5. Анализ вызываемой функции по адресу 0x3C23FE(CALL lz32.003C1129)

Теперь давайте углубимся в вызов функции, находящийся по адресу 0x3C23FE (смотри рис. 4). Нажмите F7, что бы попасть внутрь, рис.7 показывает тело функции, находящейся по адресу 0x003C1129. Это дает вам общее представление о том, что эта функция делает.
В ней есть несколько важный вызовов: по адресу 0x003C1131, она вызывает getModuleHandleW для того, что бы получить хендлер текущего потока, и потом по адресу 0x3C1145 вызывает LdrFindResource_U, что бы найти ресурсы соответствующие процессу, а далее по адресу 0x3C1159 вызывает LdrAccessResource. По адресу 0x003C116B она вызывает функцию strstr( что бы найти строку “”). Далее получает декодирующий ключ “11001800” и сохраняет его где-то в стеке по адресу 0x003C1185.

Рис. 7. Тело функции, находящейся по адресу 0x003C1129

Задание 2: Объясните значения параметров всех системных вызовов в теле функции(таких как getModuleHandleW and LdrAccessResource).

Задание 3: Объясните как было получен декодирующий ключ «11001800».

Задание 4***: Можете ли вы найти как «11001800» используется далее в коде Мах++?(подсказка: используйте точки останова)

© Translated by coldfire from r0 Crew

Ссылки

[1] “Topic: Tip: Easy way to enable privileges”
[2] ReactOS Doxygen, “RtlAdjustPrivilege source code”

UP