Ангард! Реверсим приложение, защищенное DNGuard

Фан­тазия раз­работ­чиков, жела­ющих защитить свою прог­рамму, порой не зна­ет гра­ниц. Час­тень­ко им мало одно­го навешен­ного на соф­тину про­тек­тора, и они, как монаш­ка из извес­тно­го анек­дота, натяги­вают их нес­коль­ко штук пос­ледова­тель­но. Порой тем же самым гре­шат и сами раз­работ­чики средств защиты. Слу­чай подоб­ного сим­биоза IL-обфуска­тора с VMProtect мы и рас­смот­рим в сегод­няшней статье.

.NET-обфуска­тор DNGuard HVM сущес­тву­ет доволь­но дол­гое вре­мя, за которое он успел обза­вес­тись изрядным количес­твом фич (анти­отладка и анти­дамп, тоталь­ное шиф­рование всей информа­ции в модуле и весь­ма успешное про­тиво­дей­ствие ста­тичес­кому и динами­чес­кому ана­лизу). Нес­мотря на широкую извес­тность и неп­лохую изу­чен­ность (в свое вре­мя CodeCracker запилил мно­жес­тво рас­паков­щиков под раз­ные вер­сии DNGuard и сопутс­тву­ющих фрей­мвор­ков), пос­ледние нес­коль­ко лет средс­тва ана­лиза и рас­паков­ки для акту­аль­ных вер­сий это­го обфуска­тора нап­рочь отсутс­тву­ют. Вплоть до того, что популяр­ные инс­тру­мен­ты (и даже Detect It Easy) до сих пор не научи­лись их даже детек­тировать. Поэто­му, наде­юсь, сегод­няшняя статья поможет читате­лю разоб­рать­ся, как рас­познать эту заразу и бороть­ся с ней под­ручны­ми средс­тва­ми.

warning

Статья име­ет озна­коми­тель­ный харак­тер и пред­назна­чена для спе­циалис­тов по безопас­ности, про­водя­щих тес­тирова­ние в рам­ках кон­трак­та. Автор и редак­ция не несут ответс­твен­ности за любой вред, при­чинен­ный с при­мене­нием изло­жен­ной информа­ции. Рас­простра­нение вре­донос­ных прог­рамм, наруше­ние работы сис­тем и наруше­ние тай­ны перепис­ки прес­леду­ются по закону.

Итак, пред­положим, что в твои заг­ребущие руки попала сбор­ка, защищен­ная DNGuard. Есть два вари­анта. Пер­вый: нам повез­ло, и это одна из ста­рых изу­чен­ных вер­сий, тог­да все ясно и мож­но сме­ло поль­зовать­ся одним из дам­перов DNGuard_HVM_Unpacker от CodeCracker. Воз­можно, я ког­да‑нибудь и рас­ска­жу об осо­бен­ностях и даже прин­ципах работы этих ути­лит. Одна­ко DNGuard совер­шенс­тву­ется стре­митель­но, а про­ект, судя по все­му, дав­но заб­рошен: пос­ледняя вер­сия под­держи­ваемо­го фрей­мвор­ка была 4.2, а физичес­кая при­вяз­ка к кон­крет­ным фай­лам биб­лиотек нас­толь­ко силь­на, что дела­ет исполь­зование дан­ных нарабо­ток малопо­лез­ным в деоб­фуска­ции новых вер­сий.

По­это­му сра­зу перехо­дим к более грус­тно­му вари­анту. Как я уже писал выше, хоть акту­аль­ные вер­сии и не детек­тятся, одна­ко силь­но и не скры­вают­ся. В рабочем катало­ге прог­раммы сра­зу бро­сает­ся в гла­за биб­лиоте­ка runtime.dll (или со схо­жим наз­вани­ем), с навешен­ным на ней VMProtect на минимал­ках.

Внут­ри биб­лиоте­ки обна­ружи­вают­ся две экспор­тиру­емые фун­кции: VMRuntime и GetUserString (или ResolveString).

Еще одна харак­терная чер­та — VMProtect’овская сек­ция hvm0, из‑за которой этот обфуска­тор, нас­коль­ко я понимаю, и получил такое наз­вание.

Впро­чем, наличие этой биб­лиоте­ки в катало­ге в явном виде вов­се необя­затель­но, самые пос­ледние вер­сии научи­лись дер­жать ее в зашиф­рован­ном виде в теле основной прог­раммы, рожая ее при заг­рузке в сис­темные вре­мен­ные катало­ги типа Temp или ProgramData. Cама прог­рамма, защищен­ная этим обфуска­тором, тоже выг­лядит дос­таточ­но харак­терным обра­зом при заг­рузке в отладчик вро­де dnSpy.

Как вид­но, для стар­тап‑кода прог­раммы харак­терно наличие клас­са с метода­ми CheckRuntime, CheckString, GetUserString и так далее и импортом упо­мяну­тых выше фун­кций из биб­лиоте­ки Runtime.dll. Так же как и во всех серь­езных обфуска­торах, о которых я писал в пре­дыду­щих стать­ях, наз­вания осталь­ных клас­сов, методов, строк и ресур­сов жес­тко пошиф­рованы, а тела методов пус­ты или содер­жат вызов исклю­чения «Error, DNGuard Runtime library not loaded!» (при­чем даже эта стро­ка может быть зашиф­рована).

Собс­твен­но, если поп­робовать запус­тить такое при­ложе­ние из отладчи­ка, мак­симум, что мы смо­жем уви­деть, — это ини­циали­зация стар­тап‑кода DNGuard до натив­ного вызова VMRuntime, пос­ле чего тот перех­ватыва­ет на себя JIT-ком­пилятор и мы про­щаем­ся с отладчи­ком, сло­вив подоб­ное исклю­чение.

По­пыт­ка при­атта­чить­ся к запущен­ному про­цес­су тоже не дает полез­ного резуль­тата, так же как и дамп его все­ми извес­тны­ми дам­перами. Поэто­му зак­рыва­ем dnSpy и начина­ем вспо­минать мат­часть, в том чис­ле информа­цию, изло­жен­ную в моей статье «Ре­вер­синг .NET. Как искать JIT-ком­пилятор в при­ложе­ниях».

Для тех, кто не читал статью, напом­ню ее суть в двух сло­вах. Как извес­тно, любая .NET-сбор­ка устро­ена сле­дующим обра­зом: кросс‑плат­формен­ный IL-код хра­нит­ся в спе­циаль­ных метадан­ных, из которых под­гру­жает­ся по мере исполне­ния каж­дого метода и ком­пилиру­ется в натив­ный код спе­циаль­ной фун­кци­ей. Ука­затель на нее воз­вра­щает фун­кция GetGit биб­лиоте­ки clrjit.dll, одна­ко фрей­мворк любез­но пре­дос­тавля­ет поль­зовате­лю самому уста­нав­ливать адрес на ком­пилятор, чем без­застен­чиво поль­зуют­ся соз­датели все­воз­можных обфуска­торов, под­меняя ее сво­ими про­цеду­рами рас­шифров­ки IL-кода.

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *