Як ламати програми Windows (C) ED! SON [UCF], переклад Mr.Boco/TCP p>
p>
p>
ЗМІСТ p>
1. Введення в ламання Windows-програм p>
2. Огляд SoftICE/Win 2.oo p>
3. Пошук реєстраційних кодів p>
3.1 Task Lock 3.00 - проста захист на основі серійного номера p>
3.2 Command Line 95 - проста регсітрація "ім'я-код" p>
4. Створення генератора ключів для Command Line 95 p>
5. Як працюють інструкції PUSH і CALL коли програма викликає функцію p>
6. Про програми, написані на Visual Basic p>
ПРОГРАМИ p>
A. Як у SoftICE завантажувати символьні імена (імена функцій etc) p>
B. Синтаксис функцій GetWindowText, GetDlgItemText і GetDlgItemInt p>
C. Де знайти програми p>
D. Зв'язок з автором p>
1. ВСТУП У Ломанов WINDOWS-ПРОГРАМ p>
Ламати програми Windows у більшості випадків навіть простіше, ніж ламати програми Dos. У Windows складно що-небудь приховати від того,
хто шукає, особливо якщо програма використовує стандартні функції Windows. p>
Перша (і часто єдина) річ, яка Вам буде потрібно - це SoftICE/Win 2.oo, потужний відладчик від фірми NuMega. Деяким
людям він здається дуже складним у використанні, але я розповім Вам, як з ним управлятися і, я сподіваюся, Ви повірите мені. =) У додатку A я привів деяку
інформацію, яку Вам слід прочитати. p>
URL всі програми, які Вам знадобляться, наведені у додатку C. p>
- ED! SON, [email protected] p>
2. ПЕРЕГЛЯД SOFTICE/WIN 2.OO p>
Нижче
наведено дуже
схематичні малюнок, що демонструє вікно SoftICE:
| ---
|
--------------
Регістри
- |
| 'R' - правка значення регістрів
|
Вікно даних
| 'D' - перегляд пам'яті, 'E' - правка пам'яті
|
Вікно коду
| 'U' - перегляд коду за адресою, 'A' - вставка коду
|
Вікно команд
| Тут ви набираєте команди
Інші важливі клавіші (у стандартній настройці): p>
'H'/F1 - допомогу p>
F5/Ctrl + D - запуск програми (або продовження перерваного програми) p>
F8 - покрокова налагодження із заходом в тіло функції p>
F10 - покрокова налагодження без заходу в тіло функції p>
F11 - вийти з функції (буде працювати тільки до
перший PUSH у функції) p>
3. ПОШУК РЕЄСТРАЦІЙНИХ КОДІВ p>
Можливо, найкращий спосіб попрактикуватися - це знайти де-небудь шареварную (shareware) програмку і спробувати зареєструвати її. p>
3.1 Task Lock 3.00 - проста захист на основі серійного номера p>
Це дуже проста захист: номер не залежить ні від яких чинників. p>
3.1.1 Медичне обстеження p>
Який розрядності програма - 16 або 32 біт? Де вводиться реєстраційна інформація? Чи дасть мені довідка які-небудь
припущення про те, як влаштована реєстрація? Спробуйте відповісти на ці питання перед тим, як ми продовжимо. P>
.... Зараз Ви повинні бути зайняті обстеженням .... Ви зайняті обстеженням? ... Ну як, вже все ?... p>
OK, тепер Ви знаєте, що це 32-бітне додаток, що працює під p>
Windows 95 і що реєстрація полягає у заповненні реєстраційного номера в діалоговому вікні, що з'являється коли Ви
вибираєте меню "Register | Register ...". З довідки Вам також стало відомо, що існує два типи реєстрації: для індивідуального
використання і для використання в "конторі" (в оригіналі - site license). Тому дуже ймовірно, що в програмі буде ДВІ перевірки
реєстраційних кодів. p>
3.1.2 Переривання програми p>
Реєстраційні коди найчастіше вводяться в звичайних рядках введення типу Windows Edit. Щоб перевірити код, програма повинна
прочитати рядок введення за допомогою однієї з функцій: p>
16-біт 32-біт p>
------ ------ p>
GetWindowText GetWindowTextA, GetWindowTextW p>
GetDlgItemText GetDlgItemTextA, GetDlgItemTextW p>
Остання буква в назві 32-бітових функцій говорить про те, які рядки використовує ця функція: однобайтові або багатобайтових.
Багатобайтових рядка використовуються ДУЖЕ рідко. P>
Можливо, що Ви вже вловили мою думку. "Якщо б можна було перерватися за викликом GetWindowText ..." - І Ви МОЖЕТЕ це
зробити! Але спершу Ви повинні переконатися, що символьні імена (імена функцій) завантажені SoftICE'ом. Якщо Ви не знаєте, як це зробити - див. додаток A. p>
Щоб встановити "пастку" (насправді це називається точкою зупинки або брейкпоінтом) в SoftICE, Ви повинні зайти в
відладчик натисканням клавіш Ctrl-D і використовувати команду BPX. Як параметр команди можна використовувати або ім'я функції, або безпосередньо
адресу. Так як наш "об'єкт вивчення" (Task Lock) є 32-бітним додатком, ми повинні поставити брейкпоінт на функцію GetWindowTextA. Якщо це
не допоможе, спробуйте поставити брейкпоінт на інші функції. p>
У командному рядку SoftICE наберіть наступне: p>
: bpx getwindowtexta p>
Якщо Ви отримаєте повідомлення про помилку (наприклад, "No LDT"), переконайтеся, що в фоні у Вас не виконуються жодні інші
додатки. Я помітив, що Norton Commander в фоні є причиною такої поведінки SoftICE. P>
Ви можете перевірити наявність брейкпоінтов командою: p>
: bl p>
У результаті Ви побачите що-небудь типу: p>
00) BPX USER32! GetWindowTextA C = 01 p>
Щоб вийти з відладчика, натисніть Ctrl-D (або F5) ще раз. p>
Продовжимо ... Отже, Ви встановили брейкпоінт і тепер SoftICE буде "вискакувати" при кожному виклику функції GetWindowTextA.
Спробуємо ввести якесь значення у вікні реєстрації та натиснемо OK. Ви натискаєте OK ... ... і отримуєте дурне повідомлення про те, що Ваш код був
неправильним. Значить, це була не функція GetWindowTextA ... Спробуємо GetDlgItemTextA. Видалимо старий брейкпоінт: p>
: bc 0 p>
(0 - це номер брейкпоінта у списку брейкпоінтов) p>
І встановимо новий: p>
: bpx getdlgitemtexta p>
Ну що ж, спробуємо ще раз ... p>
3.1.3 У відладчик p>
Wow! Працює! Тепер ви в SoftICE, на самому початку функції GetDlgItemTextA. Щоб потрапити туди, звідки вона була викликана, натисніть
F11. Тепер Ви всередині модуля SGLSET.EXE. Якщо Ви не впевнені - подивіться на рядок між вікном коду і вікном командного рядка, вона має виглядати так: p>
---------- SGLSET!. text +1 B13 ---------- p>
Зараз ви вже можете заборонити реакцію на виклик функції: p>
: bd 0 p>
Якщо Вам раптом захочеться знову дозволити її, наберіть: p>
: be 0 p>
Перший рядок у вікні коду виглядає так: p>
CALL [USER32! GetDlgItemTextA] p>
Щоб побачити рядки над нею, натисніть Ctrl + Up ( "стрілка вгору") до тих пір, поки не побачите нижченаведений шматок
коду. Якщо Ви нічого не розумієте в Асемблері, я додав коментарі які можуть Вам допомогти. P>
RET; Кінець функції p>
PUSH EBP; Початок іншої функції p>
MOV EBP, ESP; ... p>
SUB ESP, 0000009C; ... p>
PUSH ESI; ... p>
> LEA EAX, [EBP-34]; EAX = EBP-34 p>
PUSH EDI; ... p>
MOVE ESI, ECX; ... p>
PUSH 32; Макс. довжина рядка p>
> PUSH EAX; Адреса текстового буферу p>
PUSH 000003F4; Ідентифікатор управління p>
PUSH DWORD PTR [ESI +1 C]; Ідентифікатор вікна діалогу p>
CALL [USER32! GetDlgItemTextA]; Отримати текст p>
Команди PUSH означають збереження значень для подальшого використання. p>
Я позначив важливі рядки символом '>'. Дивлячись на цей код, ми бачимо, що адреса текстового буферу зберігався в регістрі EAX і що
EAX був EBP-34h. Тому нам варто поглянути на EBP-34h: p>
: d ebp-34 p>
Ви повинні були побачити текст, який ви ввели в діалоговому вікні. Тепер ми повинні знайти місце, де Ваш номер порівнюється з
реальним серійним номером. Тому ми крок за кроком трассіруем програму за допомогою F10 до тих пір, поки не зустрінемо що-небудь про EBP-34. Не мине й кількох
секунд, як Ви наткнетеся на наступний код: p>
> LEA EAX, [EBP + FFFFFF64]; EAX = EBP-9C p>
LEA ECX, [EBP-34]; ECX = EBP-34 p>
PUSH EAX; Зберігає EAX p>
PUSH ECX; Зберігає ECX p>
> CALL 00403DD0; Викликає функцію p>
ADD ESP, 08; Видаляє збережену інформацію p>
TEST EAX, EAX; Перевіряє значення функції p>
JNZ 00402BC0; Стрибає, якщо не "нуль" p>
Мені здається, що це виглядає як виклик функції порівняння двох рядків. p>
Ця функція працює так: на вході - два рядки, на виході - 0, якщо вони рівні і будь-яке інше значаніе, якщо не рівні. p>
А навіщо програмі порівнювати якусь рядок з тією, що ви ввели у вікні діалогу? Та для того, щоб перевірити правильність Вашої
рядки (як Ви, можливо, вже здогадалися)! Так-так, значить цей номер ховався за адресою [EBP + FFFFFF64]? SoftICE не зовсім коректно працює з негативними
числами і тому цей адреса слід порахувати: p>
100000000 - FFFFFF64 = 9C p>
Ви можете зробити це обчислення прямо в SoftICE: p>
:? 0-FFFFFF64 p>
Число 100000000 занадто велике для SoftICE, а віднімання з 0 дає той же p>
самий результат. p>
Нарешті настав час подивитися, що ж ховається за адресою EBP-9C ... p>
: d ebp-9c p>
У вікні даних SoftICE Ви бачите довгу рядок цифр - це серійний номер! p>
Але Ви пам'ятаєте, що я говорив Вам раніше? Два типи реєстрації - два різних серійних номери. Тому після того, як Ви записали
на папірець перший серійний номер, продовжуйте трассіровать програму за допомогою F10. Ми дійшли до наступного шматка коду: p>
> LEA EAX, [EBP-68]; EAX = EBP-68 p>
LEA ECX, [EBP-34]; ECX = EBP-34 p>
PUSH EAX; Зберігає EAX p>
PUSH ECX; Зберігає ECX p>
> CALL 00403DD0; Знову викликає функцію p>
ADD ESP, 08; Видаляє збережену інформацію p>
TEST EAX, EAX; Перевіряє значення функції p>
JNZ 00402BFF; Стрибає якщо не "нуль" p>
І що Ви бачите за адресою EBP-68? Другий серійний номер! P>
: d ebp-68 p>
От і все ... Я сподіваюся, що у Вас все вийшло як доктор прописав? =) P>
3.2 Command Line 95 - легка реєстрація "ім'я-код", створення генератора ключів p>
Це програма - хороший приклад, з легким алгоритмом генерації коду. p>
3.1.1 "Обстеження" p>
Ви оглянули програму і побачили, що це 32-бітне додаток, що вимагає ім'я та код у вікні реєстрації. Поїхали! P>
3.1.2 Переривання програми p>
Ми чинимо так само, як і з Task Lock'ом - ставимо брейкпоінти. Можна навіть поставити відразу два брейкпоінта на найбільш імовірні
функції: GetWindowTextA і GetDlgItemTextA. Натисніть Ctrl-D, щоб викликати відладчик і наберіть у вікні команд: p>
: bpx getwindowtexta p>
: bpx getdlgitemtexta p>
Тепер повертайтеся в перервану програму, ідіть у вікно реєстрації і введіть ім'я і який-небудь номер (звичайне ціле число --
це найбільш ймовірний код). Я написав приблизно наступне: p>
Name: ED! SON '96 p>
Code: 12345 p>
Програма зупинилася на GetDlgItemTextA. Так само, як і у випадку з Task Lock'ом, ми натискаємо F11 щоб повернутися в зухвалу функцію.
Переглядаємо вікно коду за допомогою Ctrl + Up. Виклик функції виглядає так: p>
MOV ESI, [ESP +0 C] p>
PUSH 1E; Максимальна довжина p>
PUSH 0040A680; Адреса буфера p>
PUSH 000003ED; Ідентифікатор управління p>
PUSH ESI; Ідентифікатор вікна діалогу p>
CALL [User32! GetDlgItemTextA] p>
Число 40A680 здається нам цікавим, тому ми перевіряємо цю адресу: p>
: d 40a680 p>
Що ж видно у вікні даних, як не ім'я, яке ми ввели? =) А тепер поглянемо на шматок коду під вищенаведеним: p>
PUSH 00; (не цікаво) p>
PUSH 00; (не цікаво) p>
PUSH 000003F6; Ідентифікатор управління p>
MOV EDI, 0040A680; Адреса буфера p>
PUSH ESI; Ідентифікатор вікна діалогу p>
CALL [User32! GetDlgItemInt] p>
Функція GetDlgItemInt схожа на GetDlgItemTextA, але повертає рядок, а ціле число. Вона повертає його в регістрі EAX, тому
ми трассіруем цей код (F10) і дивимося, що ж у нас з'явилося у вікні регістрів після виклику функції ... У моєму випадку воно виглядає так: p>
EAX = 00003039 p>
А що таке шістнадцяткове 3039? Наберіть: p>
:? 3039 p>
І отримаємо наступне: p>
00003039 0000012345 "09" p>
^ hex dec ^ ^ ascii p>
Як Ви бачите (і, можливо, вже здогадалися) це код, який Ви ввели в діалоговому вікні. Ok, що тепер? Подивимося далі: p>
MOV [0040A548], EAX; Зберігає рег. код p>
MOV EDX, EAX; А також поміщає його в EDX p>
3.1.3 підрахунок реєстраційного коду p>
Ми досягли місця, де підраховується реальний реєстраційний код! p>
MOV ECX, FFFFFFFF; Ці рядки підраховують p>
SUB EAX, EAX; довжину рядка p>
REPNZ SCASB;. p>
NOT ECX;. p>
DEC ECX; ECX тепер містить довжину p>
MOVSX EAX, BYTE PTR [0040A680]; Отримує байт за адр. 40A680h p>
IMUL ECX, EAX; ECX = ECX * EAX p>
SHL ECX, 0A; Зрушення вліво на 0Ah біт p>
ADD ECX, 0002F8CC; Додає 2F8CC до результату p>
MOV [0040A664], ECX p>
... І де він перевіряється p>
CMP ECX, EDX; Порівнює числа p>
JZ 00402DA6; Стрибає, якщо рівні p>
Коли Ви дотрассіровалі до порівняння чисел, Ви можете подивитися, яким повинен був бути Ваш РЕАЛЬНИЙ реєстраційний код: p>
:? ecx p>
У моєму випадку це дало: p>
000DC0CC 0000901324 p>
Тобто, правильний код для мене: 901324. p>
Натиснемо F5 або Ctrl-D щоб повернутися в програму і спробуємо ще раз, але цього разу з правильним кодом (у десяткового формі).
Працює! P>
4. СТВОРЕННЯ генератора ключів ДЛЯ COMMAND LINE 95 p>
Погляньмо на алгоритм генерації коду і спробуємо перекласти його на мову Сі. Ось дуже проста формула, за якою підраховується
ключ: p>
code = ((uppercase_first_char * length_of_string) <<0x0A) + 0x2f8cc; p>
Зауваження # 1: Не слід забувати, що всі символи у вікні введення імені були приведені до верхнього регістру, тому ми повинні зробити
те саме. p>
Зауваження # 2: "<<0x0A" означає "умножніе на 2 в ступені 10" p>
Цілком програма на Сі виглядає так: p>
# include p>
# include p>
int main () p>
unsigned long code; p>
unsigned char buffer [0x1e]; p>
printf ( "CommandLine95 Keymaker by ED! SON '96n"); printf ( "Enter name:
"); p>
gets (buffer); p>
strupr (buffer); p>
code = (((unsigned long) buffer [0] * p>
(unsigned long) strlen (buffer)) p>
<<0x0A) + 0x2f8cc; p>
printf ( "Your code is:% lu", code); p>
return 0; p>
Приємних сновидінь! p>
4. ЯК ПРАЦЮЮТЬ PUSH І CALL КОЛИ ПРОГРАМА ВИКЛИКАЄ ФУНКЦІЮ p>
Знову
поглянемо
PUSH
PUSH
PUSH
PUSH
CALL
на шматок коду з Task Lock'а:
32
EAX
000003F4
DWORD PTR [ESI +1 C] [USER32! GetDlgItemTextA]
;
;
;
;
;
Макс. довжина рядка
Адреса текстового буферу
Ідентифікатор управління
Ідентифікатор вікна діалогу
Отримує текст
Коли Ви викликаєте функцію GetDlgItemTextA з програми на C, виклик виглядає так: p>
GetDlgItemTextA (hwndDlg, 0x3F4, buffer, 0x32); p>
^ [ESI +1 C] ^ EAX p>
PUSH зберігає дані в області пам'яті, званої стеком. В результаті кожного PUSH'а новий шматок даних міститься у верхівку стека і
потім викликається, перевіряє, що лежить в стеку і використовує ці дані на свій розсуд. p>
5. Про ПРОГРАМАХ НА VISUAL BASIC p>
EXE файли, вироблені Visual Basic'ом, не є справжніми EXE. Вони просто містять код для виклику VBRUNxxx.DLL, який потім
читає дані з EXE і виконує програму. Такий пристрій псевдо-EXE файлів є також причиною того, що програми на Visual Basic'е такі повільні. P>
А так як EXE файли не є справжніми EXE файлами, Ви не можете трассіровать і розбирання їх - Ви знайдете виклик
функції з DLL і купу сміття. І коли Ви будете трассіровать таку програму, Ви "заблукаєте" в DLL. P>
Вирішенням цієї проблеми є декомпілятор. Існує декомпілятор для програм, написаних на Visual Basic'е версій 2 і
3, створений кимось, що називає себе DoDi. Ця програма є шареварной і її можна знайти в InterNet'е (див. Додаток C). Для програм, написаних на
Visual Basic'е версії 4 (VB для Windows 95), не існує декомпілятора, наскільки мені відомо, хоча я б хотів, щоб він існував. =) p>
Примітка: Справжні програмісти на пишуть на Basic'е. =) P>
ПРОГРАМИ p>
A. ЯК У SOFTICE ЗАВАНТАЖУЙ символьні імена p>
Щоб перевірити, завантажив чи SoftICE символьні імена GetWindowText, Ви повинні ввійти в відладчик натисненням на клавіші Ctrl-D і у вікні
команд ввести наступне: p>
: exp getwindowtext p>
Якщо Ви не отримали список усіх функцій GetWindowText, Вам потрібно відредагувати файл SIW95WINICE.DAT, видаливши символ
коментаря (';') перед однією з рядків 'exp =', які слідують за текстом: "Examples of export symbols that can be included for chicago" в кінці
цього файлу. p>
Ви можете видалити коментарі з усіх рядків 'exp =' або зберегти трошки пам'яті, розкоментувати тільки рядки з файлами
kernel32.dll, user32.dll і gdi32.dll, які є найважливішими. Після цього Ви повинні перезапустити комп'ютер. P>
B. ВИКОРИСТАННЯ ДЕЯКИХ ФУНКЦІЙ p>
Вам буде легше зрозуміти, як викликаються функції, про які ми говорили, якщо Ви будете знати їх опису (декларації): p>
int GetWindowText (int windowhandle, char * buffer, int maxlen); p>
int GetDlgItemText (int dialoghandle, int controlid, char * buffer, int maxlen); int GetDlgItemInt (int dialoghandle, int controlid, int
* flag, int type); p>
Якщо Вам потрібна більш детальна інформація, то прочитайте документацію до програміста Windows/Win32. p>
C. ДЕ ЗНАЙТИ ПРОГРАМИ p>
ПРОГРАМИ ДЛЯ ЗЛОМУ p>
SoftICE/Win 2.oo: http://www.geocities.com/SoHo/2680/cracking.html Декомпілятор VB:
ftp://ftp.sn.no/user/balchen/vb/decompiler/ p>
ПРОГРАМИ, ВИКОРИСТАНІ У ЯК ПРИКЛАД p>
TaskLock: http://users.aol.com/Sajernigan/sgllck30.zip p>
CommandLine 95: ftp://ftp.winsite.com/pub/pc/win95/miscutil/cline95.zip p>
D. ЯК ЗВ'ЯЗАТИСЯ З АВТОРОМ p>
На IRC (EFNet): Канали # Ucf96, # Cracking p>
E-mail: [email protected] або [email protected] p>
На моїй WWW-сторінці: http://www.geocities.com/SoHo/2680/cracking.html p>