Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Для защиты приложений .NET от отладки и реверса существует множество способов (шифрование, компрессия и другие), а также специальных протекторов, таких как, например, Agile.Net и Enigma. О взломе многих из них мы уже писали. Сегодня я расскажу, как побороть еще один популярный протектор и обфускатор — .NET Reactor.
Итак, представим себе такую гипотетическую задачу: у нас имеется некое приложение с онлайн‑проверкой лицензии при загрузке. Его анализ при помощи DIE детектит наличие платформы .NET. Загрузив программу в отладчик dnSpy, обнаруживаем сразу две вещи: плохую и хорошую. Начну с плохой: приложение жестоко обфусцировано, часть методов переименована в бессмысленный набор символов, а главное, вместо их кода повсюду пустые заглушки.
Приложение в отладчике dnSpy
Для очистки совести пробуем сдампить приложение способами, описанным в моей предыдущей статье, — это частенько помогает восстановить скрытый код методов. Увы, не в нашем случае: сдампленные модули работоспособны, но несильно отличаются от исходных. Обфускация никуда не делась, тела методов все равно пустые.
Возвращаемся в отладчик dnSpy и пробуем потрассировать работающую программу. А вот и хорошая новость: в приложении нет антиотладчика, приложение прекрасно запускается и трассируется, причем при трассировке «пустых» методов во вкладке Call Stack видно, что счетчик команд перемещается по невидимому коду и проваливается в вызовы. Погуляв вслепую по коду, мы обнаруживаем еще одну хорошую новость: не все методы переименованы, некоторые названия вполне осмысленны, и можно даже нащупать процедуру проверки валидности (на скриншоте выше — isValid
). Тело данного метода скрыто, но название и индекс известны, и это уже что‑то.
Попробуем подойти к деобфускации по стандартной схеме: для начала натравливаем на приложение de4dot. К сожалению, в нашем случае этот метод не работает, de4dot ничего не деобфусцирует. Более старые версии сразу валятся с ошибкой:
de4dot v3.1.41592.3405 Copyright (C) 2011-2015 [email protected]
Latest version and source code: https://github.com/0xd4d/de4dot
Detected .NET Reactor 4.8
Необработанное исключение: System.Security.Cryptography.CryptographicException: Недопустимая длина данных для дешифрования.
в System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
в de4dot.code.deobfuscators.DeobUtils.AesDecrypt(Byte[] data, Byte[] key, Byte[] iv) в D:ade4dot-cexde4dot-cexde4dot.codedeobfuscatorsDeobUtils.cs:строка 87
в de4dot.code.deobfuscators.dotNET_Reactor.v4.EncryptedResource.DecrypterV1.Decrypt(EmbeddedResource resource) в D:ade4dot-cexde4dot-cexde4dot.codedeobfuscatorsdotNET_Reactorv4EncryptedResource.cs:строка 225
в de4dot.code.deobfuscators.dotNET_Reactor.v4.EncryptedResource.Decrypt()
…
Версии посвежее формулируют ошибку лаконичнее:
Latest version and source code: http://www.de4dot.com/
21 deobfuscator modules loaded!
Detected .NET Reactor 4.8
ERROR:
ERROR:
ERROR:
ERROR: Hmmmm… something didn’t work. Try the latest version.
Ну теперь мы хотя бы знаем, с чем имеем дело, — это .NET Reactor версии предположительно 4.8. Версия довольно старая, однако с ней не справляется даже специально обученный под .NET Reactor de4dot. Ошибка та же, и нам снова предлагают поискать версию посвежее.
Трудности нас не останавливают: в конце концов, мы уже научились разбирать более крутые обфускаторы типа Agile буквально изнутри на самом низком уровне. Загружаем нашу злополучную программу в отладчик x32dbg и вспоминаем все то, о чем я писал в предыдущей статье. Дабы не тратить время на повторение, опускаю длинное описание теоретической части процесса. Вкратце: загружаем библиотеку cljit.dll, отладочные символы к ней и ставим точку останова на вход JIT-компилятора CILJit::compileMethod
.
Указанный способ работает, то есть при каждом вызове компилятора в поле ILCode
структуры CORINFO_METHOD_INFO
мы видим расшифрованный IL-код каждого метода. В принципе, можно анализировать код и даже патчить на лету, но это долго и утомительно, вдобавок нас ждет еще одна ложка дегтя. Напомню, что в предыдущей статье я описывал слегка жульнический способ определить индекс компилированной процедуры. Суть его состоит в том, что хендл ftn
(первое двойное слово в структуре CORINFO_METHOD_INFO
), если его использовать как указатель, указывает на одинарное слово — индекс метода в .NET метадате EXE-модуля.
Источник: xakep.ru