Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

APISpy32 v2.5 - в помощь крэкеру (регистрация и доработка )

Обсудить статью на форуме

Массу крэкерских инструментов, видеоуроков и статей вы сможете найти на видеокурсе от нашего сайта. Подробнее здесь.

Автор: Ara <ara86@inbox.ru>

Используемые инструменты:

- OllyDbg 1.10;
- SoftIce 4.05;
- HIEW;
- PETools v1.5;
- ImportReconstructor v. 1.6 Final
- PEiD (не обязательно)

Вступление

Программа ApiSpy32 позволяет просматривать вызовы всех известных API функций загружаемой
программы, показывает адрес вызова, сохраняет список функций в лог-файл. Можно указать,за какими именно
функциями нужно следить. Удобна для сравнения работы исходной и измененной программ (например, место проверки CRC
находится довольно быстро).Вообщем, может реально помочь в трудных местах взлома других прог. К сожалению, сайт, указанный в HELPe
ApiSpy, я не нашел, но наверняка она есть на других сайтах. Размер установочного файла 226 Кб.

Начнем с обследования.При запуске-НАГ с надписью UNGERISTERED. В заголовке окна проги - тоже самое. Unregistered версия имеет ограничения на длину лог-файла и это очень неудобно в работе :-(
Регистрация требует имя и рег.номер. Откроем APISpy с помощью PEid и видим:
- PEtite 1.2 -> Ian Luck
Файлик запакован, будем снимать пакер.

Распаковка
Распаковка этого пакера ничем ни отличается от распаковки UPX,ранних версий AsPack и иже с ними.
Поэтому заострять внимание на распаковке не буду (есть статьи,специально посвященные распаковке),
покажу только нахождение ОЕР (пригодится для написания патча)
Как основной отладчик я использовал OllyDbg, а SoftIce применял для нахождения адресов вызовов API функций.
Можно бало бы для нахождения адресов использовать APISpy, но саму себя она исследовать не хочет, да и хочет быть запущенной
в одном экземпляре. Итак, откроем Apis32.exe в Olly. Если попытаться пройти немного по F8, то на первом же Call’e
прога вылетит. Поэтому зайдем в Call по F7.Если чуть потрейсим по F8 (чтобы пройти процесс распаковки), то попадем сюда:



004195D2 JMP apis32.00406360 <---- JMP OEP
004195D7 JMP apis32.00407937

Прыгаем на OEP (406360),жмем Ctrl+А. На OEP очень даже похоже, поэтому делаем дамп (я использовал PETools)
восстанавливаем импорт с помощью ImpRec, не забывая прописать найденный ОЕР. Если теперь наш дамп запускается,
значит все сделано верно!

Регистрация программы

Для определения адреса функции получения имени и рег.кода используем SoftIce. Ставим брекпойнты на две функции:

bpx GetWindowTextA
bpx GetDlgItemTextA

вводим имя и рег.номер на удачу. У меня
Name: Ara
Reg.Key: 112233
жмем ОК и вываливаемся в айс. Пару раз F12 и мы тут:

=====4051f7 Call ebx --> Call GetDlgItemTextA

Смотрим, что ЕАХ=3(функия возвращает кол-во считанных байт)=>считано Name
Чуть ниже берется ключ.

=====40522е Call ebx

Далее я работал в Olly. В принципе я почти всегда пользую Олю (суперотладчик-ИМХО):-)
Загружаем в Олю прогу и ставим бряк (F2) на адрес 40522е (Сall ebx). Запускаем (F9), вводим имя и код еще раз,
ОК и останавливаемся на ВР!

В следующем Сall имя и пароль без проверки сразу сохраняются в реестре (можно посмотреть кому интересно, если по F7 зайти).
Далее Call EndDialog закрывает диалог регистрации, но нам это не интересно, нужно искать проверку кода.
Поэтому идем по F8 и попадаем в user32, жмем F8 пока не вернемся в нашу прогу.
Видим, что возвратились после выполнения Call DialogBoxParam. Эта функция возвращает результат выполнения EndDialog
(ее мы еже видели). Попадаем сюда:

00401871 CALL DWORD PTR DS:[<&user32.DialogBoxPara>; DialogBoxParamA
00401877 TEST EAX,EAX
00401879 JE Dumped_.004019B8
0040187F PUSH Dumped_.0040A030
00401884 PUSH Dumped_.0040C780
00401889 CALL DWORD PTR DS:[<&kernel32.lstrcpy>]
0040188F PUSH Dumped_.0040A044
00401894 PUSH Dumped_.0040C780
00401899 CALL DWORD PTR DS:[<&kernel32.lstrcat>]
0040189F PUSH Dumped_.0040A35C
004018A4 PUSH Dumped_.0040C780
004018A9 CALL DWORD PTR DS:[<&kernel32.lstrcat>]
004018AF CALL Dumped_.00405040 <--------- Проверка кода
004018B4 MOV DWORD PTR DS:[40C34C],EAX
004018B9 JMP SHORT Dumped_.004018BC
004018BB ...
004018BC OR AL,AL
004018BE JE SHORT Dumped_.004018C2
004018C0 JMP SHORT Dumped_.004018EE
004018C2 MOV EDI,Dumped_.0040A0FC
004018C7 MOV EDX,Dumped_.0040C780

Видим,что идут операции со строками (для заголовка, для About...)-нам не интересно.
Зато интересна процедурка по адресу 4018AF, т.к. далее мы видим, что готовится сообщение The registration information you provided is incorrect
Прога уйдет мы туда, если выполнится JE по адресу 4018BE.(еах=0)
Если немного потрейсить, мы это сообщение и увидим!
Поэтому трейсить не будем, а занопим переход JE,жмем F9 и видим сообщение:Thanks for registering!!!
Ура, ма ее сломали!!
Меняем 74 02 на 90 90 в любом редакторе(не забывая сделать копию файла-на всякий случай) и запускаем! Но что это?
Опять UNREGISTERED!Повторим регистрацию, прога скажет спасибо, но при перезапуске регистрированной себя не считает.
Да и если About глянуть, тоже самое.
Так что все заново :-((
Зато теперь мы знаем, где проверяется введенный код
Восстанавливаем файл-не зря копию делали)
Ставим ВР на 4018AF и регистрируемся.В Call заходим по F7 - здесь и будем копать.
Смотрим, что делает первый-же Call.
А он читает записанный в реестр код и возвращает его длину.

00405056 ADD ESP,0C
00405059 CMP EAX,10
0040505C JGE SHORT Dumped_.00405066

Затем сравнивает длину с 10h (16 символов)
Если меньше, обнуляет еах и возврат из процедуры (EAX=0, а мы помним, что нам нужен НЕ ноль)
Чуть ниже:

00405068 PUSH Dumped_.0040C3C0 ; ASCII "Ara"
0040506D PUSH Dumped_.0040A678 ; ASCII "UserName"
00405072 CALL Dumped_.00405370
00405077 ADD ESP,0C
0040507A CMP EAX,5
0040507D JGE SHORT Dumped_.00405087

Тоже самое с Name.
Теперь мы знаем, что Name должно быть не менее 5 символов, а код - не менее 16
Заново регистрируемся, только теперь типа
Name: Ara_Crack
Key: 1234567890123456
Заходим в процедуру, проходим проверку длины и смотрим, как модифицируются наши данные.
Смотрим не очень внимательно, обратим внимание на место перед выходом из процедуры:
004051BB XOR EAX,EAX
004051BD POP EDI
004051BE TEST EBP,EBP
004051C0 POP ESI
004051C1 POP EBP
004051C2 SETE AL
004051C5 POP EBX
004051C6 POP ECX
004051C7 RETN

Что же мы видим: как бы наши коды не проверялись, по адресу 4051BB EAX все равно ставится в ноль!
Но ниже есть SETE AL. Эта команда устаналивает операнд (в нашем случае AL) в 01, если флаг Z равен 1
и в 00, eсли наоборот.Выяснять, где меняется флаг нуля, мы не будем.
Вместо SETE AL пишем
mov al,1
nop
Проверяем - все рулит, мы зарегили APISpy!

Доработка программы (пункт необязательный)

Все, теперь мы владельцы зарегистрированной версии APISpy. Проверим ее работу на любом .ехе файле.
Сохраним лог-файл работы и откроем его в Блокноте. Увидим, что в логе по несколько вызовов записывается
в одной строке, что очень неудобно. Сперва я решил написать на Делфи программку, которая исправляла бы лог
в читабельную форму. Потом передумал и решил немного доработать сам APISpy.И как оказалось-зря. Когда уже все было
сделано, я зачем-то решил открыть лог в Ворде и увидел нормальный ровный текст. Как говорится, дурная голова рукам покоя не дает.
Ну да ладно, зато разберемся, что здесь к чему. Опять используем SoftIce. Для открытия или создания нового файла используется
функция CreateFile. На нее и поставим в айсе бряк. Пробуем сохранить лог какой-нибудь проги и вылетаем в айс.


405967 Call CreateFileA
В Olly поставим бряк на адрес 405967, загрузим APISpy и сохраним лог какого-нибудь файла.
Сработает ВР и смотрим, как формируются строки лог-файла.
Сначала формируется заголовок лога, нас интересует немного другое:
Видим цикл:

00405772 MOV ECX,DWORD PTR SS:[EBP-C]
00405775 ADD ECX,1
00405778 MOV DWORD PTR SS:[EBP-C],ECX
0040577B MOV EDX,DWORD PTR SS:[EBP-C]
0040577E CMP EDX,DWORD PTR SS:[EBP-8]
00405781 JGE Dumped_.00405808
00405787 PUSH Dumped_.0040AF20 <----- Адрес, куда заносится одна строка API
0040578C MOV EAX,DWORD PTR SS:[EBP-C]
0040578F PUSH EAX
00405790 PUSH 189
00405795 MOV ECX,DWORD PTR DS:[40ADB4] |
0040579B PUSH ECX
0040579C CALL DWORD PTR DS:[<&user32.SendMessage><---- Получаем строку
004057A2 PUSH Dumped_.0040AF20
....................................................
....................................................

004057D9 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[esi]
004057DB MOV ECX,EBX
004057DD AND ECX,3
004057E0 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] <-----Вставляем в конец строки разделитель
004057E2 MOV EDI,Dumped_.0040AF20

004057E7 OR ECX,FFFFFFFF
004057EA XOR EAX,EAX
004057EC REPNE SCAS BYTE PTR ES:[EDI]
004057EE NOT ECX
004057F0 ADD ECX,-1
004057F3 PUSH ECX
004057F4 PUSH Dumped_.0040AF20
004057F9 MOV EAX,DWORD PTR SS:[EBP-4]
004057FC PUSH EAX
004057FD CALL DWORD PTR DS:[<&kernel32._hwrite>] <---- Сохраняем строку в файл
00405803 JMP Dumped_.00405772

Если открыть любой файл .txt в 16-ричном редакторе, то можно посмотреть-перед новой строкой стоят 0D0A
Значит, нам надо заменить разделитель, используемый программой (0А) на символ перевода строки (0D)
Смотрим значение esi по адресу 4057Е0: esi=0040А750
По этому адресу лежит 0А-разделитель строк!
Вставляем в редакторе вместо 0А---->0D0A
Запускаем прогу, выбираем любой файл, сохраняем лог и смотрим, что каждый вызов- в отдельной строке!

Вставка патча в запакованную прогу

Теперь будем писать патч. И вставим его в запакованную прогу.
Смысл такого патча должен быть понятен-даем запаковщику распаковать прогу, а вместо
перехода на OEP переходим на наш патч, патчим где надо и возвращаемся на OEP.
Начали!Находим пустое место в файле(где много нулей).Я сразу не нашел, поэтому решил писать патч в заголовок файла и начал с адреса 00400041
Идея впихать патч в заголовок файла позаимствована у -=Alex=- из статьи про взлом CrackMe2.
Патч: mov word ptr[004051c2],01b0 --->mov al,1
mov byte ptr[004051C4],90 --->nop
mov word ptr[0040A750],0a0d --->разделитель строк
jmp 406360 --->jmp oep


Когда осуществляется переход на OEP, мы нашли в ходе распаковки
004195D2 JMP apis32.00406360 <---- JMP OEP
004195D7 JMP apis32.00407937

Меняем JMP 406360 на JMP 400041(адрес, куда писали патч)
Запускаем запакованный файл с патчем - все ОК!

Еще можно сделать, чтобы регистрация принимала имя и код любого размера,
но это уже придется делать вам самим!


Заключение

В заключении хотел бы отметить отдельно -=Alex’a=- за идею размещения патча и всех ребят с CrackLab.ru
Данная статья расчитана на начинающего крекера, были затронуты вопросы распаковки, нахождения проверки пароля и
встраивания патча в запакованный файл. От продвинутых хотелось бы услышать мнение о самой программе, пользуется ли ей кто-нибудь,
т.к. ранее в статьях, мной прочитанных, о ней не упоминалось!
Если данная программа кому-то пригодилась во взломе, замыльте пару строк.
При использовании и указании инструментов руководствовался только своими привычками, так что на вкус и цвет товарища нет.

____________________________________________________________________________________________________________________
Ara Ltd. ara86@inbox.ru 2004г.


Обсуждение статьи: APISpy32 v2.5 - в помощь крэкеру (регистрация и доработка ) >>>


Комментарии к статье: APISpy32 v2.5 - в помощь крэкеру (регистрация и доработка )

-= ALEX =- 24.06.2004 19:15:01
Спасибо.
---
Potoplazma 08.12.2004 06:35:56
Кул ! чётко и доходчиво ! Только щас наконецто крякнул этот апыспи благодаря этой статте! Кстати я думал что только я вишу на Олле дбг :)
---

Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS