автоматична ломалка

Що ви зазвичай робите, щоб зламати шароварну прогу? правильно,
лізете в інтернет за кряком. Але якщо програма рідкісна, то кряка
може не бути 🙁 От би зробити універсальний кряк, що підходить до
будь-якій програмі ... 🙂

Ще шість років тому, коли віндовз 95 ще вважався незрозумілим перекрутити,
мною була створена автоматична ломалка, за кілька секунд
розкриває захист приблизно третини підсунених програм без втручання
людини. Але по молодості ваш покірний слуга сплутав міський конкурс
прикладних програм і DefCon і мав необережність продемонструвати
своє дітище (демонструвалося, як шароварний RAR стає
зареєстрованим). Природно, що ідею м'яко кажучи не оцінили,
і програма була занедбана.

Нещодавно, зіткнувшись із захистом електронної версії журналу,
я зрозумів, що ідея автоломалкі все ще актуальна. експлуатується
той факт, що програмісти, які не знайомі зі способами злому софту,
з року в рік роблять одну і ту ж дурість: порівнюють правильний
пароль з введенням.

Я не буду викладати готову автоломалку, тому що цим відіб'ю
всю охоту вивчати це питання 🙂 Набагато корисніше буде опис,
як її створити.

Мови програмування високого рівня (Delphi, C і, VB) порівнюють
рядки за допомогою стандартних процедур, які можна пропатчити
з метою розширення їх можливостей 🙂 Наприклад, всі порівнювані
рядки можна кидати в файл, таким чином можна вивудити правильний
пароль. Або можна змусити програму вважати будь-які два рядки
рівними, тоді будь-який введений пароль буде вважатися вірним.

Насправді ця процедура порівняння викликається багато разів в
«Службових» цілях, так що патчить її треба обережно. Я використовую
таку модифікацію алгоритму: якщо одна з порівнюваних рядків
починається на BUGZ, то результат порівняння - «рядки рівні».
Інакше запускається стандартний алгоритм порівняння. Це дозволяє
ввести замість серійника / пароля слово BUGZY 😉 А якщо серійний номер
повинен бути довшим, то залишок можна «забити» будь-яким іншим текстом.

Патчити код в виконуваному модулі (exe, dll) або прямо в пам'яті - справа
хазяйське, автоломалка в обох випадках виглядає абсолютно
однаково, за винятком використовуваних функцій читання і запису.

Власне про те, що і як патчить.

Крок перший: знайти функцію порівняння.
Шукати будемо по сигнатурі, тобто шматку коду, присутнього в функції.
Кожен компілятор має свою сигнатуру, однак самих компілаторов
не так вже й багато, до того ж, немає особливої ​​потреби робити автоломалку
для компілятора Фортрану і watcom c: ти спробуй спочатку знайди
проги, які на них зроблені 🙂 Вистачило б джентельменсткого
набору: Delphi, MSVC і BC.

Щоб визначити сигнатуру конкретного компілятора, я не придумав нічого
краще, ніж поставити його собі, потім викликати функцію порівняння і
подивитися на неї з дізассемблірующего відладчика.

Крок другий: знайти місце для додаткового коду.
так як можливості функції порівняння розширюються, пропатчити код «на місці»
не виходить, доводиться розміщувати додатковий код в невикористаної
частини пам'яті. З основної процедури робиться стрибок на вставку, а потім
управління повертається зі стандартною процедурою перевірки.

Як «вільного місця» я використовую першу-ліпшу область,
забиту великою кількістю нулів. Начебто працює, хоча не повинно 🙂

Крок третій: підготовка патча.
Патч містить умовні та безумовні переходи від шматка коду на місці
«Нормальної» процедури порівняння до вставки і назад. Так як «відстань»
між ними заздалегідь невідомо, доведеться розраховувати довжину стрибків
виходячи з розташування частин патча.

Крок четвертий: запис патча.
дані просто нахабно пишуться в пам'ять процесу або в файл, в залежності від
обраного методу. Починати записувати краще з вставки, хіба мало чого 🙂

Нарешті, практичний приклад патча (для Delphi).

Для порівняння рядків компілятор використовує функцію LStrCmp. В явному вигляді з
коду високого рівня ця функція не викликається, але при дізассембліровніі
її видно. Ось як виглядає її асемблерний лістинг:

push ebx
push esi
push edi
mov esi, eax
mov edi, edx
cmp eax, edx
jz StringsEqual - перевірка на порівняння рядки з самою собою
test esi, esi
jz NotEqual - перевірка на порожній рядок
test edi, edi
jz NotEqual - перевірка на порожній рядок

а далі йде те, що я використовую як сигнатуру (8b 46 fc 8b 57 fc 29 d0):

mov eax, [esi-4] - це місце
mov edx, [edi-4] - заміщається
_subptr: - сюди відбувається повернення з патча
sub eax, edx

Там, де знаходиться цей код, буде розташовуватися перша частина патча -
перехід на другу. Патч - 5 байт, що починаються з E9.

Друга частина патча:
mov eax, [esi-4] - то, що ми
mov edx, [edi-4] - затерли стрибком
cmp [esi], $ 5a475542 - рядок 'BUGZ'
_se:
(*) Jz StringsEqual - перехід в частину процедури, що говорить, що рядки рівні
cmp [edi], $ 5a475542 - то ж для другого аргументу
jz _se - щоб не возитися зайвий раз з перерахунком довжини стрибка
(*) Jmp _subptr - перехід до «нормальної» процедурі порівняння

код рядків, позначених (*), розраховується виходячи з відстані між
шматками патчів.

Залишається тільки додати, що для редагування програми прямо в пам'яті (після
того, як вона їм заважає і розпакувала сама себе, якщо була запакована
asprotect etc), проводиться за допомогою функцій OpenProcess або
CreateProcess, ReadProcessMemory і WriteProcessMemory, опис яких є в win32.hlp. Автоломалка успішно випробувана на тестових
програмах (які просто порівнюють введену рядок з еталоном)
і на електрохакере # 34 (останній в якості коду активації приймав
слово 'BUGZY').

Очікується, що автоломалка буде розкривати кожну третю програму. ця
помилка початківців захисників вічна ...

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

«Лабораторія Касперського» представила свою версію інциденту, що призвів за собою витік даних АНБ

В анонімному сервісі для інформаторів SecureDrop знайдена уразливість, що призводить до витоку даних

Захисне рішення Google Play Protect порівняли з іншими антивірусами для Android

Схожі статті