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