Взлом программы защищенной про­тек­тором Enigma

Взлом программы защищенной про­тек­тором Enigma

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

Еще по теме: Удаленная отладка вредоносных программ

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

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

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

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

Вкладка Trial Control утилиты Enigma Protector
Вклад­ка 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 генери­рует все вре­мя новые, для каж­дой прог­раммы они одни и те же. То есть дос­таточ­но пер­вый раз их опре­делить, и мож­но сме­ло в пакет­ном режиме уби­вать их перед запус­ком защищен­ной прог­раммы. Труд­но поверить, но надо приз­нать­ся, что все доволь­но прос­то.

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

Еще по теме: Отладка программ с помощью WinDbg

ВКонтакте
OK
Telegram
WhatsApp
Viber

Добавить комментарий

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