Что такое upx в njrat
Как пользоваться NjRAT? Приколы вируса удаленного доступа
Zip File, мамкины хацкеры. Сегодня мы наконец-то поговорим про ратники. Рассмотрим их основные функции, нюансы открытия портов, варианты решения проблемы с DynDNS и прочие вещи, которые так волнуют начинающих злоумышленников. Оговорочка по Фрейду. Конечно, же безопасников, а не злоумышленников. Ведь именно специалистам, отвечающим за защиту, приходится выявлять крыс на компьютерах в своих больших и малых конторах.
Для тех, кто не в теме, проведу краткий экскурс в историю. Ратники, они же Remote Access Trojan (трояны удаленного доступа) или попросту крысы, применяются хацкерами для получения доступа к ресурсам компьютера. По сути, это вирусные утилиты, разработанные по образу и подобию админских программ для обслуживания по удалёнке. Таких, как RAdmin, TeamViewer, TightVNC и прочие известные всем нам ремотки.
Однако принцип внедрения у ратников несколько отличается от вышеперечисленного софта. Для того, чтобы установить тот же RAdmin, вам, как минимум нужно побывать за компьютером пользователя 1 раз. Либо обладать правами на установку прог по сети. TeamViewer при первом запуске также выдаст рандомный пароль с уникальным ID, а для дальнейшего подключения без участия пользователя потребуется войти под своей учеткой.
В любом случае, ваш доступ к машине будет так или иначе санкционирован. Ратники же, имея под капотом вирусный бэкграунд, требуют от юзверя лишь запустить их единожды. После этого информация о соответствующем ПК отлетит прямиком к злоумышленнику, который в свою очередь сможет распорядиться полученным доступом по своему усмотрению.
Вот и образовалось, что называется свободная касса для всех любителей поживиться чужими данными. На форумах в дарке, эту тему форсят ещё с апреля и на сегодняшний день ситуация мало чем изменилась. Разве что ратников стало больше, чем раньше и продавать их стали за бабки. Причём функционал у них у всех плюс-минус одинаковый, а отличаются они лишь графической оболочкой.
В данном уроке, я продемонстрирую вам наиболее популярный ратник NjRAT. Он имеет самое большое количество скачиваний на гитхабе, поэтому очень надеюсь, что комментариев типа «ааа вирус нам скидываешь» не будет. Ведь я не заливаю данный ратник в телегу, а показываю, где его может скачать потенциальный злоумышленник и каким образом использовать для своих целей. Если интересно, устраивайтесь по удобней и приступим к созданию крыски. Погнали.
Шаг 1. Заходим на гитхаб и загружаем архив с NjRAT’ом.
Шаг 2. Распаковываем Zip File и внутри созданного каталога ищем папочку Moded, а в ней файл ратника.
Шаг 3. Запускаем его и прописываем порт, который нам нужно будет открыть на роутере. Надеюсь, что не нужно объяснять то, что он же, должен быть добавлен в исключения вашего брандмауэра. Хотя лично я, всегда вырубаю последний, дабы не выносить себе, и без того утомлённый мозг, этим вопросом. А по поводу проброса портов, у меня на канале есть чудеснейший видос про RDP. Там суть один в один, поэтому растягивать данный ролик по времени разжёвываю эту тему, я тут не буду. Кто не шарит, переходите и смотрите по ссылке в подсказке.
Шаг 4. Ну а мы жмём Start и попадаем в основное окно программы. Тут нас интересует только одна кнопка – «Builder». После нажатия на неё, запускается меню конфигурирования EXE’шки клиента, которая, по сути, и является вирусом. Давайте настроим всё по порядку. В пункте Hostзадаём наш белый IP’шник. Я миллион раз повторял в своих видео, что если вы хотите заниматься изучением администрирования или безопасности на постоянной основе, то обзавестись белым IPу провайдера нужно в обязательном порядке. Далее у нас порт, открываемый на роутере. Чуть ниже имя жертвы. Маскировка под определённый процесс. Обычно злоумышленники маскируют ратник под какую-нибудь системную службу, аля служба печати или диспетчер задач. Ну а справа у нас дополнительные параметры вируса. BSODпри попытке закрытия, копирование в автозагрузку, запись в реестре, распространение по USB в случае подключения носителя к ПК и прочие прелести. В более продвинутых ратниках ещё встречается функция изменения иконки, FUD-крипт и т.д. Ниже размер логов. Пусть будет 512. В принципе, всё. Кликаем «Build» для создания файла.
Шаг 5. Указываем имя и месторасположения. Я назову RAT, однако ясен-красен, что для распространения такое имя уж точно не годится и вы никогда не встретите подобную EXE’шку в чистом виде. По поводу максировки вирусов в меня на канале также есть пару занятных роликов. Ссылка на один из них непременно всплывёт в подсказке.
Шаг 6. Окей. Запускаем файл на компьютере жертвы.
Шаг 7. И вернувшись на свой ПК проверяем статус подключения. Комп подключился, а значит наш вирус уже в системе, и мы можем начинать кошмарить её по полной программе. Для этого достаточно вызвать контекстное меню функций и выбрать наиболее подходящий нам вариант.
Шаг 8. Давайте рассмотрим всё по порядку. Первый пункт Manager предоставляет нам доступ к файлам на дисках, открывает менеджер процессов, в котором мы можем выключить ту или иную задачу, а также посмотреть текущие соединения и поковыряться в регистре.
Шаг 9. Функция «Run File» позволяет запустить любой файл с диска или по внешней ссылке. Давайте я для примера продемонстрирую жертве пикчу носков.
Шаг 10. Указываем путь к картинке. И затем проверяем результат на клиенте.
Шаг 11. Всё отрабатывает. Теперь давайте затестим удалённый рабочий стол. Подключившись с его помощью можно не только смотреть за происходящим, но также, как и в любой популярной удалёнке управлять мышкой, клавой и делать скриншоты.
Шаг 12. Про вебку и микрофон думаю объяснять не нужно. Это, пожалуй, одни из самых полезных функций для злоумышленников, живущих за счёт продажи компромата в даркнете.
Шаг 13. Хотя, как по мне, большинству хацкеров ничуть не меньше зайдёт функция «Get Passwords». Она вытаскивает все сохранённые пассы из браузеров. Т.к. у меня это виртуалка, соответственно тут данный список девственен и чист.
Шаг 14. Далее по списку у нас старый добрый кейлоггер. Он перехватывает все нажатия клавиш пользователя. От набивки текста унылейшей курсовой, до пароля в vk.
Шаг 15. А затем сейвит их в отдельный RTF’овский файл, который складывается в папку пользователя, рядом с TXT’шкой пассвордов.
Шаг 16. Ну и самое весёлое – это, конечно же, чат с жертвой. Вы можете пообщаться с беднягой, пообещав удалить троянчик с компьютера за пару сотен пиастров.
Шаг 17. И в случае удачной сделки, даже сдержать своё слово, мочканув вредонос удалённо.
И вроде бы, с первого взгляда, всё круто, однако, не стоит забывать о подводных камнях. Во-первых, для того, чтобы всё завелось, на компьютере жертвы должен быть либо отключён автивирус. Либо ваш EXE-файл должен быть прокриптован. Во-вторых, на сегодняшний день, львиная доля членов нашего братства, жидится потратить сотку на белый IP и тем самым добавляет себе гемороя с пробросом портов.
Да, чисто теоретически можно попробовать воспользоваться популярным сторонним сервисом No-IP и с помощью технологии DynDNS забацать себе псевдо-белку. Также у некоторых именитых сетевых вендеров есть свои собственные, бесплатные сервисы для этой истории. Например, у тех же ASUS данная фича прекрасно работает из коробки. Однако, никакой дин вам не поможет, если ваш гавно-провайдер по экономическим соображениям экономит пул, и посадив клиентов за NAT, раздаёт, что называется «many to one».
В этом случае, вам поможет только белый IP или VPN. Либо, если у вас есть собственный Web-сайт, можно попробовать поизголяться с online-ратниками. Они хоть и менее функциональны, зато не требуют открытия портов. Следующий ролик у нас, как раз, будет по этой теме. Так что, если ты, друг мой, впервые забрёл на канал и ещё не оформил подписку, сейчас самое время. Клацай на колокол и в твоей ленте будут регулярно появляться годнейшие видосы по вирусологии, этичному хакингу и пентестингу.
С олдов жду лайки и конечно же комментарии по поводу того, какие ратники вы используете в своих обучающих целях. На сегодняшний день их развелось просто офигеть, как много, поэтому давайте посредством народного голосования выберем лучший. Хотя я почти на 100% уверен, что лидером окажется Putin RAT, но всё же давайте ради приличия немножко поиграем в иллюзию демократии. Напоследок, традиционно, желаю всем удачи, успеха и самое главное, безопасной работы.
Берегите себя и свои тачки. Не допускайте крыс в свою ОСь. Самый лучший способ для этого раз и навсегда перейти на Linux и больше никогда не вспоминать об EXE-файлах. Ну а с вами, как обычно, был Денчик. Искренне благодарю за просмотр. До новых встреч, камрады. Всем пока.
Иследование несложных crackme’s (часть 3)
Здравствуйте, Хабралюди.
Представляю вам третью часть из моего цикла статей о исследовании крякмисов. В этом топике мы поговорим с вами о ручной распаковке некоторых пакеров и о преодолении не сложных антиотладочных методов.
1. Ручная распаковка
Теория
Запакованная программа работает следующим образом:
Сначала запускается код распаковщика, который начинает расшифровывать запакованый програмный код. После окончания расшифровки делается прыжок на OEP программы и далее начинает выполняться уже распакованный програмный код.
Алгоритм распаковки будет таков:
1. Находим RVA OEP.
2. Дампим программу.
3. Восстанавливаем таблицу импорта.
4. Меняем точку входа на оригинальную.
Практика
В этой статье мы рассмотрим два пакера. Это UPX и ASPack. Распаковка других пакеров не сильно будет отличаться от распаковки этих двух.
Скачиваем самую свежую версию. Пакуем что — нибудь. Запускаем это под отладчиком.
Во время расшифровки запакованного кода пакер во всю использует стек. Естественно, чтобы запакованная программа работала правильно, пакеру необходимо сохранить начальное значение стека и потом, после завершения распаковки, восстановить его. Практически во всех упаковщиках, когда они восстанавливают стек перед переходом на OEP, считывается значение в стеке по адресу esp-4.
Таким образом, в Olly ставим бряк командой «hr esp-4». Затем запускаем программу и видим, что бряк сработал тут:
Далее трассируем программу до OEP(грубо говоря становимся на OEP). С помошью плагина Olly Dump дампим программу.
Теперь осталось только восстановить импорт.Запускаем нашу запакованную программу и ImpREC. В списке процессов ImpREC’a находим нашу программу. В поле RVA вводим RVA OEP( выше описано как его найти). Нажимаем AutoSearch. После появления сообщения о том, что скорее всего что — то найдено нажимаем Get Imports и, если в списке появились функции, то нажимаем Fix Dump и выбираем наш дамп. Вот и всё программа распакована.
ASPack
Тут всё аналогично, за исключением некоторого момента. После установки бряка мы попадаем сюда:
0046F416 75 08 JNZ SHORT Test_Com.0046F420
0046F418 B8 01000000 MOV EAX,1
0046F41D C2 0C00 RETN 0C
0046F420 68 C08F4500 PUSH Test_Com.00458FC0 //кладём в стек OEP
0046F425 C3 RETN // Косвенно переходим на OEP
В остальном процедура одинакова.
Крякмис на тему распаковки
Вот этот крякмис.
Распаковываем так как описано выше. Всё отлично распаковывается.(Для справки OEP = 00401000). После этого савим бряки на вызов функции GetDlgItemTextA, запускаем, вводим фейковый пасс, нажимаем на кнопку и попадаем сюда:
В EAX у нас находится длина введённого пароля. Командой SHL al,3 мы выполняем логический сдвиг значения AL влево на 3 и в идеале мы должны получить 78.Проведём процедуру обратную shl. Это shr 78,3 = 0F = 15 длина валидного пароля. Дальше я очень долго трассировал до некоторого момента и на пути мне встретилось несколько антиотладочных трюков:
Инструкция RDTSC возвращает в регистр EAX количество тактов с момента последнего сброса процессора. В коде выше мы видим два вызова этой инструкции а потом сравнение разницу их выводов с неким эталонным значением. Дело в том, что, когда программа выполняется без отладчика, разность тактов будет мала, а когда она под отладчиком то разность будет большая. Подобных моментов вам встретится много, просто пачте их или меняйте флаги. Когда вы до трассируете до следующего момента:
Обратите внимание на 0040127C. Тут совершается прыжок на несуществующий адрес, поэтому смело патчим переход на 00401281. Таких моментов будет несколько. Трассируете до такого кода:
004014F1 0FB613 MOVZX EDX,BYTE PTR DS:[EBX] ; наш пароль сейчас находится по адрессу расположенному в EBX, и сейчас мы заносим первый символ нашего пароля в EDX
004014F4 B9 08000000 MOV ECX,8
004014F9 AC LODS BYTE PTR DS:[ESI] ; подгружаем в EAX какой-то символ
004014FA 24 01 AND AL,1 ; and 1 с этим символом
004014FC 74 04 JE SHORT crackme2.00401502
004014FE D0E2 SHL DL,1
00401500 72 08 JB SHORT crackme2.0040150A
00401502 D0E2 SHL DL,1
00401504 0F82 BF020000 JB crackme2.004017C9 ; прыжок на плохую ветку программы
0040150A ^E2 ED LOOPD SHORT crackme2.004014F9
0040150C 43 INC EBX
0040150D 58 POP EAX
0040150E 48 DEC EAX
0040150F 0F84 9A020000 JE crackme2.004017AF
00401515 50 PUSH EAX
00401516 ^EB D9 JMP SHORT crackme2.004014F1
Над этим моментом я очень долго думал. Оказалось, что это процедура генерации пароля. То есть пароль хранится в программе не в открытом виде. AL на протяжении всей генерации принимает значения 1 или 0. Так вот, протрассировав всю процедуру генерации пароля и выписав все значения, я получил огромную строку из двоичных значений(для удобства перевёл в десятичную систему):
119 101 108 108 100 111 110 101 85 102 105 110 100 109 101
учитывая то, что каждая восьмёрка символов(в двойчной строке, а я перевёл в десятичную, поэтому тут это каждый символ обрамлённый пробелом), генерировалась после того, как мы положили в EDX определённый символ нашего введённого пароля, то можно утверждать что строка выше и есть валидный пароль. Перекодировав её получилось «welldoneUfindme».
2. Некоторые антиотладочные методы
Антиотладочных методов очень много, начиная с этой статьи будем разбирать их по очереди, от простых к сложным.
Итак, на crackmes.de как раз есть специальный крякмис, который называется AntiOlly. Качаем его, запускаем и видим следующее окошко:
Тут нам говорят, что ничего не обнаружено и мы справились. Теперь мы имеем представление о том, как выглядит «хорошее» сообщение. Загружаем крякмис в Olly и видим следующее:
Ошибка вызвана тем, что Olly, проанализировав заголовок нашего крякмиса, нашла в нём(заголовке) ошибки. Но это поправимо. Загружаем наш крякмис в PE edior и переходим во вкладку Optional header. Моё внимание привлекло «слишком большое» значение параметров NumberOfRVAandSize, Base of Code и Base of Data. Обычно NumberOfRVAandSize = 0x00000010, Base of Code =00001000, Base of Data = 00002000. Меняем эти параметры на «обычные» и запускаем крякмис под отладчиком. Теперь ругательного сообщения не видно(т.е. оно осталось, но никак не повлияет на анализ) и мы можем спокойно анализировать крякмис. Итак, это была первая антиотладочная уловка.
Запустив крякмис под отладкой мы видим «плохое» сообщение:
Проанализировав программу мы находим участок антиотладочного кода:
00401010 |. FFD7 CALL EDI // Вызываем функцию GetTickCount
00401012 |. 6A 00 PUSH 0
00401014 |. 68 34214000 PUSH AntiOlly.00402134
00401019 |. 8BF0 MOV ESI,EAX
0040101B |. FF15 DC204000 CALL DWORD PTR DS:[4020DC] //FindWindowA
00401021 |. 85C0 TEST EAX,EAX
00401023 |. 75 04 JNZ SHORT AntiOlly.00401029
00401025 |. 884424 0F MOV BYTE PTR SS:[ESP+F],AL
00401029 |> FF15 04204000 CALL DWORD PTR DS:[402004] //IsDebuggerPresent
Итак, первая вызывается функция GetTickCount. Эта функция возвращает время, которые прошло с момента старта системы в милисекундах. Дело в том что есть ещё один вызов этой функции. Далее, в последующем коде, замеряется разница между значениями полученными в результате выполнения этих функций. Это была вторая антиотладочная хитрость.
Далее следует вызов FindWindowA, которая ищет окно с заголовком OllyDbg. Ну и наконец вызов IsDebuggerPresent, которая просто проверяет отлаживается программа или нет. Если да то в Eax 1 если нет то 0.
вот проверки, которые проводит крякмис:
0040102F |. 85C0 TEST EAX,EAX // эта проверка после функции IsDebuggerPresent
00401031 |. 75 02 JNZ SHORT AntiOlly.00401035 // если дебаггер есть то прыгаем на 00401035
00401033 |. 32DB XOR BL,BL //если нет то обнуляем BL
00401035 |> FFD7 CALL EDI //Второй раз вызываем функцию GetTickCount
00401037 |. 2BF0 SUB ESI,EAX
00401039 |. 83FE 64 CMP ESI,64 // Сравниваем значения
0040103C |. 76 0D JBE SHORT AntiOlly.0040104B // Если ok то прыгаем на 0040104B
0040103E |. A1 44204000 MOV EAX,DWORD PTR DS:[402044]
00401043 |. 50 PUSH EAX
00401044 |. 68 3C214000 PUSH AntiOlly.0040213C
00401049 |. EB 3F JMP SHORT AntiOlly.0040108A // если не ok то идём по плохой ветке
0040104B |> 84DB TEST BL,BL
0040104D |. 74 14 JE SHORT AntiOlly.00401063 // Проверка результата функции IsDebuggerPresent
0040104F |. 8B15 44204000 MOV EDX,DWORD PTR DS:[402044]
00401055 |. A1 60204000 MOV EAX,DWORD PTR DS:[402060]
0040105A |. 52 PUSH EDX
0040105B |. 68 3C214000 PUSH AntiOlly.0040213C
00401060 |. 50 PUSH EAX
00401061 |. EB 2E JMP SHORT AntiOlly.00401091
00401063 |> 807C24 0F 00 CMP BYTE PTR SS:[ESP+F],0 //Проверка на то нашлось ли окно функцией FindWindow
00401068 |. 74 15 JE SHORT AntiOlly.0040107F
Думаю теперь понятно где патчить или редактировать регистры.
Большое спасибо вам за внимание.
Как удаленно взломать компьютер с помощью NJRAT
Инструмент удаленного администрирования (RAT) – это запрограммированный инструмент, который позволяет удаленному устройству управлять системой, как если бы у него был…
Инструмент удаленного администрирования (RAT) – это запрограммированный инструмент, который позволяет удаленному устройству управлять системой, как если бы у него был физический доступ к этой системе. В то время как совместное использование рабочего стола и удаленное администрирование имеют много законных применений, программное обеспечение «RAT» обычно связано с несанкционированной или злонамеренной деятельностью. NjRat – одна из лучших RAT. Это позволяет получить доступ к удаленному компьютеру и легко выполнять любые удаленные задачи. В этом уроке я расскажу вам, как удаленно взломать компьютер с помощью njRat.
КАК УДАЛЕННО ВЗЛОМАТЬ КОМПЬЮТЕР С NJRAT?
ТРЕБОВАНИЯ:
1) Загрузите njRat v0.8 как обновленную версию. Вы также можете работать с любой старой версией, если хотите.
2) Зайдите на сайт noip.com и зарегистрируйтесь. После регистрации вы увидите поле, как показано ниже, для ввода имени хоста. Введите любое имя, выберите любой tld из выпадающего меню и нажмите кнопку «Добавить хост».
3) Хорошо. Давайте откроем njRat и начнем строить сервер. Когда вы откроете окно, появится всплывающее окно, как показано на скриншоте ниже. Пожалуйста, введите порт, который хотите использовать. Я бы рекомендовал порт по умолчанию 1605. Введите 1605 и нажмите кнопку ОК.
4) После нажатия Ok нажмите кнопку Build. И заполните все поля, как я сделал на скриншоте. Убедитесь, что вы ввели собственное имя хоста в поле хоста. Введите порт 1605. В имени жертвы вы можете указать любое имя, какое захотите. Размер KeyLogs подходит для 20. Выбирает каталог, в котором вы хотите разместить свой сервер. И дайте ему имя exe. Вы также можете использовать значок, отметив значок. Но пока я не буду им пользоваться.
5) Когда вы нажмете кнопку «Создать», вам будет предложено ввести имя, указать любое имя и нажать «Сохранить». Начнется создание сервера. Вы увидите диалоговое окно успеха. Теперь сервер готов к распространению на другие компьютеры. Вы можете отправить его кому-нибудь через онлайн-файлы или любым физическим способом. Обязательно заархивируйте его перед копированием на любой физический носитель.
6) Теперь нам нужно открыть порты. Это немного сложная часть. Для этого я создал и разместил видеоурок.
7) Загрузите DUC и введите свое имя пользователя и пароль на noip.com.
8) Все готово … Теперь мы в порядке. Когда кто-то откроет созданный нами сервер на своей машине, он окажется у нас в руках и появится в окне njRat. Вы можете выполнять на компьютере жертвы любое действие, какое захотите.
Что такое upx в njrat
“That people seeking education should have the opportunity to find it.”
Nick Parlante
“Binary Trees”
Рецензент:
Dr.Golova/UINC.RU
Сорецензенты:
Four-F/HI-TECH, Quantum, Sten, Fixer
1. Требования повышаются!
2. Вместо введения
3. Как Windows работает с секциями PE-файла
4. А запакован ли файл?
5. Тонкости PE-формата
6. OEP и иже с ним
7. Дампер процессов
8. Практический пример: UPX
9. Практический пример: Aspack
10. SEH с точки зрения кракера
11. Немного об антиотладке – в преддверии telock
12. Практический пример: teLock
13. Список литературы
14. Выводы.
Требования повышаются!
Итак, мы продолжаем. Подразумевается, что вы ознакомились с первой частью статьи и теперь владеете минимумом теории. Однако мы еще более повышаем требования. Теперь, для успешного и полного понимания SEH (Structured Exception Handling) и некоторых приемов, тут продемонстрированных, вам придется иметь базовое представление о С++. Мы не будем особо далеко лезть в дебри родовых классов, виртуальных функций и т.п., но самые основы OOП, такие как наследование, вам необходимо (по крайней мере, желательно!) знать.
Кроме того, вам придется хлебнуть информации о недрах Windows для чего ОЧЕНЬ предлагается прочесть какую-нибудь хорошую книжку по системному программированию под Windows – например, Марка Руссиновича или Свена Шрайбера (список рекомендуемой литературы в конце статьи). Также по ходу дела мы постараемся давать линки на статьи (к сожалению, подавляющая масса литературы подобного характера на английском языке, на русском тоже что-то есть, но не слишком много).
Как вы уже, должно быть, догадались, все статьи этого цикла будут напирать на теорию. Мы предпочтем рассмотреть вопрос «почему», а не вопрос «как». Обязательно учтите, что здесь мы не рассматриваем 9x!
Практические примеры требуют воспроизводимости. Это означает, что вы должны иметь возможность воспроизвести примеры, показанные здесь, т.к. возможны недопонимания и все следует проверять практически. Во всех примерах упаковщиков используется один-единственный файл – calc.exe из поставки Windows 2000.
Вместо введения
Все трюки, продемонстрированные ниже, нельзя исполнить без файлов символов.
Если вам в силу тех или иных причин необходимо исследовать Windows, то сразу же возникает необходимость в настройке среды для работы. Очевидно, одного джентельменского набора из IDA/Soft-Ice/HIEW/IceExt и дампера процессов 3-кольца типа PE Tools тут уже недостаточно. Это шаг выше. Поэтому вам потребуется обзавестись символами отладки, которые можно сгрузить с сайта MS по этому адресу:
http://www.microsoft.com/whdc/ddk/debugging/symbolpkg.mspx установить и корректно настроить их. Обязательно учтите – символы должны ТОЧНО соответствовать вашей ОС и установленному SP. Для этого лучше использовать технологии MS. NuMega Symbol Retriever показал себя нестабильно работающей утилитой. Поэтому не поленитесь, если есть такая возможность, сгрузить файлы ручками, прогнать их через NMS-транслятор и проверить командной table, все ли у нас в порядке. Кстати, если по каким-то, одним разработчикам понятным причинам, Soft-Ice ну никак не желает откликаться на bpx, возможно, установка nms-символов на ntoskrnl сможет помочь.
Было бы неплохо также иметь какую-то утилиту, способную извлекать информацию из PDB-файла. Есть и такие – pdbdump – http://sourceforge.net/projects/pdbdump. Просто удивительно, сколько полезной информации можно извлечь из PDB. Нам с вами еще не раз предстоит в этом убедится на протяжении статьи. Наиболее полезный файл из всех – ntosrknlsym.pdb.
Установка не должна вызвать проблем. Поместите LiveKd в ту же директорию, программа все сделает сама.
Ну, поскольку, рисунок всегда нагляднее, вот:
рис 1 |
А если и рисунка мало, тогда смотрите на дамп из kd:
А теперь глянем в Шрайбера (w2k_def.h) касательно PEB. Оговоримся сразу – нас не интересует большинство полей, глянем только на два:
Теперь ReactOS (teb.h):
Видите, структуры различаются. Кто же прав? Ответ нам даст kd:
Указатели, в нашем случае, показывают на структуру LDR_DATA_TABLE_ENTRY:
Для чего мы заставляем вас проходить через это? Смотрите на код, он теперь должен иметь немного больше смысла:
Потрассируйте такой код и посмотрите в LordPe, что он вам покажет в поле SizeOfImage. Посмотрели? Угадайте, что будет, если дампер будет пробовать читать память, которой НЕТ? А теперь прогоните через PE Tools… Ну как результат?
Также необходимо предельно кратко ознакомиться со структурами режима ядра. Мы и здесь вполне осознаем, сколь много было сделано и описано Руссиновичем и Шрайбером, поэтому километровые листинги структур здесь даны не будут, мы рассмотрим лишь наиболее общие, а также наиболее ценные, в практическом плане, вопросы.
Мы уже упоминали, что содержимое, доступное через fs, различно для ring-0 и ring-3. Как вы теперь понимаете, в ring-3 fs:[0] показывает на структуру TEB. А что же мы видим, к примеру, в этом случае в кольце-0:
рис 3 |
Таким образом вы легко сможете преобразовать примеры выше в удобоваримый код, с которым можно сравнительно легко работать дальше:
Еще, вероятно, вас может смутить поле NT_TIB в составе KPCR. Как же так – ведь структура NT_TIB принадлежит кольцу-3! А вот и не совсем так. И кольцо-0 и кольцо-3 владеют каждый по NT_TIB – по одной на брата. Т.о. и в кольце-0 и в кольце-3 fs:[0] показывает на TIB, только в первом случае TIB входит в KPCR и ни о каком TEB речи нет, а вот во втором случае TIB входит в TEB. Вот вам и дамп из kd в доказательство:
Учитывайте эти нюансы и все будет ОК.
А теперь посмотрите, СКОЛЬКО информации нам дает pdbdump, написанный позже:
Ну, а если вы истинный, то есть, ленивый (это синонимы) программист, то уже должны думать про себя: «Неужели мне, каждый раз, когда я вижу ebx+134h, придется каждый раз делать такие комментарии в IDA (да, кстати, недокументированные функции полностью отсутствуют в этом дизассемблере!)?». Ну, разумеется, нет! Все уже сделано за вас. Озаботьтесь загрузить себе idc-скрипты, описывающие некоторые структуры нулевого кольца с http://www.alkor.ru/
00077500/kb/winnt.htm или, как всегда, с wasm.ru (в последнем случае картина более полная, т.к. Four-F создал замечательный здоровенный idc-скрипт).
Ничто также не мешает вам самим перевести .h файлы в idc-скрипты. Частично проблема решена Леонидом Лисовским (Leonid Lisovsky) в его скрипте h2enum (слить с сайта datarescue), однако более разумным кажется приспособить готовый лексический анализатор для этих целей, к примеру, lex, совместить его с перловским скриптом, который будет подставлять нужные функции IDA и все. Почитать о lex и yacc можно, например, тут: http://www.codeproject.com/cpp/introlexyacc.asp. Хм. Добровольцы?
Также обязательно ознакомьтесь с набором команд IceExt (скачать с http://stenri.pisem.net либо с wasm.ru) – уникальный плагин для Soft-Ice, способный не только выполнять анти-антиотладку, но, к примеру, могущий также показать список PTE, содержание теневой SDT и т.п.
Мы довольно прилично осознаем, что от такого введения недолго и в обморок упасть. Поэтому не торопитесь. Вы, должно быть, уже сообразили, что эту статью нельзя прочесть с наскока – это не бульварное чтиво. В помощь при разборе ассемблерщики пусть возьмут себе уникальный KmdKit by Four-F и внимательно разберутся с файлом w2kundoc.inc. Программисты на С пусть возьмут основательно подправленный Volodya файл Шрайбера w2k_def.h. Оба доступны с wasm.
Как Windows работает с секциями PE-файла
В первой части мы представили и должным образом дополнили работу Rustell Osterlund о работе ntdll.dll и тех проверках на валидность PE-файла, которые она выполняет. Теперь пришло время двинуться дальше и рассмотреть, какие ограничения на формат накладывает само ядро Windows. Это означает, что придется идти глубоко – в ntoskrnl.exe. В принципе, новички могут пропустить эту главу, так как она способна запросто привести в ужас кого угодно, кроме самих создателей Windows. Единственное что – в самом ее конце мы описываем практическое использование полученных знаний и реализацию оных в PE Tools.
Продвинутые читатели наверняка знают некоторые подробности об объектах Windows, поэтому смягчать выражения мы особо не будем. Единственный объект, который нас интересует – это объект «секция». Объект полностью недокументирован. Лишь в главе 7 книги Руссиновича есть легкое упоминание о такой вещи и симпатичный рисуночек.
Подробнее – Петр Косых aka gloomy. Материалы можно слить с wasm.ru. Кода ReactOS, довольно часто упоминаемые нами в этой статье, по данному поводу можно просто выбросить – там чушь. NtCreateSection является лишь тонкой прослойкой вокруг MmCreateSection, которая и выполняет всю работу по заполнению объекта «секция», работе с PTE, а, точнее, с гиперпространством, проверке валидности, переводу флагов PE-секций в атрибуты структур SUBSECTION (см. ниже) через хитрые массивы ядра и т.п. Внутри MmCreateSection могут вызываться три функции:
Сначала вызывается MiCreatePagingFileMap. Далее, Windows на основании флагов из структуры CONTROL_AREA (см. рисунок ниже) решает как ей быть дальше – либо работать с файлом как с данными через MiCreateDataFileMap, либо как с исполняемым файлом через MiCreateImageFileMap, принимающей указатель на FILE_OBJECT. Весь процесс этот достаточно сложный, но, быть может, этот рисунок поможет немного разобраться (маленько улучшенная копия оного из книги Соломона-Руссиновича):
рис 4 |
Все семейство Mi*-функций, активно используемых в Mm-функциях, невероятно интересно. Однако целиком мы его рассматривать не будем. Внутри MiCreateImageFileMap заголовок PE-файла (ТОЛЬКО заголовок) безусловно отображается на гиперпространство по адресу 0x0С050000 (mov eax, 0C0500000h) функцией MiMapImageHeaderInHyperSpace (в функцию жестко зашито значение для отображения). После этого отображенный заголовок принимаются активно проверять – функция MiVerifyImageHeader. А вот эта функция уже безусловно интерестна для нас с вами:
В принципе, этот псевдокод особых проблем вызвать не должен. Особое внимание обратите на проверку выравнивания файла и секций.
Если NtCreateSection вернула что-либо отличное от нуля – файл валидным не является – это невероятно надежный источник проверки валидности файла! Если неуверенно себя чувствуете с нативными приложениями (т.е. программами, использующими ntdll.dll напрямую с помощью статической линковки, или динамически, через GetProcAddress), то вот замечательный линк: http://www.osr.com/ntinsider/1996/native.htm
А запакован ли файл?
В виду того, что эта статья позиционируется для взломщика с некоторым опытом, кажется немного наивным поднимать здесь такой вопрос. И в самом деле, для того, чтобы определить, а запакован ли файл, нужен только опыт. Дизассемблируется мусор, редакторы ресурсов отказываются работать и т.д., и т.п. Словом, все симптомы налицо и не о чем тут говорить. Это так. Возражений нет. Однако в рамках этой главы нам бы хотелось показать довольно оригинальный прием программной детекции упакованного файла. Для этого определим понятие «энтропия».
Алгоритм может выглядеть так:
Впрочем, кажется, мы увлеклись. Итак, определение того, что файл упакован, не займет много времени. Теперь зададим вопрос: «А ЧЕМ упакован файл?». Ответ на подобный вопрос нужен не одним нам с вами. Мировым стандартом (не побоимся этой фразы) считается составление сигнатуры и поиска этой сигнатуры в файле. С точки зрения алгоритмики имеем поиск подстроки в строке.
Приготовление сигнатуры – вещь не сложная и во многом должна определяться квалификацией того человека, который эту сигнатуру составляет. В Pe Tools для этой цели разработана утилита SignMan, следующая версия которой будет основана на очень простом принципе: побайтовом сравнении файлов, запакованных ОДНИМ И ТЕМ ЖЕ упаковщиком с разными опциями:
Сигнатуры хранятся в текстовой форме в файле Sign.txt. Практика показала, что это решение удачно. У многих людей, заинтересованных в судьбе утилиты, нашлось свободное время, чтобы отправить баг-репорт с правками сигнатур и, можно заявить, что файл, на сегодняшний день является достаточно тщательно проверенным не только авторами утилиты, но и многочисленными пользователями. Хотя, разумеется, это не означает, что багов там нет.
Словом, примем сигнатуру для поиска достаточно надежным средством. Осталось определится с тем, как ее искать. Мы трактуем файл как последовательность байт. PE Sniffer, по версию 1.5.х. включительно, является пока еще утилитой-ребенком и от него, ни в коем случае, пока нельзя ожидать многого. Поэтому утилита должна быть переписана с учетом быстрого и в достаточной степени надежного поиска. Итак, поиск может быть разделен на две категории:
1) Точный поиск подстроки в строке –
2) Неточный поиск подстроки в строке –
Поиск Бойера-Мура достаточно быстр за счет построения таблицы смещений и делает меньше сравнений, чем тривиальное strcmp. Однако он подходит лишь для точного поиска образца (или, в улучшенных вариантах, допускает лишь минимальные отклонения, согласно простейшим регулярным выражениям). Здесь же мы ни в коей мере не можем быть уверены, что подстрока (сигнатура) не будет самым злостным образом искажена. Давайте рассмотрим пару примеров и на их основе попытаемся сформулировать ряд правил для написания движка.
Пример: libc.lib – стандартная библиотека языка С. Известно, что код программы начинается не с main, а с *mainCRTStartup (одной из четырех). Поэтому ничто не препятствует поменять код процедуры с такого, например:
Выражено коряво, но смысл вы схватить должны. Это полностью исказит сигнатуру и мы более не сможем сказать, что же это за компилятор. Причем и противопоставить-то такому приему практически нечего. К счастью, такое практически невозможно в общем случае проделать с исполняемым файлом, поэтому рассмотренный код относится, скорее, к патологии.
Реально же имеем следующее:
1) Для каждого пакера существует устойчивая кодовая последовательность именуемая в дальнейшем сигнатурой для которой действуют следующие правила (здесь под элементом сигнатуры подразумевается байт)
a) Элементы сигнатуры не могут меняться местами
b) Элементы сигнатуры не могут быть заменены на другие
2) Между отдельными элементами может присутствовать «шумовой» код (если мы для сигнатуры выберем 1, 5, 10 байты сгенерированные пакером, для уменьшения количества ложных срабатываний, необходимо учесть минимальное расстояние на котором могут встретиться эти элементы сигнатуры друг от друга), а между некоторыми такой код появиться не может (двух и более байтные команды).
Что-то наподобие такого и будет реализовано в новой, уже не совсем детской версии PE Sniffer. Хотя и здесь решение для общего случая, скорее всего, НЕ существует. Уж слишком злопакостно можно исказить сигнатуру при желании, и ни CRC, ни xor-сумма строки, ни побайтовое сравнение по хитрым правилам не помогут. Скажем, пункты 1.a/1.b явно дискуссионны, чего только стоят т.н. stolen bytes в Asprotect. Поэтому если имеете собственное суждение – не стесняйтесь его высказать.
В заключение было бы интерестно рассмотреть – а как же действуют профессиональные антивирусы? Ведь как-то же они предполагают наличие вируса, хотя, зачастую и неверно, давая ложные срабатывания или просто не узнавая его. Однако мир антивирусов практически закрыт от конечного пользователя. И кто-то еще ругает Windows за закрытость кода?
Как правило, в открытую печать не попадает сколь-нибудь ценной технической информации. Что тут говорить. Тем не менее, мы предложим пару линков:
Тонкости PE-формата
Вы решили потратить деньги на приобретение пакера. ОК, выбор ваш. Положим, вы не уверены, что способны написать хорошую защиту, просто нет времени или еще что-то. Тогда проверьте пакер! Хороший криптор должен не только перезагружать Windows если кто-то подошел к монитору, он должен и корректно обрабатывать многие тонкости и сложности PE-формата.
Одним из достаточно простых, но достаточно забавных тестов на качество написанного пакера может быть следующий, почти гениальный, клочок кода:
Основной смысл такого упражнения – в создании секции .tls в результирующем PE-файле (заметьте, мы говорим о статическом tls – с tls можно работать и динамически – подробнее – Джеффери Рихтер). .tls-секция (если она существует) обрабатывается лоадером при загрузке – вызываются callback-функции и т.п. Все это достаточно подробно описано Питреком в
и облегчать жизнь писателям пакеров у нас желания нет. Однако факт остается фактом – многие коммерческие упаковщики не учитывают инициализацию tls-цепочек лоадером, в результате чего запакованный файл падает. Среди таковых и Aspack 2.12, который такой файл даже обработать не может! А люди еще за это и деньги платят.
Более того, можно сделать еще веселее! Положим, мы имеем дело с dll (tls-цепочки используются, в основном, именно в dll) – как прикажете обрабатывать секцию tls, которая подвержена перемещению, т.е. появляются fixup-элементы? В случае exe-файла аналогичного результата можно добиться опцией MS-линкера /FIXED:NO. Так это вообще фантастика! UPX гарантировано обрабатывает такие вещи, а вот некоторые остальные, не будем показывать пальцами.
Вот такими и является большинство упаковщиков. С миру по нитке накопировано антиотладочных приемов (зачастую, беззастенчиво спертых из кода вирусов или толковых статей кракеров), все это достаточно неумело отлажено, кое-как обрабатывается PE-файл, при этом совершенно не учитываются многие нюансы и тонкости формата и за это просят деньги, утверждая, что пакер работает превосходно и надежно спасает от недалеких кракеров.
OEP и иже с ним
Для этой главы неплохо было бы выбрать самый простой из всех возможных упаковщик, на котором и проиллюстрировать некоторые закономерности работы. Такой, к счастью, есть. Называется PE Deminisher и доступен для закачки с wasm.ru.
Итак, пакуем наш старый добрый calc.exe и что мы имеем:
Очевидно, три секции являются нормальными, четвертая принадлежит упаковщику. Так же очевидно, что, в этом случае, остальные секции (за исключением .rsrc) являются сжатыми по какому-либо алгоритму (в данном случае это apLib, но нам это не важно). Что находится в четвертой секции и почему она расположена именно четвертой? Вот слегка обрезанный отчет HIEW о данном файле:
Использование директории отладки является старым добрым антиотладочным приемом, мы это уже описывали и повторяться неинтерестно. Ресуры тоже уже мало кого удивляют. Любопытнее выглядит изменение RVA директории импорта в секцию пакера. Если глянуть на заголовок (Optional Header), то можно видеть, что и точка входа переориентирована в новую секцию, и количество секций, соответственно, увеличено. Разумеется, изменилось поле SizeOfImage, иначе файл валидным не будет. Кому интерестно видеть все мелочи – воспользуйтесь функцией Compare из Pe Tools. Нам же интерестнее ответить на вопрос: так почему же секция идет четвертой. Если чуточку подумать над проблемкой, то ответ ясен – так легче. Положим, можно поставить и третьей, если не лень пересчитывать ресурсы как директорию и как секцию. А вот первой – ни-ни. Так как слишком уж это дело будет хлопотное. Но если кому-то не лень, что тогда? Смотрите – теоретически невозможно поставить секцию пакера первой – это потребует коррекции ссылок в секции кода и коррекции ссылок между секциями кода и данных и т.п., да и не только. Откуда получить такую информацию? Если файл содержит IMAGE_DIRECTORY_ENTRY_BASERELOC, то тогда, используя информацию оттуда, такое дело возможно, однако методика для общего случая работать не будет.
Работать с dll примерно так же просто. Достаточно давно разработана методика Break & Enter. Смысл ее состоит во влеплении опкода СС (о самом опкоде см. ниже) прямо в EP программы. Известно, что Soft-Ice Symbol Loader часто просто проскакивает мимо EP. Поэтому LordPE и PE Tools лепят СС-байт прямо в EP, предварительно запоминая оригинальный. Все, что остается пользователю – ввести bpint 3 и восстановить старый байт после всплытия Soft-Ice. Скоро будет написан плагин под PE Tools в виде лоадера dll, т.к. dll, с нашей с вами точки зрения, мало чем отличается от exe.
Что до директории импорта – тоже достаточно просто понять, что оригинальная директория импорта остается нетронутой лоадером (он ее просто не видит). Вместо этого пакер сам, после расшифровки содержимого файла, находит эту директорию и в цикле, перед передачей управления на OEP, с помощью GetProcAddress, наполняет ее валидными для данной системы адресами и производит перерасчет RVA на VA (см практический пример с Aspack). Обязательно следует заметить, что и тут прогресс ушел далеко вперед. Современные крипторы уже не используют GetProcAddress. Уж слишком легко нам поставить на нее брейкпоинт и разобраться в логике пакера (см. практические примеры).
* Под частью экзешника подразумевается та часть, которая подлежит сжатию/разжатию. В общем, кроме самого UPX’а никто больше не умеет определять точные границы этой части.
Сигнатура UPX для старых NE, линуксовых ELF и т.д. представлена иначе, но нам интересен только формат PE32.
Uncover UPX самостоятельно восстанавливает сигнатуру после UPX-SCRAMBLER, так как данный скрамблер уничтожает сигнатуру частично, но что делать если сигнатура утеряна полностью, как в случае с HidePX? Тогда Uncover UPX заполнит её значениями по умолчанию и нам придётся немного ему помочь, если в том возникнет нужда.
Поле magic, понятное дело, менять не стоит. Поле version обычно оставляется как есть (0C или 0D). Format оставьте со значением 09. Method в 99% случаев равен 02. В level можете поместить любое отличное от нуля значение, так-как распаковщик не обращает внимания на уровень сжатия. Тоже самое относится к полю u_file_size.
Если отключить обе проверки (до и после распаковки), про адлеры можно будет забыть. Следующий код заодно отключает проверку c_len и u_len, т.е. гонимся за четырьмя зайцами и успешно их ловим:
Правда, даже если вы сможете перекомпилировать этот код, вы получите версию UPX без поддержки NRV. Было бы куда лучше внести эти исправления в последнюю версию UPX (1.90 на данный момент), которая поддерживает сразу UCL и NRV. Где наш дизассемблер? Стоп, перед устранением этого бага в UPX, не забудьте его распаковать (он сам собой и запакован)
Распакованный UPX.EXE (около 327 Кб) грузим в HIEW и задаём поиск 56578B7C241484DB8BF1. Кстати, данная последовательность применительна и к предыдущей версии UPX. Узнаёте следующий код?
Меняем 74 на EB и первая проверка адлеров решена! Чуть дальше вы встретите вторую проверку контрольной суммы:
Функции вместо new_len нужно подсунуть адрес ph.u_len. Это можно организовать заменив 8D4C241C на 8D4C261C. Сразу за этим вызовом видим код примерно следующего содержания:
Исправьте второй переход с условного на безусловный. Всё, теперь нам море по колено! Можете вписывать в поля u_adler и c_adler всё, что хотите (хоть FFFFFFFF, чтобы не путаться с little endian) Для полного отключения проверки валидности файла можете ещё удалить сравнение имени первой секции. Это сравнение очень просто найти в. Нет уж, ищите сами! В противном случае, будете и дальше править имена секций в PE Editor.
Что до u_len и c_len, то проверку валидности данных полей вы уже отключили но, в отличии от адлеров, выбор значений u_len и c_len налагает некоторую ответственность. Дело в том, что UPX резервирует два буфера в памяти: один размером с u_len для временного хранения распакованного файла, другой размером с c_len для чтения запакованного содержимого файла. Понятно, что если задать слишком маленькое значение для u_len, то распакованный файл просто не поместится в буфер. С другой стороны, слишком большое значение заставит UPX потреблять больше динамической памяти. Для u_len вполне подойдёт значение 000FFFFF (FFFF0F00 в little endian) для большинства упакованных экзешников.
В заключение стоит упомянуть поле filter. В нём обычно хранится значение 260X, где X может быть 0, реже – 1, а еще реже – что-нибудь другое, например, 6, для старых версий UPX. Данное поле заслуживает особого внимания, так как неправильное значение фильтра приводит к неправильной распаковке экзешника, т.е. файл распаковывается, но не запускается! В общем, зря скрамблеры пренебрегают этой записью. Немного подправив значение фильтра можно защитить файл куда эффективнее, хотя от дамперов это всё равно не поможет, но всё-таки.
Теперь давайте проведем два практических примера. Наконец-то!
Итак, UPX-SCRAMBLER. Скачиваем с wasm специальные upx by Quantum/Volodya. Результат:
Теперь HidePX.
Поможем нашему UPX. Загружаем PE Tools, запускаем Quantum’овский плагин. Жмем одну-единственную кнопочку – Fix. Повтор:
На тот маловероятный случай, что что-то пойдет не так. Хм, а зачем мы вам столько писали, а?
В самое заключение главы. Помните, в самом начале мы говорили, что здесь не будет ни строчки дизассемблированного листинга? Так вот, мы соврали. Имеет смысл разобрать один скользкий момент с HIEW. Передача управления на OEP в UPX отображается HIEW (по 6.85 включительно) так:
Практический пример: Aspack
Что делает новичок, увидев программу, запакованную Aspack? Ну, берется Soft-Ice, берется дампер процессов и, обязательно, Imprec. Потом над всем этим инструментарием начинают интенсивно издеваться – зацикливать на OEP, дампить целиком, посекционно или еще как, немедленно запускать Imprec и вставлять полученный дамп директории импорта в файл. Ну что ж. Можно и так. Работает. Только давайте усложним задание. Положим, дампер процессов не имеет никакого движка по перестройке импорта, а Imprec и иже с ним у нас просто нет. Что тогда?
В связи с тем, что есть такие великолепные материалы, мы не станем рассматривать код ASPack подробно. Для начала учтите – что это не криптор, это самый обычный упаковщик. Здесь нет ни антиотладки, ни сколь-нибудь сложных приемов противостояния дизассемблерам. Лишь в самом начале есть нечто, робко напоминающее полиморфный код:
Итак, ясно, что ebp показывает на начало кода/данных. В связи с этим весь остальной код теперь достаточно четок и ясен. Полагаем, понять, что делает этот код, после фокуса с ebp, уже предельно просто:
уже тоже сбить не должен. Куда передаст управление регистровый jmp, вы уже можете найти и без отладчика.
Теперь давайте посмотрим, как правильно надо сбрасывать дамп из программ, запакованных Aspack. Здесь предельно четко нужно понимать, что нам нужен файл ДО обработки его самим упаковщиков, т.е. СРАЗУ ЖЕ после разжатия. Такой момент существует не для всех упаковщиков, однако для Aspack он проявляется предельно наглядно.
Итак, Aspack выполняет разжимание секций по LZ+Хаффман-подобному алгоритму с использованием VirualAlloc для отведения памяти под временный буфер и VirtualFree для высвобождения этого буфера. В буфер вбрасывается разжатое содержимое, которое копируется двойными словами (хорошая оптимизация!) (и докопируется побайтно при необходимости) на то место, что принадлежит ему по праву – на оригинальный RVA секции. После полного разжатия и копирования Aspack принимается обрабатывать директорию импорта (см. ниже), директорию перемещаемых элементов, вычисляет и предает управление на OEP. Наша задача – сбросить дамп ДО обработки импорта, fixup-элементов и т.п. Сделаем мы это как раз здесь:
Адрес 0х010191A9 здесь как раз и является «заветным». Зацикливая программу на этом адресе мы можем быть уверены, что дамп является полностью рабочим и не подвергнут ни обработке импорта, ни чему-либо еще. Ввести программу в бесконечный цикл можно по-разному, к примеру, введите ассемблерную команду jmp eip, воспользуйтесь командой !dump в IceExt, выберите SuspendThread, словом, вам и карты в руки. Мы же здесь, разумеется, объясним как использовать PE Tools.
Итак, после того как jnz не сработает – все секции распакованы и можно приступать. Полный дамп файла с опциями Full Dump: fix header, Full Dump: rebuild image. DumpFix, ValidatePE, RebuildPE. В дампе ручками в PE Editor: Optional Header > пересчитываем: SizeOfImage, SizeOfHeaders, Checksum (при помощи кнопки «?»). Уменьшаем размер. Делаем RebuildPE, с опциями: DumpFix, ValidatePE, RebuildPE.
Файл ПОЧТИ валиден. Осталась мелочь – параметры директории импорта и правка EP. Нам более не нужен код пакера, поэтому EP должна быть переориентирована назад – на OEP и директория импорта должна быть поправлена. Для этого залезем в алгоритм Aspack еще раз. Вспоминаем первую часть и действие функции LdrpSnapIAT, что в ntdll.dll. Все пакеры должны эмулировать ее действие, заключающееся (не только) в превращении RVA полей директории импорта в VA – взгляните на код:
Итак, RVA директории импорта ясен, осталось узнать размер. Делаем так:
Параметры директории должны выглядеть так: RVA – 0x12A40, Size – 0xAB0. Теперь OEP:
Точка останова сработает поблизости от OEP – на popad – при вытаскивании регистров назад. Вот здесь:
Заметим напоследок, что трюк с bpm esp-4 сейчас работает не так уж и часто. Многие крипторы специально осложняют нам жизнь. В некоторых случаях это можно обойти, к примеру, поставив точку останова еще ниже, но с некоторыми крипторами не помогает и это. К примеру, вполне возможно поставить в блок try/catch пример на исчерпание стека в бесконечном цикле, а обработчик исключения должен это дело разобрать. Для успешного понимания таких защит необходимо четко разбираться в SEН – структурных исключениях, что и рассматривается в следующей главе.
SEH с точки зрения кракера
рис 5 |
рис 6 |
Можно с полным на то основанием считать использование заведомо сбойных участков кода в SEH-кадрах самым настоящим антиотладочным приемом, который одинаково хорошо работает и как против ring-0 отладчика, и как против ring-3 отладчика. Автор упаковщика встраивает код, который заведомо даст сбой, в SEH-кадр. Примерно так (код из статьи Питрека очень нагляден):
Поле UTEB показывает адрес памяти, по которому в ring-3 расположен TIB, а поле Except Frame показывает адрес ПОСЛЕДНЕГО узла в списке SEH (к SEH можно также подступится не только через FS:[0], но и через TIB (FS:[18]) в которой, помимо указателя на хвост списка SEH, хранится линейный адрес самой структуры TIB, который можно использовать для доступа к ее полям). Потрассируйте программу, использующую SEH, и обратите внимание на изменение адреса в этом поле.
Сам обработчик, в нашем случае может просто увеличить EIP и вернуть управление назад, так, чтобы перескочить F1. И вот теперь мы, собственно, добрались до кульминационного момента. Когда Windows вызывает обработчик исключения, ему (обработчику) становится доступной структура CONTEXT, дающая возможность менять все общедоступные регистры процессора, включая DR0-DR7.
Вопрос: когда RtlDispatchException возвратит управление, а когда нет? Ответ заключается в самом обработчике прерывания. Если обработчик имеет вид:
то, очевидно, управление будет передано назад. Если же имеем обработчик вида:
1) запись от RtlpExecuteHandlerForException, которая тоже использует try/catch,
2) запись пользовательского обработчика. Т.е. список будет выглядеть так:
Итак, вывод. Если обработчик намеренно меняет DR-регистры, то управление должно вернуться в ntdll.dll и быть передано функции NtContinue. Теперь мы вплотную подошли к этой любопытной функции. Из функции, реально, документирован только прототип. В кодах ReactOS по поводу NtContinue наблюдается полное отсутствие всякого присутствия. Следующий псевдокод получен путем дизассемблирования и анализа, как всегда:
Что это означает для нас с вами? Смотрите, у пакера нет выбора. Если пакеру необходимо изменить DR-регистр, он ДОЛЖЕН передать управление в ядро, где программа кольца-3 не в силах проконтролировать установку точек останова, и момент передачи управления на код, работающий с DR-регистрами, может быть нами подправлен как нам заблагорассудится!
Очевидно, что если переделать в абсолютный jmp один условный переход, то DR-регистры останутся неискаженными, следовательно, мы свободно сможем пользоваться нашей любимой командой bpm. И все – наполнение мусором DR-регистров (как это любит делать asprotect) нам теперь до лампочки. Неужели все так просто? К сожалению, нет. Да, действительно, нет никаких принципиальных сложностей в изменении условных переходов (скажем, можно привинтить в IceExt команду, которая будет ставить подобную защиту при необходимости и снимать ее, когда отпадет надобность), но и авторы упаковщиков даже не даром свой хлеб едят. Что вы скажете о защите, которая сама ставит точки останова, используя DR-регистры, т.е. трассирует сама себя? Т.е., если DR-содержимое очищено или оставлено без изменений с помощью трюка с NtContinue, точка останова не сработает и программа узнает, что дело плохо. Вероятно, в общем случае, разработать решение этой проблемы не удастся. Подумайте, возможно, именно вы сумеете разобраться как можно проэмулировать этот трюк, если это вообще реализуемо.
Спешим «порадовать» еще одной «приятной» новостью – фирма MS в Windows XP ввела так называемые векторные исключения – VEH, имеющие приоритет над SЕH, т.е., выполняющиеся перед ними. Умница Питрек и тут не подкачал – читайте его статью.
Пока нам не доводилось встречать программы, которые бы игрались с этим приемом, однако, когда придет и их время, полагаем, у вас теперь найдется, что им сказать.
Немного об антиотладке – в преддверии telock
Практически в любой статье по снятию упаковщика рассказано о трюке применения int 1 в SEH-кадре и том, что это помогает обнаружить Soft-Ice. Однако ни слова не сказано о том, ПОЧЕМУ И КАК это происходит. Давайте попробуем разобраться. Хотелось бы сразу сказать, что лезть придется глубоко – в ядро Windows. Итак, поехали!
Очевидно, чтобы избежать антиотладочных фокусов, нужно понимать, что такое отладка и какие средства в нашем распоряжении есть. А это требует чертовски хорошего понимания защищенного режима и обработки прерываний защищенного режима. Значит – интеловские талмуды!
Итак, вполне понятно, что int 1 в качестве антиотладки можно использовать только в SEH-кадрах, иначе не выживет сама программа. Стандартно можно поступить так:
Более изощренный код, в котором адрес обработчика исключения уже не столь очевиден, может выглядеть так:
А мы, тем временем, продолжим разбор обработчика с int 1. Очень внимательно рассмотрите этот код:
В системе БЕЗ Soft-Ice int 1 имеет DPL = 0 (если c IDT чувствуете себя неуверенно – хорошая ссылка: http://www.acm.uiuc.edu/sigops/roll_your_own/i386/idt.html):
Быстренько вспоминаем, что происходит, когда задача с меньшим DPL пытается обратится к сегменту с большим DPL? Правильно – нарушение защиты #GP! В системе БЕЗ Soft-Ice int 1 имеет DPL = 0 и, в случае намеренного (хм, или ненамеренного) сбоя в программе кольца-3 (DPL = 3), будет вызван обработчик KiTrap0D, выполняющий следующие действия:
в конечном результате которых мы имеем код 0xC0000005(!) в ExceptionRecord->ExceptionCode! Еще раз – произошло int 1, а имеем – access violation!
Что же произойдет в системе, где Soft-Ice установлен?
Ну а далее, можно либо проверять флаг, либо переориентировать EIP через структуру CONTEXT.
Нет нужды верить на слово. Все элементарно можно проверить. Вот программа:
Защитится от этого можно элементарно – пропатчив IDT или поставив IceExt, который восстановит DPL int 1 в прежнее состояние.
Что до int 3 – то само по себе использование int 3 в SEH-кадрах не есть антиотладка – статус будет всегда одним и тем же – STATUS_BREAKPOINT. Специфичной антиотладкой int 3 становится тогда, когда к нему добавляются переданные в ax, dx и т.п. параметры. Например, известный трюк с командой HBOOT. Если в Soft-Ice выполнить данную команду, произойдет мнгновенная перезагрузка. Того же эффекта можно достичь через backdoor интерфейс, что, к примеру, описано у Hex’a (проект xtin.org). Если помните, мы говорили, что int 3 обязательно должен иметь опкод СС и никакого другого. Windows явно рассчитывает на это. Кусок кода из KiTrap03 тому примером:
Кстати, Soft-Ice тоже лжет. Выполните команду idt и вы увидите следующее:
т.е., якобы, ничего не изменилось. В действительности же имеем:
Практический пример: tElock
Эта цель отнюдь не является легкой. В качестве антиотладки очень активно используются SEH-кадры, набитые всякой гадостью. Однако, используемые приемы однотипны. Так, вся защита программы построена на одном веселом принципе. Смотрите:
Что мы можем этому противопоставить? Очевидно в ядро, наш старый добрый знакомый, нам заходить ни к чему. Поэтому имеет смысл переориентировать EIP на безопасный клочок внутри SEH-кадра и продолжать двигаться дальше. Но это только в теории. На практике, Soft-Ice очень не любит такие конструкции, поэтому проходит через SEH-фреймы пешком очень не рекомендуется. Поскольку строение и принципы работы SEH теперь понятны, постарайтесь всегда узнавать адрес обработчика ДО вхождения в кадр и сразу переориентируйте EIP на него. Только не стоит забывать о такой вещи как балансировка стека и значения регистров. Иначе очень быстро допереориентируетесь.
Если вы все еще с нами – продолжаем! Итак, обработчик int 3 записывает в DR значения ВНУТРИ ТОГО ЖЕ САМОГО кадра SEH. Управление ОПЯТЬ передается в этот же самый злополучный кадр! Четыре раза должны отработать DR-регистры. После четвертого раза происходит исключение типа деление на ноль. И тут-то получает управление ветка, которую можно назвать «на дорожку». Правится EIP, во все DR-регистры прописываются нули, ставятся маски на управляющие DR6-7 и управление идет дальше – на метку work_with_PE. И это все! Больше работы с DR-регистрами в коде telock нет!
Немножко по поводу DR-регистров и Soft-Ice, который действительно является чудом. Dr-регистры явно не отображаются и принудительно могут быть выведены командой CPU. Записать в DR-регистры что-нибудь можно лишь опосредовано – через bpm с явным указанием одного из четырех (DR0-DR3). Кроме того, умничка Soft-Ice умеет отображать модельно-специфичные регистры – MSR. Для этого есть одноименная команда и более усовершенствованный вывод сообщений при срабатывании bpm:
Читаем в интеловских талмудах – том 3 глава 15 “Debugging and performance monitoring”: “The LastBranchToIP and LastBranchFromIP MSRs are 32-bit registers for recording the instruction pointers for the last branch, interrupt, or exception that the processor took prior to a debug exception being generated”.
Так это же вообще шикарно! LastBranchFromIp – это «откуда», LastBranchToIp – это у нас «куда». Как это можно использовать? Ну. Встретите защиту вида:
и все сразу станет ясно.
Ну а что дальше? Дальше – еще веселее. Безумные SEH-кадры с инсталляцией головы списка наподобие:
и int 68h внутри. Однако, смеем надеяться, более проблем они вам не доставят! Да, они головоломны, да, код перенасыщен мусором, да, обилие зашифрованных сегментов – но дорогу осилит идущий! Самое главное – чисто пройти головоломный трюк с DR. Все. После него вы спокойно можете ставить bpm. И не слушайте всяких рассказов, что, мол, bpm в telock ставить нельзя. Можно!
Смело ставьте bpm GetProcAddress x (telock использует его напрямую, без всяких сканирований директории экспорта):
Собственно, не имеет смысла описывать этот цикл. Важно отметить – нет нужды во многочисленных плагинах под ImpRec, возьмите директорию отсюда. Остерегайтесь ставить bpx на API напрямую, используйте bpm или старый трюк с bpx API+x, т.к. telock проверяет вызываемые функции на СС в начале (разумеется, точки останова на Native API никто проверить не сможет). bpm LoadLibraryA и bpm GetProcAddress – наши отправные позиции. Используйте их просто как зацепку, т.к. нам нужна ЧИСТАЯ, НЕИЗМЕНЕННАЯ директория импорта. Куски кода можно просто дампить IceExt по ходу дела и бинарные сегменты дизассемблировать прямо в IDA. Дамп – разбор кода, дамп – разбор кода. Можно, скажем, поступить и еще оригинальнее – известно, что в один прекрасный момент времени директория (да и не только она) является полностью разжатой – просто выполните в Soft-Ice поиск имен библиотек или предполагаемых функций (например, «kernel32.dll»), в памяти и разберитесь на глаз с диапазонами директории). Словом, дорогу осилит идущий.
На вашу совесть также мы оставляем трюк с мьютексами. После прочтения Джеффери Рихтера он не должен быть источником проблем.
Список литературы
Эта статья никогда не была бы написана, если бы не громадный ворох литературы, который был основательно перелопачен. В подавляющем большинстве – это англоязычные книги, лишь для нескольких из них был выполнен перевод. Поэтому, как это не прискорбно, знание языка ОБЯЗАТЕЛЬНО, если хотите быть в потоке.
Список литературы ни в коем случае не ограничивается лишь этими 4-мя книгами. Мы старались давать как можно больше линков по ходу статьи – они стоят того, чтобы их прочесть.
Что до литературы по распаковке – такой, к сожалению, нет принципиально. Со статьями тоже напряженка. В подавляющем большинстве статей расписывается лишь как давить на кнопочки, или, что еще лучше – приводятся километровые ассемблерные листинги без комментариев, превращая статью в нечто нечитабельное. Здесь хочется похвалить Касперски, который очень удачно выбирает размер листингов в своих книгах – 10-20 очень тщательно подобранных строк – самое то!
Выводы
Ну что ж. Вот и закончена очередная часть. Будем надеятся, вы усвоили две главные вещи.
Вещь 1: программа исполняется не в вакууме! Windows создает и поддерживает огромное количество сложнейших структур данных, поддерживающих каждый процесс, каждый поток. Чем больше ваше понимание об этих механизмах – тем легче ломать. Применение ImpRec/PE Tools и иже с ними не освобождает от понимания принципов, лежащих в основе этих и многих других утилит.
- Что такое upu почта
- Что такое ur uslugi