Триальный конь. Как сломать trial, защищенный Enigma Protector

Триальный конь. Как сломать trial, защищенный Enigma Protector

Life-Hack [Жизнь-Взлом]/Хакинг

#Обучение

По­пуляр­ный сре­ди раз­работ­чиков соф­та про­тек­тор Enigma пред­лага­ет нес­коль­ко вари­антов защиты при­ложе­ний. Один из них — уста­новить проб­ный режим с огра­ниче­нием на количес­тво запус­ков, дней исполь­зования или рабоче­го вре­мени. Кажет­ся, пре­одо­леть такую защиту неп­росто. Одна­ко для нас­тояще­го иссле­дова­теля нет прег­рад!

WARNING

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

Пос­тоян­ным читате­лям «Хакера», зна­комым с моей пре­дыду­щей стать­ей, мог­ло показать­ся, что взлом защиты Enigma пред­став­ляет собой какое‑то архислож­ное дей­ствие, дос­тупное лишь избран­ным спе­циалис­там, обла­дающи­ми навыка­ми работы с отладчи­ками и воору­жен­ными спе­циаль­ными инс­тру­мен­тами. Пра­виль­но показа­лось, имен­но такого эффекта я и собирал­ся добить­ся. Одна­ко я недаром делал ого­вор­ку о наличии сла­бых мест, которы­ми поль­зуют­ся мно­гочис­ленные сетевые авто­ры обу­чающих видео и «однокли­ковых ути­лит». Сегод­ня мы рас­смот­рим одно из таких сла­бых мест защиты Enigma — три­аль­ный режим.

INFO

Очень час­то перед покуп­кой раз­работ­чики дают поль­зовате­лю воз­можность поиг­рать с прог­раммой огра­ничен­ное вре­мя или опре­делен­ное чис­ло запус­ков, что­бы он оце­нил все воз­можнос­ти соф­тины. И конеч­но же, защита Enigma име­ет в сво­ем джентль­мен­ском наборе такую фичу. Ленивые раз­работ­чики могут соз­давать три­аль­ные вер­сии сво­их прог­рамм фак­тичес­ки нажати­ем одной кноп­ки. Одна­ко такое доверие Enigma Protector может ока­зать­ся неоп­равдан­ным, и сей­час я рас­ска­жу почему.

Для понима­ния про­цес­са ска­чаем с офи­циаль­ного сай­та пос­леднюю демовер­сию защиты, бла­го они ее сво­бод­но раз­дают. Запус­тив прог­рамму, мы уви­дим в меню Settings вклад­ку Trial Control. Здесь находят­ся нуж­ные нам раз­делы: Limitation by Executions Count (огра­ниче­ние на количес­тво запус­ков), Limitation by Days Count (огра­ниче­ние на количес­тво дней), Limitation of Execution Time (огра­ниче­ние на количес­тво прог­рам­мно­го вре­мени) и Time Control (про­вер­ка мух­лежа с перево­дом вре­мени).

Вклад­ка Trial Control ути­литы Enigma Protector

Осо­бен­ности этих режимов зак­люча­ются в том, что при пер­вом запус­ке прог­рамма «при­вязы­вает­ся» к текуще­му момен­ту и ведет отсчет сво­ей работы имен­но от него. Тех­нология сбро­са подоб­ного три­ала зак­люча­ется в том, что­бы вер­нуть сис­тему в сос­тояние, пред­шес­тву­ющее запус­ку, пос­ле чего прог­рамма будет стар­товать как буд­то в пер­вый раз пос­ле уста­нов­ки. Нап­ример, с режимом Limitation from Date till Date (огра­ниче­ние на запуск в кон­крет­ный вре­мен­ной отре­зок) такой номер не прой­дет, пос­коль­ку при­ложе­ние уже не при­вяза­но к момен­ту пер­вого запус­ка. Защита про­веря­ет лишь текущее сис­темное вре­мя, незави­симо от того, запус­калась прог­рамма до это­го на дан­ном компь­юте­ре или нет. Хотя, конеч­но, мож­но обма­нуть и этот метод защиты, сбро­сив три­ал (что­бы исклю­чить запоми­нание текуще­го вре­мени с целью обма­нуть Time Control, если этот режим так­же вклю­чен) и переве­дя часы на нуж­ный вре­мен­ной интервал.

Од­нако хва­тит лиричес­ких отступ­лений, пора брать­ся за дело! Давай защитим любое при­ложе­ние, огра­ничив количес­тво его запус­ков, а потом сбро­сим эту защиту. По счастью, раз­работ­чики Enigma и здесь пош­ли нам навс­тре­чу, бес­плат­но пре­дос­тавив такую воз­можность в демовер­сии сво­его про­тек­тора. Для это­го откры­ваем вклад­ку Limitation by Executions Count, уста­нав­лива­ем вер­хний чек­бокс и в окош­ке Maximum count of executions ука­зыва­ем нуж­ное количес­тво запус­ков (ска­жем, три).

Нас­тра­иваем огра­ниче­ние на количес­тво запус­ков

Те­перь соберем защищен­ную вер­сию прог­раммы, которая при каж­дом стар­те будет показы­вать пятисе­кун­дное окош­ко рек­ламы Enigma (что поделать, за халяву при­ходит­ся пла­тить) и счи­тать запус­ки. Через три запус­ка вмес­то прог­раммы ты уви­дишь сооб­щение о пре­выше­нии лимита, озна­чающее, что халява закон­чилась.

Для начала поп­робу­ем пой­ти самым тер­нистым путем — попыта­емся снять защиту сов­сем. Как я уже писал в пре­дыду­щей статье, прог­рамма, защищен­ная Enigma вер­сии стар­ше 4, прос­то не дам­пится. Вер­нее, дам­пится, но на выходе получа­ется толь­ко сле­пок кода реали­зации защиты, который нам не силь­но нужен. Поп­робу­ем разоб­рать­ся, как сдам­пить прог­рамму руками, бла­го незащи­щен­ная вер­сия у нас есть. Открыв исходную прог­рамму, мы уви­дим в ней 12 сек­ций:

Name VirtSize RVA PhysSize Offset Flag

.text 00E8CEBC 00001000 00E8D000 00001000 60D00060

.data 000103F8 00E8E000 00010400 00E8E000 C0700040

.rdata 003C0A80 00E9F000 003C0C00 00E9E400 40600040

.qtmetad 00000620 01260000 00000800 0125F000 40600040

.eh_fram 002B5648 01261000 002B5800 0125F800 40300040

.bss 00003AC0 01517000 00000000 00000000 C0600080

.edata 00000E04 0151B000 00001000 01515000 40300040

.idata 000055C4 0151C000 00005600 01516000 C0300040

.CRT 00000038 01522000 00000200 0151B600 C0300040

.tls 00000008 01523000 00000200 0151B800 C0300040

.rsrc 000428B0 01524000 000428B0 0151BA00 C0300040

.reloc 00062CFC 01567000 00062E00 0155E400 42300040

В защищен­ной прог­рамме эти сек­ции тоже при­сутс­тву­ют, прав­да без наз­ваний, фла­гов и в зашиф­рован­ном виде:

1 00E8D000 00001000 0061CC00 00000600 E0000040

2 00011000 00E8E000 00001A00 0061D200 E0000040

3 003C1000 00E9F000 001E8E00 0061EC00 E0000040

4 00001000 01260000 00000200 00807A00 E0000040

5 002B6000 01261000 000BFA00 00807C00 E0000040

6 00004000 01517000 00000000 00000000 C0600080

7 00001000 0151B000 00000000 008C7600 E0000040

8 00006000 0151C000 00000800 008C7600 E0000040

9 00001000 01522000 00000200 008C7E00 E0000040

10 00001000 01523000 00000000 008C8000 E0000040

11 00043000 01524000 00000000 008C8000 E0000040

12 00063000 01567000 00000000 008C8000 E0000040

То, что они зашиф­рованы, — еще пол­беды, пос­коль­ку по мере заг­рузки сек­ции рас­шифро­выва­ются: в этом мы можем убе­дить­ся, «всплыв» отладчи­ком во вре­мя работы уже заг­ружен­ной прог­раммы. Одна­ко здесь нас ожи­дает неп­рият­ный сюр­приз — жиз­ненно необ­ходимые нам сек­ции импорта и экспор­та (в нашем при­мере .edata и .idаta) запол­нены нулями. Злов­редная Enigma очи­щает их пос­ле заг­рузки при­ложе­ния в память, что­бы осложнить нам жизнь. В прин­ципе, таб­лица экспор­та у нас есть, но импорт, ори­гиналь­ные наз­вания и фла­ги сек­ций отсутс­тву­ют, не говоря уже о точ­ке вхо­да в при­ложе­ние.

Как ни кру­ти, а при­дет­ся лезть в вир­туаль­ную машину. Заод­но пос­мотрим, как она выг­лядит в 32-бит­ной вер­сии (в прош­лой статье была опи­сана 64-бит­ная реали­зация). Уже при попыт­ке сдам­пить при­ложе­ние мы с огор­чени­ем обна­ружим, что при дан­ном спо­собе защиты из нее уже не тор­чат уши интер­пре­тато­ра в виде экспор­тиру­емых сим­волов, — интер­пре­татор при­дет­ся искать самим. Заг­рузив прог­рамму в отладчик (не забыва­ем о ScyllaHide) и тупо запус­тив, с ходу спо­тыка­емся о пер­вую попыт­ку исклю­чения на одной из двух рогаток:

01AF05A5 div eax ; <---------------------- Деление на ноль

01AF05A7 call 1B04618

01AF05AC xor eax,eax

01AF05AE pop edx

01AF05AF pop ecx

01AF05B0 pop ecx

01AF05B1 mov dword ptr fs:[eax],edx

01AF05B4 jmp 1AF05EB

01AF05B6 jmp 1A108B4

01AF05BB call 1A10C1C

01AF05C0 jmp 1AF05EB

01AF05C2 xor eax,eax

01AF05C4 push ebp

01AF05C5 push 1AF05E1

01AF05CA push dword ptr fs:[eax]

01AF05CD mov dword ptr fs:[eax],esp

01AF05D0 ud2 ; <----------------------------- Недопустимая инструкция

01AF05D2 call 1B04618

01AF05D7 xor eax,eax

01AF05D9 pop edx

01AF05DA pop ecx

01AF05DB pop ecx

01AF05DC mov dword ptr fs:[eax],edx

01AF05DF jmp 1AF05EB

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

push 7E7D14B3

jmp.1B91420

Мы наш­ли адрес 32-бит­ного интер­пре­тато­ра шитого кода 32-бит­ной вир­туаль­ной машины, ана­логич­ной той, что я опи­сал в пре­дыду­щей статье. Здесь он выг­лядит вот так:

pushad

pushfd

mov dl,1

mov esi,0

lea edi,dword ptr ds:[esi+1B937E4]

lea edi,dword ptr ds:[edi]

mov ecx,1

xor eax,eax

lock cmpxchg dword ptr ds:[edi],ecx

je 1B9144D

cmp dl,byte ptr ds:[1B937E0]

je 1B91422

inc dl

add esi,64

jmp 1B91429

lea eax,dword ptr ds:[esi+1B937E4]

lea eax,dword ptr ds:[eax+10]

mov ecx,dword ptr ss:[esp]

...

Да­лее, с исполь­зовани­ем уже зна­комо­го нам спо­соба, ста­вим на него условную точ­ку оста­нова с печатью в лог {RAX} {[RSP]}. Нам пред­сто­ит ана­лизи­ровать логи и искать раз­вилки в вир­туаль­ном коде на пред­мет экспи­рации три­ала или наличия уже рас­шифро­ван­ной, но еще не обну­лен­ной сек­ции импорта.

Про­цесс неп­ростой, и осложня­ется он еще и тем, что акту­аль­ная Enigma, как и любая взрос­лая вир­туали­зиро­ван­ная защита, вдо­бавок про­фили­рует вре­мя работы отдель­ных учас­тков вир­туаль­ного кода. То есть нель­зя прос­то так взять и вклю­чить логиро­вание с самого начала пер­вого запус­ка вир­туаль­ной машины и получить пол­ный лис­тинг ее вызовов до заг­рузки при­ложе­ния. В этом слу­чае в опре­делен­ный момент защита обна­ружит наличие точ­ки оста­нова и выкинет ошиб­ку Internal Protection Error, please contact to author!. Поэто­му надо отсле­живать в вир­туаль­ном коде кри­тичес­кие точ­ки таких про­верок и акку­рат­но обхо­дить их. Воз­можно, я ког­да‑нибудь рас­ска­жу и об этом. Но в начале статьи я, кажет­ся, обе­щал рас­крыть прос­той спо­соб?

Ты будешь сме­ять­ся, но, что­бы зас­тавить прог­рамму зарабо­тать вновь, нам не понадо­бит­ся даже отладчик. Что нам пот­ребу­ется, так это Process Monitor (ProcMon мож­но бес­плат­но ска­чать с сай­та Microsoft) и встро­енный редак­тор реес­тра RegEdit.

Что­бы отсле­дить, куда Enigma пря­чет свои дан­ные, запус­каем ProcMon в момент стар­та защищен­ной прог­раммы на компь­юте­ре. Если мы пре­дус­мотри­тель­ные, то дела­ем это при пер­вом запус­ке, если нет и мы про­мор­гали этот тро­гатель­ный момент — тоже не беда. ProcMon, по сво­ему обык­новению, вывали­вает огромней­ший спи­сок все­воз­можных сис­темных вызовов, неп­рерыв­но удли­няющий­ся с каж­дой секун­дой, и, кажет­ся, разоб­рать­ся в нем нет никакой воз­можнос­ти. Не спа­сает даже то, что, при­тор­мозив прог­рамму, мы ста­вим филь­тр на обра­щения к реес­тру и фай­ловой сис­теме исклю­читель­но от нашего при­ложе­ния.

Но если мы выпол­ним в этом спис­ке поиск по сло­ву Enigma, про­изой­дет чудо! Пошур­шав нес­коль­ко секунд бай­тами, Process Monitor находит бли­же к середи­не спис­ка обра­щение к вет­ке реес­тра:

HKCU\Software\Enigma Protector\29AEB4A0365755F6-B862CAE984EA4D0E\02F01F553A112DCE-00C9DB38C18D5FD1

При­чем при пер­вом запус­ке нашей прог­раммы вет­ка соз­дает­ся, а при пов­торных — чита­ется. Не веря сво­им гла­зам (неуже­ли все так прос­то?), откры­ваем редак­тор реес­тра и акку­рат­но выпили­ваем дан­ную вет­ку (в катало­ге Enigma Protector может ока­зать­ся мно­го подоб­ных веток для дру­гих прог­рамм, тоже защищен­ных «Эниг­мой», их мы не тро­гаем).

Пе­реза­пус­каем прог­рамму, и тут нас под­сте­рега­ет облом — сно­ва сооб­щение о истекшем количес­тве запус­ков. Лезем в реестр: уби­тая вет­ка опять на сво­ем мес­те. Что ж, сно­ва уби­ваем, ее запус­каем ProcMon и прог­рамму — ага, пыта­ется обра­тить­ся к уби­той вет­ке, обла­мыва­ется, и сра­зу вслед за этим про­исхо­дит обра­щение к фай­лу C:\Users\Username\AppData\Local\Temp\80EB2F5C. Стран­ный файл, рас­положен­ный во вре­мен­ном катало­ге, раз­мер 14 байт.

Про­буем уда­лить его вмес­те с вет­кой, и — бин­го! Три­ал‑вер­сия соф­тины, как ни в чем не бывало, запус­кает­ся и прек­расно работа­ет. Поэк­спе­римен­тировав с раз­ными три­ала­ми на раз­ных прог­раммах, мы видим, что, нес­мотря на свою дубовость, спо­соб получил­ся уни­вер­саль­ным. Хотя наз­вания вет­ки реес­тра и фай­ла Enigma генери­рует все вре­мя новые, для каж­дой прог­раммы они одни и те же. То есть дос­таточ­но пер­вый раз их опре­делить, и мож­но сме­ло в пакет­ном режиме уби­вать их перед запус­ком защищен­ной прог­раммы. Труд­но поверить, но надо приз­нать­ся, что все доволь­но прос­то.

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

Источник



Report Page