Захист програм від дизассемблирования

Напевно кожен з вас стикався з проблемою щось змінити в якийсь чужий проге. Якщо це передбачало просто заміну інформації, то ви, недовго думаючи, запускали свій улюблений HEX вьюер і міняли все що можна. Не завжди для досягнення результату вдавалося зберегти розмір програми. Але і тоді крутий програмер не зупинявся і запускав свій дизассемблер (дизасемблювання - процес, в результаті якого з програми ви отримуєте її вихідний код на ... асемблері :). Ha сьогоднішній день відома туєва хуча пристойних д / а, як то IDA, Periscope, Bubble
Chamber, Sourcer, etc ...). Якщо у Вас такого ще немає, то я раджу почати з IDA (Interactive DisAssembler Pro), який можна дістати на
www.datarescue.com/idabase. Далі в отриманих ASM файлах змінювалося що було потрібно, і потім з них знову ліпили
працюючу прогу. Найбільш просунуті програмісти часто з отриманих початкових кодів намагаються зібрати програми для мов високого рівня, будь то С, Fortran або навіть Basic і Pascal. Цей процес називається декомпіляцією, через його складності автоматичні реалізації зустрічаються вкрай рідко. Декомпілюються зазвичай вручну, при цьому шукають кінець і початок функцій. Наприклад, зустрівши рядки 'push ebp; mov ebp, esp 'ви можете сказати, що це початок функції, а' pop ebp; retn '- її кінець. Такі просунуті дизасемблери як IDA вже виділяють всі функції, і завдання ставиться тільки зрозуміти, що вони роблять.

Але ось ви почали розбирати програму і ... облом :(. Ваша прога видала дуже маленький код і завалила якимись db з незрозумілими цифрами. При цьому ви явно запідозрили щось недобре. Якщо програма закодована або захищена чимось дуже страшним, що не варто відразу відкидати її і кричати «Я таку гидоту і за сто років не гарячкуй!». Досить усвідомити, чим би програма не була закодована, ВОНА САМА Ж сЕБЕ розкодує, щоб працювати. Ну ось. А далі залишається тільки діяти. Якщо програма себе дешифрує / розпаковує або еще_х_знает_чт _делает, то можна цю частину програми запустити і взяти вже розпакували КОД. Є й інший підхід, в принципі не відрізняється від попереднього: запустити прогу, і під час її роботи записати використовувану їй пам'ять на диск.

Як правило, шіфруемие програми, в тому числі і поліморфні віруси :), шифрують себе кілька разів, при цьому вони можуть переносити або навіть змінювати свій код, запускати розшифровану інформацію для подальшої розпакування, ну а також застосовувати і інші заплутують підходи. Звідси випливає, що дизассемблером користуватися невигідно. Для цієї мети виглядає вигідно послідовно прогу виконувати по одній інструкції (так зване трасування - trace) або виконувати програму до заданої інструкції / області пам'яті. Такими функціями володіють практично всі отладчики (дебаггера). Тільки не кажіть мені, що у вас їх немає. Навіть в DOSе (і мастдайке в т.ч) є утилитка DEBUG - найпростіший відладчик. Але він, на жаль, 16-бітний, і в загальних рисах не задовольняє вимогам крутих программеров. Взагалі, практично у будь-якої мови програмування є дебаггер. У Borlandовскіх (Turbo Assembler (TASM), Borland's C ++) - це серія TD (Turbo Debugger). TD - для DOSовскіх програм, TDW - для віндовскій. Але часто TDW Не бере програму з заголовком PE / NE 32bit. Тоді сміливо запускайте TD32. Не варто забувати і MicroSoft. В їх продуктах (MicroSoft Assembler, MASM) можна знайти відладчик CodeView (CV, CVW). Відносно недавно з'явився пакет утиліт NuMega фірми Compuware, дивіться на
www.numega.com. Отладчик NuMega SoftIce (winice) дозволяє дебаггіть навіть ядро ​​системи, а також з легкістю переглядати всі треди, процеси і вікна. Часто він входить в комплект BoundsChecker.

Тепер у нас є все для злому. Запускаєте в отладчике потрібну прогу, і виконуєте по інструкції ... 🙂 якщо ж терпець не вистачить, то поставите breakpoint на виході з циклу і запустіть програму з того місця, на якому зупинилися. Програма передасть управління отладчику перед виконанням інструкції з позначкою breakpointом. Найчастіше breakpointи є переривання (точніше, пастки), які замінюють помічені інструкції. Навіщо я це пишу. - просто
будьте пильні, щоб програма не замінить інструкцію, на якій стоїть breakpoint, а то він може
загубитися, і програма буде виконуватися поки не закінчитися :-(. Ну ось, припустимо ми дійшли до того місця, коли починається власне розпаковані програма ... принаймні як Ви думаєте, а насправді це може бути продовження декодера: D. Тепер можете зберегти всю отриману кашу як EXEшнік. Але тільки врахуйте вашу нову точку входу і
подбайте про те, щоб значення регістрів збереглося ... а раптом вони далі будуть використані. Тема ви можете подивитися за допомогою класної утиліти HIEW (Hacker's View) by SEN (ftp.kemsc.ru/pub/sen). Якщо прога DOSовская - заголовок MZ, віндовскій - найчастіше PE.

Тепер розглянемо деякі способи захисту програм від дизассемблирования. Якщо Ви - крутий програмер, зробили класну прогу, і з якихось причин хочете приховати її код (а раптом хто помітить там мого улюбленого троянчіка.), То перше, що прийде вам на розум - зашифрувати її. Тут ви можете погортати веселі книжки по криптографії, але в кінці зрозуміти, що распаковщик занадто простий. Я можу також запропонувати не тільки зашифрувати, а й запакувати інфу. Якщо нічого не знаєте - перше, що придумаєте, буде RunLengthEncode, але пакувати їм код - дохлий номер. Краще використовувати якусь модифікацію алгоритму LZW. Він, точніше його модифікації, використовуються в багатьох архіваторах (RAR, ZIP), в графічних файлах GIF, навіть в PDFах, їм запаковуються EXEшнікі (PKLITE). Тепер, коли є основа, подумаємо про те, як зіпсувати життя любителям розкривати програми. По-перше, можна зашифрувати частину Розпакувальник, взагалі так можна шифрувати програму по частинах, і по кілька разів зашифровувати розшифровувача :), а потім ще всі разом зашифрувати :))). Можна спокійно перемішувати частини програми, що також може привести в замішання.
Крім цього, можна придумати і більш дієві способи захисту. Як ви думаєте, що буде перебувати в регістрах після виконання наступної ділянки коду:

Label1: mov ax, 1ab8h
mov bx, 06bbh
mov cx, 00b9h
mov dx, 01bah
mov si, 0ffbeh
mov di, 32bfh
jmp Label1 + 1

Правильна відповідь: bx = 0x0b906; cx = 0x0ba00; dx = 0x0be01; si = 0x0bfff; di = 0x0eb32. Чи не зрозуміли чому. Тоді відкомпілюйте її і протрассіруйте. Щоб прибирати наставлені breakpointи можна змінювати виконується код, наприклад, збільшувати або зменшувати таку інструкцію, можна ставити на них маски, складати, та й просто перезаписувати. Таким чином кожен раз подальша інструкція може бути змінена:

push cs
pop ds
mov ch, 0ebh
mov esi, offset $ або Label2: mov esi, offset Label2
add byte ptr [esi + 07], 08
sub byte ptr [esi + 10], 5
db Rel

Цей фрагмент виконує відносний перехід на Rel байтів (рівносильно Jmp short ptr Rel). Можна (навіть треба) захищати програми від ... трасування. Так, саме від трасування. Ну, і їжаку зрозуміло, що трасування набагато довше звичайного виконання програми. Це і можна використовувати. Нижче я приведу фрагмент, що викликає функцію DOS 'Get
Time ':

mov ah, 2ch; Get Time
int 21h; call DOS services
push dx; dh - seconds, dl - hundredths of a second (0-99)
mov ah, 2ch; Get Time
int 21h; call DOS services
pop ax; ah - seconds
cmp dh, ah
jz continue
; GOTCHA.

Якщо час в секундах не змінилося, то здійснюється перехід на мітку continue, інакше триває виконання програми. Ну а тут ... можна поставити і низькорівневе форматування диска 80H (ну, C: я маю на увазі ...). Це для особливо поганих людей типу мене: p, а іншим ... раджу просто підвісити систему.
Навіть вищенаведений фрагмент, насправді, можна протрассировать набагато швидше секунди, тому раджу вставляти запити часу в різні ділянки програми,
можна навіть по-різному запаковані, так як розпакування набагато швидше трасування.
Більш того, порівняння отриманих секунд можна відкласти на наступну ділянку коду, так щоб він не особливо виділявся, а то відразу запідозрять: спочатку подивився скільки часу, потім порівняв з чимось, а навіщо. ... Часто у багатьох крекерів (мене в т.ч.) викликають підозри команди умовного переходу, тому доречніше було б написати все це без них:

Насправді, ще можна придумати туеву хучу способів запудрити мізки хакерам, так що хто на що здатний :). Вважаємо, що програма зашифрована добре. Залишилося це зробити на практиці. Я сподіваюся у Вас не з'явилося бажання запакувати EXEшнік цілком. Ну, якщо так, і ви ще не придумали як це зробити, підказую: у EXEшніков можна змінювати точку входу ... i.e. ви запаковують відкомпільоване інфу, а дешифратор прикріплюєте знизу :). Не хочете? Просто? Будь ласка - я знаю, наприклад, в
C ++ Buildere з подібних є функція компілювання вашого файлу в ... асемблерний source (сам користувався), так що сміливо озбройтесь ассемблером і вперед. Ну, і один з найвеселіших способів - запаковувати окремо процедури, просто вставляєте асемблерний код в програму ... Зрештою, можна створити * .lib, * .obj або * .dll файл і перекручуватися над ними. Тут вже кому що більше
подобається. Головне, щоб гимора поменше і ... працювало!

Покажи цю статтю друзям:

Схожі статті