Форум   Статьи   Новости   Файлы   Bugtraq   Сниффер   Друзья   О Клубе

Последнее на Форуме

Пожертвования

Liberty Reserve: U9999024
Кошельки WebMoney:
Z583322939655
E121331800314
R274644017049
U349709454906


YM: 410011220120073

Пожертвовать

Контакты

Связь с Администрацией

hpcteam1[@]gmail.com

Статьи rss

[ Добавить Статью на сайт ]

Статьи / Безопасность / Реверсинг

Взлом Fant0m Crackmes №1,2,3,4

Всем добрового времени суток, с вами снова я, PsiBoX.
Теперь я расскажу вам о взломе 4 крэкмисов от Фантома. (скачать их можно по ссылке в конце статьи).

Эти крэкмисы предназначенны для новичков, только ступивших на нивы крекинга.
Начав свой путь в этой области, я тоже взламывал их все.

Несмотря на то, что они достаточно простые, у новичков зачастую возникает немало вопросов по поводу их взлома.
Мы с вами, шаг за шагом, последовательно разберем их взлом. Думаю, полученные вами знания помогут вам и при решении более трудных задач.
И, да, немаловажное замечание - знание основных команд ассемблера необходимо. Без этого вы наврядли поймете, о чем идет речь.

CrackMe №1


Итак, что нам понадобиться для этого КрекМи?
OllyDebugger или любой другой отладчик.
Автор хочет, чтобы мы нашли верный пароль для него.
В бонусном задании он просит пропатчить его для принятия любого пароля, будь он верный, или неверный.
Начнем с основного задания. Откроем Крэкми №1 в OllyDebugger'e.
Из задания мы знаем, что серийних задан жестко, поэтому поищем его в строках.
Щелкнем ПКМ по коду, выберем Search->All Referended Text Strings. Увидим такое окно, содержащее все строки программы.

Text strings referenced in CRACKME1:.text
Address    Disassembly                               Text string
00401000   PUSH 0                                    (Initial CPU selection)
0040106B   MOV DWORD PTR SS:[EBP-C],CRACKME1.004030  ASCII "MainMenu"
00401072   MOV DWORD PTR SS:[EBP-8],CRACKME1.004030  ASCII "DLGCLASS"
004010AA   PUSH CRACKME1.00403009                    ASCII "MainDialog"
004011B5   PUSH CRACKME1.00403014                    ASCII "AboutDialog"
0040128C   PUSH CRACKME1.00403029                    ASCII "m0tNaF-EmKCARc"
0040129D   PUSH CRACKME1.00403038                    ASCII "Check Status"
004012A2   PUSH CRACKME1.00403045                    ASCII "Wrong Password! Keep trying, you'll get it!"
004012B2   PUSH CRACKME1.00403038                    ASCII "Check Status"
004012B7   PUSH CRACKME1.00403071                    ASCII "You got it! Your now a cracker! :)"

По-моему, по адресу 40128C очень подозрительная строка. "cRACKmE-FaNt0m" задом наперед. Попробуем ее в качестве серийника.
Ура, заработало! Это и есть решение основной части. Теперь бонусное задание.
Нажмем Ctrl+N, найдем в появившимся окне функцию MessageBoxA (т.к. именно она показывает нам сообщение про верный\неверный серийный код. Щелкнем по функции правой кнопкой, нажмем "Set breakpoint on every refference"
Теперь запустим программу и введем что-нибудь в поле ввода, нажмем ОК и вывалимся на брэйкпоинт.

00401270  |.  68 00010000   PUSH 100                                 ; /Count = 100 (256.)
00401275  |.  68 9C304000   PUSH CRACKME1.0040309C                   ; |Buffer = CRACKME1.0040309C
0040127A  |.  68 E8030000   PUSH 3E8                                 ; |ControlID = 3E8 (1000.)
0040127F  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401282  |.  E8 6B000000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
00401287  |.  68 9C304000   PUSH CRACKME1.0040309C                   ; /String2 = ""
0040128C  |.  68 29304000   PUSH CRACKME1.00403029                   ; |String1 = "m0tNaF-EmKCARc"
00401291  |.  E8 BC000000   CALL <JMP.&KERNEL32.lstrcmpA>            ; \lstrcmpA  <----Это она!
00401296  |.  83F8 00       CMP EAX,0
00401299  |.  74 15         JE SHORT CRACKME1.004012B0
0040129B  |.  6A 30         PUSH 30                                  ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
0040129D  |.  68 38304000   PUSH CRACKME1.00403038                   ; |Title = "Check Status"
004012A2  |.  68 45304000   PUSH CRACKME1.00403045                   ; |Text = "Wrong Password! Keep trying, you'll get it!"
004012A7  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004012A9  |.  E8 5C000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004012AE  |.  EB 13         JMP SHORT CRACKME1.004012C3
004012B0  |>  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004012B2  |.  68 38304000   PUSH CRACKME1.00403038                   ; |Title = "Check Status"
004012B7  |.  68 71304000   PUSH CRACKME1.00403071                   ; |Text = "You got it! Your now a cracker! :)"
004012BC  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004012BE  |.  E8 47000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004012C3  |>  C9            LEAVE

Сразу над процедурами вывода сообщений можно увидеть функцию lstrcmpA, которая проверяет равенство друг строк (если равны, в EAX идет 0) Сразу за ней - сравнение EAX с 0. То что нужно для патчинга=). Ставим курсор на адрес 401296, жмем пробел, и вводим CMP EAX, EAX, не забыв поставить галку "Fill with NOP's". Готово! Теперь ЕАХ все время будет сравниваться сам с собой, а, как следствие, переход будет выполняться всегда. Можно было, однако, поступить по другому: вместо JE по адресу 00401299 мы могли ввести JMP, но такой путь не рекомендуется как ненадежный.
Теперь жмем ПКМ на коде, далее Copy To Exebutable->All modification, выбираем Copy All и в появившемся окне выбираем Save File и выбираем куда сохранить пропатченный файл.
Задача решена!

CrackMe №2


Тут автор предлагает нам избавиться от надоедливых Наг-скринов.
Опять таки, OllyDebugger нам в руки.
Бывает, что когда программа незарегистрированна, она выдает надоедливые напоминания. Большинство из них строятся по схожим принципам. Сейчас мы все подробно разберем, рассмотрим наиболее популярные варианты.
Хмм... Что мы видим чуть ниже точки входа? Это явно то сообщение, которое можно увидить, запустив программу вне отладчика...

004010BD  |.  FF75 14       PUSH DWORD PTR SS:[EBP+14]               ; /ShowState
004010C0  |.  FF75 B0       PUSH DWORD PTR SS:[EBP-50]               ; |hWnd
004010C3  |.  E8 F8010000   CALL <JMP.&USER32.ShowWindow>            ; \ShowWindow
004010C8  |.  FF75 B0       PUSH DWORD PTR SS:[EBP-50]               ; /hWnd
004010CB  |.  E8 FC010000   CALL <JMP.&USER32.UpdateWindow>          ; \UpdateWindow
004010D0  |.  6A 30         PUSH 30                                  ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004010D2  |.  68 33304000   PUSH CRACKME2.00403033                   ; |Title = "Remove me!"
004010D7  |.  68 3E304000   PUSH CRACKME2.0040303E                   ; |Text = "Nag Nag Nag... Remove me! Nag Nag Nag..."
004010DC  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
004010DE  |.  E8 C5010000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004010E3  |.  6A 00         PUSH 0                                   ; /lParam = NULL
004010E5  |.  68 10124000   PUSH CRACKME2.00401210                   ; |DlgProc = CRACKME2.00401210
004010EA  |.  FF75 B0       PUSH DWORD PTR SS:[EBP-50]               ; |hOwner
004010ED  |.  68 29304000   PUSH CRACKME2.00403029                   ; |pTemplate = "NAGDIALOG"
004010F2  |.  FF35 6C304000 PUSH DWORD PTR DS:[40306C]               ; |hInst = NULL
004010F8  |.  E8 87010000   CALL <JMP.&USER32.DialogBoxParamA>       ; \DialogBoxParamA

Просто уберем его...
По адресу 4010D0 нажимаем пробел (убедимся, что галка "Fill with NOP's" включена и вписываем в строку Assembly "NOP" (без кавычек), и повторяем, пока нопами не покроется вся функция, которая в отладчике отмечена черной рамкой (т.е. до адреса 004010E3).
Напомню, что NOP - ничего не делающий оператор, следовательно, окно не появиться.
Теперь жмем ПКМ на коде, далее Copy To Exebutable->All modification, выбираем Copy All и в появившемся окне выбираем Save File и выбираем куда сохранить пропатченный файл. Закрываем исходный файл и открываем пропатченный. Видите свою кучку NOP'ов? =)
Отлично, осталось только одно наг-окно, разберемся теперь с ним.
Мой наметанный взгляд определил, что это не MessageBox. Что же тогда? Диалоговое окно.
Потрассируем немножко программу с самого начала по F8. По адресу 401026 откроется и главное окно программы, и наг скрин. Чтож, я был прав...
Зайдем в функцию с помощью F7 и трассируем дальше. О, а вот это уже интересно, взгляните на участок после NOP'ов:

004010DA  |.  90            NOP
004010DB  |.  90            NOP
004010DC  |.  90            NOP
004010DD  |.  90            NOP
004010DE  |.  90            NOP
004010DF  |.  90            NOP
004010E0  |.  90            NOP
004010E1  |.  90            NOP
004010E2  |.  90            NOP
004010E3  |.  6A 00         PUSH 0                                   ; /lParam = NULL
004010E5  |.  68 10124000   PUSH CRACKME2.00401210                   ; |DlgProc = CRACKME2.00401210
004010EA  |.  FF75 B0       PUSH DWORD PTR SS:[EBP-50]               ; |hOwner
004010ED  |.  68 29304000   PUSH CRACKME2.00403029                   ; |pTemplate = "NAGDIALOG"
004010F2  |.  FF35 6C304000 PUSH DWORD PTR DS:[40306C]               ; |hInst = 00400000
004010F8  |.  E8 87010000   CALL <JMP.&USER32.DialogBoxParamA>       ; \DialogBoxParamA
004010FD  |>  6A 00         /PUSH 0                                  ; /MsgFilterMax = 0
004010FF  |.  6A 00         |PUSH 0                                  ; |MsgFilterMin = 0
00401101  |.  6A 00         |PUSH 0                                  ; |hWnd = NULL
00401103  |.  8D45 B4       |LEA EAX,DWORD PTR SS:[EBP-4C]           ; |
00401106  |.  50            |PUSH EAX                                ; |pMsg
00401107  |.  E8 8A010000   |CALL <JMP.&USER32.GetMessageA>          ; \GetMessageA
0040110C  |.  83F8 00       |CMP EAX,0

Комментарий неоднозначно указывает: "NAGDIALOG", мы нашли то, что искали)
По аналогии нопим функцию DialogBoxParamA (всю целиком, вместе с параметрами, это очень важно!) и сохраняем файл.
Теперь мы избавились от всех наг-окон, попробуйте запустить программу вне отладчика!
Автор просит написать патчер к данной программе в качестве бонуса, однако это выходит за румки данной статьи, поэтому мы это делать не будем. Просто работа с файлом, ничего сложного, более-менее разбирающиеся в программировании с легкостью напишут его.
Значит, переходим к следующей задаче...

CrackMe №3


Что у нас тут? Опа, CD Check, и ошибка...
А что в задании? Ага, патчим так, чтобы всегда выдавалось сообщение о том, что в сидюке есть диск.
Что у нас там для определения типа диска? Смотрим хелпы...
GetDriveTypeA. Возвращает 5, если сидюк в дисководе.
Ок, откроем программу в нашем любимом отладчике. Что тут у нас...
Жмем Ctrl+N и ищем GetDriveTypeA, далее ПКМ -> Set Breakpoint on every reference...
Запускаем и жмем CD Check. Вываливаемся на бряке.

004011FA  |.  6A 00         PUSH 0                                   ; /RootPathName = NULL
004011FC  |.  E8 99000000   CALL <JMP.&KERNEL32.GetDriveTypeA>       ; \GetDriveTypeA
00401201      83F8 05       CMP EAX,5
00401204  |.  74 17         JE SHORT CRACKME3.0040121D
00401206  |.  6A 30         PUSH 30                                  ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401208  |.  68 14304000   PUSH CRACKME3.00403014                   ; |Title = "FaNt0m's CrackMe #3 -- CD Check"
0040120D  |.  68 40304000   PUSH CRACKME3.00403040                   ; |Text = "Error finding CDROM"
00401212  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
00401214  |.  E8 51000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
00401219  |.  C9            LEAVE
0040121A  |.  C2 0400       RETN 4
0040121D  |>  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
0040121F  |.  68 14304000   PUSH CRACKME3.00403014                   ; |Title = "FaNt0m's CrackMe #3 -- CD Check"
00401224  |.  68 54304000   PUSH CRACKME3.00403054                   ; |Text = "Found a CDROM! Good job!"
00401229  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
0040122B  |.  E8 3A000000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
00401230  |.  C9            LEAVE
00401231  \.  C2 0400       RETN 4

По адресу 401201, сразу за функцией GetDriveTypeA, проверка, есть ли сидюк "CMP EAX,5". Патчим. Жмем пробел, пишем "CMP EAX,EAX" и жмем Assembly. Сохраняем файл, как я учил.
Все! Задача решена! Пробуем запускать файл вне отладчика, и все работает!
Много букв? Если не устали, то продолжим, иначе отложите чтение статьи и продолжим на свежую голову, ок?

CrackMe №4


Задача усложнятся. Теперь ключ к нему генерируется по введенному нами имени.
Вводим любые данные - вдим стандартный MessageBox. Опять таки, жмем Ctrl+N -> Set Breakpoint on every reference/
Запускаем, вводим что-либо. Я введу PsiBoX и 12345, так мне будет проще найти слова внутри отладчика.
Останавливаемся на брейкпоинте.
Кусок кода с брейкпоинтами:

00401205  |> \68 00010000   PUSH 100                                 ; /Count = 100 (256.)
0040120A  |.  68 84304000   PUSH CRACKME4.00403084                   ; |Buffer = CRACKME4.00403084
0040120F  |.  68 E8030000   PUSH 3E8                                 ; |ControlID = 3E8 (1000.)
00401214  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401217  |.  E8 62010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
0040121C  |.  68 00010000   PUSH 100                                 ; /Count = 100 (256.)
00401221  |.  68 84314000   PUSH CRACKME4.00403184                   ; |Buffer = CRACKME4.00403184
00401226  |.  68 E9030000   PUSH 3E9                                 ; |ControlID = 3E9 (1001.)
0040122B  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040122E  |.  E8 4B010000   CALL <JMP.&USER32.GetDlgItemTextA>       ; \GetDlgItemTextA
00401233  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]
00401236  |.  E8 BE000000   CALL CRACKME4.004012F9
0040123B  |.  83F8 00       CMP EAX,0
0040123E  |.  74 15         JE SHORT CRACKME4.00401255
00401240  |.  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401242  |.  68 29304000   PUSH CRACKME4.00403029                   ; |Title = "Check Serial"
00401247  |.  68 60304000   PUSH CRACKME4.00403060                   ; |Text = "You got it! Congrats! :)"
0040124C  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
0040124E  |.  E8 49010000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA      <- Бряк здесь
00401253  |.  EB 13         JMP SHORT CRACKME4.00401268
00401255  |>  6A 30         PUSH 30                                  ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401257  |.  68 29304000   PUSH CRACKME4.00403029                   ; |Title = "Check Serial"
0040125C  |.  68 36304000   PUSH CRACKME4.00403036                   ; |Text = "Wrong Serial! Keep trying, you'll get it!"
00401261  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
00401263  |.  E8 34010000   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA      <- Бряк здесь
00401268  |>  68 E8030000   PUSH 3E8                                 ; /ControlID = 3E8 (1000.)
0040126D  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401270  |.  E8 03010000   CALL <JMP.&USER32.GetDlgItem>            ; \GetDlgItem

По адресам 00401205 - 0040122E находятся 2 функции GetDlgItemTextA. Они получают значения, введенные наби в поля, и сохраняют их в буфер.
По адресу 0040123B идет сравнение регистра EAX с 0, а на строчку выше - очень подозрительная процедура.
Представьте себе алгоритм:
1)Считали данные из первого поля
2)Считали данные из второго поля
3)Вызвали некую функцию
4)Сравнили результат с нулем
5)Сделали выводы.

Функция, очевидно, преобразует имя (или пароль) и сравнивает их, возвращая в EAX ноль, если преобразованные строки равны.
Мы могли бы пропатчить место сравнения или переход, но мы углубимся внутрь функции и найдем верный серийный номер. Так будет разумнее и правильнее. Готовы?
Убираем все брейкпоинты, ставим бряк на 00401236 (то бишь, на нашу функцию) и перезапускаем программу.
Вводим что-нибудь в поля ввода, жмем ОК, оказываемся внутри отладчика. Входим в функцию по F7.

004012F9  /$  55            PUSH EBP
004012FA  |.  8BEC          MOV EBP,ESP
004012FC  |.  56            PUSH ESI
004012FD  |.  57            PUSH EDI
004012FE  |.  8D35 84304000 LEA ESI,DWORD PTR DS:[403084]
00401304  |.  8D3D 84324000 LEA EDI,DWORD PTR DS:[403284]
0040130A  |.  33C0          XOR EAX,EAX
0040130C  |.  33C9          XOR ECX,ECX
0040130E  |.  B3 1A         MOV BL,1A
00401310  |>  803E 00       /CMP BYTE PTR DS:[ESI],0
00401313  |.  74 15         |JE SHORT CRACKME4.0040132A
00401315  |.  8A06          |MOV AL,BYTE PTR DS:[ESI]
00401317  |.  02C1          |ADD AL,CL
00401319  |.  32C1          |XOR AL,CL
0040131B  |.  F6F3          |DIV BL
0040131D  |.  66:C1E8 08    |SHR AX,8
00401321  |.  04 41         |ADD AL,41
00401323  |.  8807          |MOV BYTE PTR DS:[EDI],AL
00401325  |.  47            |INC EDI
00401326  |.  46            |INC ESI
00401327  |.  41            |INC ECX
00401328  |.^ EB E6         \JMP SHORT CRACKME4.00401310
0040132A  |>  C607 00       MOV BYTE PTR DS:[EDI],0
0040132D  |.  33C0          XOR EAX,EAX
0040132F  |.  83F9 00       CMP ECX,0
00401332  |.  74 1A         JE SHORT CRACKME4.0040134E
00401334  |.  68 84324000   PUSH CRACKME4.00403284                   ; /String2 = ""
00401339  |.  68 84314000   PUSH CRACKME4.00403184                   ; |String1 = "12345"
0040133E  |.  E8 A1000000   CALL <JMP.&KERNEL32.lstrcmpA>            ; \lstrcmpA
00401343  |.  83F8 00       CMP EAX,0
00401346  |.  74 04         JE SHORT CRACKME4.0040134C
00401348  |.  33C0          XOR EAX,EAX
0040134A  |.  EB 02         JMP SHORT CRACKME4.0040134E
0040134C  |>  8BC1          MOV EAX,ECX
0040134E  |>  5F            POP EDI
0040134F  |.  5E            POP ESI
00401350  |.  C9            LEAVE
00401351  \.  C2 0400       RETN 4

Не пугайтесь, код только кажется громоздким. Вверху я привел весь код функции целиком.
С 004012F9 по 0040130E у нас подготовительные действия - введенный нами логин загружается в регистр EAX, в последней строке в регистр BL помещается значение 1A.
Далее, по адресам 00401310 - 00401328 идет непосредственно цикл обработки логина (Ага! Пароль остается неизменным!)
Вот что происходит с данными:
1)В AL помещается буква
2)К ней прибавляется значение из CL
3)Значение AL ксорится (xor) с CL
4)Знаение регистра EAX делится на BL
5)Значение AX (т.е. целая часть от пердыдущего деления) "сдвигается" вправо на 8 позиций.
6)К Al прибавляется 41
7)Все сохраняется по адресу, записанному в регистре EDI
8)Все повторяется для следующей буквы

Это кажется сложным, но нам вовсе не обязательно знать алгоритм, чтобы вытащить ключ.
Посмотрите на строки 00401334 - 0040133E!
Здесь то, что получилось в результате преобразований, сравнивают с нашим паролем, и если они оказываются равны, то функция через EAX вернер нам 0! Для ускорения процесса не трассируем руками (типичная повадка новичков), а ставим бряк после цикла (на 0040132A) и жмем F9 для запуска программы. Когда мы остановимся на брейкпоинте, по адресу 00403284 мы увидим наш ключ (его можно увидеть в комментарии отладчика по адресу 00401334).

00401334  |.  68 84324000   PUSH CRACKME4.00403284                   ; /String2 = "CNBSPK"  <--- Вот тут
00401339  |.  68 84314000   PUSH CRACKME4.00403184                   ; |String1 = "12345"
0040133E  |.  E8 A1000000   CALL <JMP.&KERNEL32.lstrcmpA>            ; \lstrcmpA

Поздравляю, вы сделали это! Для моего логина "PsiBoX" пароль оказался "CNBSPK"

Удачи вам во всех ваших начинаниях, и помните - ломать программы незаконно, все материалы предоставлены исключительно в ознакомительных целях.

Скачать крекми 1 - 4 вы можете здесь
Тема для обсуждения

Автор: PsiBoX

Источник: hpc.name

Материал добавил PsiBoX


Комментарии(0)

Дата: 2011-11-16 13:30:49

Добавить Комментарий к Материалу

Вы должны быть авторизованы на форуме чтобы добавлять комментарии. Регистрация Уже авторизованы?

Комментариев к материалу пока нет.

Последнее на Сайте

Новости

Статьи

Bugtraq

Файлы

Copyright © 2008 - 2017 «HPC». При копировании материалов ставьте ссылку на источник.
Все материалы представлены только в ознакомительных целях, администрация за их использование ответственности не несет.
Пользовательское соглашение Реклама на сайте