Тема: Solutions
Показать сообщение отдельно

..::[FaTmiKE 2oo5]::.. CrackMe #2
  #2  
Старый 09.01.2007, 23:49
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

Репутация: 1077
По умолчанию ..::[FaTmiKE 2oo5]::.. CrackMe #2


CrackMe: ..::[FaTmiKE 2oo5]::.. CrackMe #2
Цель: закейгенить
Сложность: легко
Коментарий: KeyGen писать не будем, только найдём способ генерации.
link: http://www.crackmes.de/archive/
Решение:

Обходим упаковщик, тк распаковка не воходит в наши планы. Так и не посмотрел какой но судя по pusha - popa - UPX.

Два способа обхода этого препятствия:

f8 > hr esp > run > hd esp
или
Ctrl-F > popa > f2 > f9 > f2 > f8

В первую очередь пореверим крякмис на возможность String Reference взлома. Другими словами пороверим наличие в открытом виде таких строк, как "Registred", "good","sucsessfull","Cool","Xaker","Cracker","pas sword". Для этого жмём F10 (эквивалент нажатия на правую клавишу), Search for > All referenced text strings. Ничего полезного((!

Поищем функции ввода, вывода, и проставим бряки. Для этого в command bar'е наберём "bpx MessageBoxA". Перед нами предстали все апи. Но MessageBoxA и GetWindowTextA среди них нет. Но где то они вызываться должны!! С этими словами, я полез в Executable modules(Alt-E). Выбираем user32.dll, тк именно там храняться интересующие нас функции, и Ctrl-N. Ищем MessageBoxA, enter (входим в функцию). Ставим бряк на retn 10. Почему? Вдруг автору крякми вздумается украсть пару байт или проверить первый байт на присутствие int 3 (это breackpoint F2, можно так сказать). F9.

Вводим что-нибудь и жмём "Go!". Вылетает сообщение, о необходимости регистрации. Жмём Ok и брякаемся на retn 10. F8 и мы вновь в программе. Поднимимся немного выше. Что то маловато кода. Только функции зашифровки/расшифровки текста и MessageBoxA.

Код:
004018E0   3E:8B0D 78924000 MOV ECX,DWORD PTR DS:[409278]            ; Crackme2.004010F0
004018E7   FFD1             CALL ECX
004018E9   3E:8B0D 80924000 MOV ECX,DWORD PTR DS:[409280]            ; Crackme2.00401290
004018F0   FFD1             CALL ECX
004018F2   A1 4C924000      MOV EAX,DWORD PTR DS:[40924C]
004018F7   6A 40            PUSH 40
004018F9   68 0C924000      PUSH Crackme2.0040920C                   ; ASCII "Information"
004018FE   68 10904000      PUSH Crackme2.00409010                   ; ASCII "This function is only available in the registered version!"
00401903   50               PUSH EAX
00401904   3E:8B0D 68924000 MOV ECX,DWORD PTR DS:[409268]            ; Crackme2.004080B8
0040190B   3E:FF11          CALL DWORD PTR DS:[ECX]
0040190E   3E:8B0D 78924000 MOV ECX,DWORD PTR DS:[409278]            ; Crackme2.004010F0
00401915   FFD1             CALL ECX
00401917   3E:8B0D 80924000 MOV ECX,DWORD PTR DS:[409280]            ; Crackme2.00401290
0040191E   FFD1             CALL ECX
00401920   C3               RETN
Чтож мы пойдём другим путём. Перезапустим программу и доберёмся до точки входа, вобщем опять обходим упаковщик.

Проскроллируем ниже, поищем функцию GetModuleHandleA.

Код:
00407006   FF15 14804000    CALL DWORD PTR DS:[408014]               ; kernel32.GetModuleHandleA
0040700C   50               PUSH EAX
0040700D   E8 8EA3FFFF      CALL Crackme2.004013A0
После GetModuleHandleA ничего нет, зато идёт функция CALL Crackme2.004013A0 в которой наверняка всё и спрятанно. Заходим в неё.

Вот и то, что мы искали:
Код:
004013E9   6A 00            PUSH 0
004013EB   68 50144000      PUSH Crackme2.00401450
004013F0   6A 00            PUSH 0
004013F2   6A 65            PUSH 65
004013F4   50               PUSH EAX
004013F5   FF15 A8804000    CALL DWORD PTR DS:[4080A8]               ; USER32.DialogBoxParamA
push NULL
push ADDR DlgProc
push NULL
push ADDR DlgName
push hInstance
call DialogBoxParam

или более привычный для меня вариант

invoke DialogBoxParam, hInstance, ADDR DlgName,NULL,addr DlgProc,NULL

Нам нужен адрес функции диалогового окна, DlgProc равный, в нашем случае, 00401450. Отправляемся по нему, Ctrl-G > 00401450.

Вот она, DlgProc, во всей красе.

Код:
00401450   55               PUSH EBP                                 ; DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
00401451   8BEC             MOV EBP,ESP
00401453   83EC 68          SUB ESP,c68
00401456   8B45 0C          MOV EAX,DWORD PTR SS:[EBP+C]             ; eax <- uMsg
00401459   53               PUSH EBX
0040145A   56               PUSH ESI
0040145B   83E8 10          SUB EAX,10
0040145E   57               PUSH EDI
0040145F   0F84 BC020000    JE Crackme2.00401721			   ; WM_CLOSE
00401465   2D 00010000      SUB EAX,100
0040146A   0F84 22020000    JE Crackme2.00401692			   ; WM_INITDIALOG
00401470   48               DEC EAX
00401471   74 0B            JE SHORT Crackme2.0040147E		   ; WM_COMMAND
00401473   33C0             XOR EAX,EAX
00401475   5F               POP EDI
00401476   5E               POP ESI
00401477   5B               POP EBX
00401478   8BE5             MOV ESP,EBP
0040147A   5D               POP EBP
0040147B   C2 1000          RETN 10                                  ; DlgProc endp
Протрссировав функцию, я определил
Код:
0040145F   0F84 BC020000    JE Crackme2.00401721			; WM_CLOSE
переходом в случаее, получения uMsg равного WM_CLOSE.

Код:
0040146A   0F84 22020000    JE Crackme2.00401692			; WM_INITDIALOG
переходом в случаее, получения uMsg равного WM_INITDIALOG

WM_*** - сообщения от Windows, которые должна обработать DlgProc.

Код:
WM_CLOSE                             equ 10h
WM_INITDIALOG                        equ 110h
WM_COMMAND                           equ 111h
Нас интересует случай когда uMsg равен WM_COMMAND (обработка сообщений нажатия на кнопку, открытия меню и тп).

mov eax,wParam
wParam - ID кнопки, меню и тп.

Код:
0040147E   8B45 10          MOV EAX,DWORD PTR SS:[EBP+10]
Равняем по 3e8h (1000d).
Код:
00401481   05 18FCFFFF      ADD EAX,-3E8
Делаем вывод, что ID кнопок от 1000 до 1009 тк дальше идёт проверка.
Код:
00401486   83F8 09          CMP EAX,9
00401489   0F87 F8010000    JA Crackme2.00401687
Код:
0040148F   33C9             XOR ECX,ECX
00401491   8A88 58174000    MOV CL,BYTE PTR DS:[EAX+401758]
00401497   FF248D 44174000  JMP DWORD PTR DS:[ECX*4+401744]
ecx*4+xxxxxxxx =)), видимо где то харнятся адреса меток по которым подаётся управление. Но нас это не интересует.

Ставим бряк на jmp и жмём f9. Вводим вместо имени и пароля 01234, 56789 соответсвенно. Для удобства все символы разные. Посмотрим, что делается после нажатия "Go!". Мы попадаем на функцию.

Код:
004014E3   FF15 58924000    CALL DWORD PTR DS:[409258]               ; Crackme2.004018E0
Зайдем в неё, Enter. Чтож это мы уже видели. F9. Теперь попробуем нажать Registred. Брякаемся на всё том же прыжке и переходим по нему.

Чтож трейсим)). Ниже встречаются вызовы GetDlgItemTextA. Введёные слова записываются в стек. После второй GetDlgItemTextA встречаем:

Код:
0040154C   837D 10 13       CMP DWORD PTR SS:[EBP+10],13
00401550   0F85 31010000    JNZ Crackme2.00401687
Из чего можно сделать вывод, что символов в пароле должо быть 19, тк по ebp+10 хранится размер введёного пароля. Чтож жмём f9 и меняем пароль на 0123456789123456789. И идём дальше.

Код:
00401556   8A0D 1C924000    MOV CL,BYTE PTR DS:[40921C]
0040155C   B0 2D            MOV AL,2D
0040155E   3AC8             CMP CL,AL
00401560   0F85 21010000    JNZ Crackme2.00401687

AL=2D ('-')
CL=34 ('4')
Из чего можно сделать вывод, что через каждые 4 символа должнен быть "-". Меняем пароль на 0123-4567-8912-3456.

Проходим проверки, всё гуд)). Трейсим!! Дальше нам встречается цикл:
Код:
00401592   0FBE4C05 98      MOVSX ECX,BYTE PTR SS:[EBP+EAX-68]
00401597   03F1             ADD ESI,ECX
00401599   40               INC EAX
0040159A   3BC2             CMP EAX,EDX
0040159C  ^7C F4            JL SHORT Crackme2.00401592
Суммируются некоторые символы.
И умноножение на некое DEADBEFF.
Код:
0040159E   69F6 EFBEADDE    IMUL ESI,ESI,DEADBEEF
В esi остаётся своеобразный хэш. Числа будут совпадать не так часто, а число будет строго определённого формата, так что, можно назвать и хэшем.

Код:
004015A4   8975 0C          MOV DWORD PTR SS:[EBP+C],ESI
004015A7   8B15 44914000    MOV EDX,DWORD PTR DS:[409144]            ; Crackme2.004091A4
004015AD   FF75 0C          PUSH DWORD PTR SS:[EBP+C]
004015B0   8D85 CCFFFFFF    LEA EAX,DWORD PTR SS:[EBP-34]
004015B6   52               PUSH EDX
004015B7   50               PUSH EAX
004015B8   3E:8B0D 74924000 MOV ECX,DWORD PTR DS:[409274]            ; Crackme2.004080C0
004015BF   3E:FF11          CALL DWORD PTR DS:[ECX]
Можно распознать как:

Код:
push 75AC7566	; - наш "хэш"))
push "%X"	; Unsigned hexadecimal integer
push 0012FA38	; Буфеp для пpиема отфоpматиpованных символов
CALL wsprintfA
Вобщем эта функция переводит наше hex-число в ASUII строку.

Код:
004015C5   8A55 CC          MOV DL,BYTE PTR SS:[EBP-34]
004015C8   A0 19924000      MOV AL,BYTE PTR DS:[409219]
004015CD   3AD0             CMP DL,AL
004015CF   0F85 B2000000    JNZ Crackme2.00401687
...
...
0040162B   8A45 D3          MOV AL,BYTE PTR SS:[EBP-2D]
0040162E   8A0D 29924000    MOV CL,BYTE PTR DS:[409229]
00401634   3AC1             CMP AL,CL
00401636   75 4F            JNZ SHORT Crackme2.00401687
Судя по представленному выше коду в пароле нужно заменить 12 на 75, 56 на AC, 91 на 75, 45 на 66.
Формируем новый пароль a75b-cACd-e75f-g66h. Ну ещё добавил ab cd ef gh для наглядности. Хотя вместо них можно поставить что угодно.

Пробуем пароль. Попадаем в ольку, проходим все прверки. Дальше идут функции GetDlgItem, EnableWindow.

Код:
ControlID = 3EF (1007.)
hWnd = 0048061C ('..::[FaTmiKE 2oo5]::..',class='#32770')
CALL GetDlgItem

Enable = FALSE
hWnd = 00460798 (class='Edit',parent=0044061C)
CALL EnableWindow
Что значит дезактивация поля. Идём до конца. Нам несколько раз встречаются EnableWindow, что придаёт нам уверенности в правильном ответе)). Жмём F9. И переходим к нашей программе.Поля и кнопка регистрации, как я сказал больше не активны.

Момент истины, барабанная дробь)). Жмём "Go!". Мдя... Только для зарегестрированных пользователей! Крякмис всётаки не хочет нас таковыми считать)))!

Придётся перезапускаться. Ставим старые breackpoint'ы. Вводим старые имя и пароль. Проходим проверки. И вот, что мы проглядели:
Код:
0040164D   890D 58924000    MOV DWORD PTR DS:[409258],ECX
Ничего не напоминает? А как вам этот адресок?
Код:
004014E3   FF15 58924000    CALL DWORD PTR DS:[409258]               ; Crackme2.004018E0
По ходу автор меняет адрес функции вывода о необходимости регистрации новым адресом. Тогда всё понятно)). Пробуем опять нажать "Go!". Вновь брякаемся на jmp. Заходим.

Код:
004014E3   FF15 58924000    CALL DWORD PTR DS:[409258]               ; Crackme2.004012B0
Как мы и предполагали, содержимое 409258 поменялось на 004012B0.

Код:
004012B0   55               PUSH EBP
004012B1   8BEC             MOV EBP,ESP
004012B3   83EC 10          SUB ESP,10
004012B6   53               PUSH EBX
004012B7   56               PUSH ESI
Что то новое)). Сотрим!!

Код:
004012B9   0FBE05 18924000  MOVSX EAX,BYTE PTR DS:[409218]
004012C0   8945 FC          MOV DWORD PTR SS:[EBP-4],EAX
...
004012F6   C1E0 08          SHL EAX,8
004012F9   8945 F8          MOV DWORD PTR SS:[EBP-8],EAX
004012FC   8B4D FC          MOV ECX,DWORD PTR SS:[EBP-4]
004012FF   0B4D F4          OR ECX,DWORD PTR SS:[EBP-C]
00401302   0B4D F8          OR ECX,DWORD PTR SS:[EBP-8]
00401305   0B4D F0          OR ECX,DWORD PTR SS:[EBP-10]
Программа раскладывает наши ab cd по регисистрам, кладёт в стек значения, сдвигает значения на 8, 10, 18 влево. В результате, получая что то вроде этого:

xx000000
00yy0000
0000zz00
000000uu

Затем с помощью or собирает всё в один регистр ecx
xxyyzzuu

в нашем случае:
ECX 61626364 или abcd

ECX сохраняется и тоже самое проделывается с efgh. Далее идёт некая функция зайдём в неё.

Код:
00401115   8B15 48914000    MOV EDX,DWORD PTR DS:[409148]
По 409148 судя по всему какаято функция, в ecx попадает те самые abcd
Код:
00401124   33D1             XOR EDX,ECX
РасXORивается значение некой функции и записывается наместо
Код:
0040112C   8915 48914000    MOV DWORD PTR DS:[409148],EDX
Следующий байт рахоривается по efgh и тд. Встаёт законный вопрос. Где тогда узнать abcdefgh. На это у меня один ответ. Если не устанавливается seh-обработчик, то скорее всего автор сам узнает о правильности прохореных команд. Ничего не остаётся как идти дальше. Выйдя из этой функции мы встречаем ещё одну. В которой расположены следующие строки.

Код:
00401776   813D 98914000 E8>CMP DWORD PTR DS:[409198],97BE8
00401780   0F85 32010000    JNZ Crackme2.004018B8
00401786   813D 5C914000 FF>CMP DWORD PTR DS:[40915C],0D8BD1FF
00401790   0F85 22010000    JNZ Crackme2.004018B8
Мдя...

Придётся опять перезапускать и проходить до того места где всё расхоривается. Улавиливаете чем хорить байты в 409198 и 40915c. Правильно тем чем сравнивется.

итак до расхоривания у нас было:

Код:
00409198   A4               MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
00409199   2C 4C            SUB AL,4C
0040919B   4B               DEC EBX
0040919C   54               PUSH ESP

0040915C   AB               STOS DWORD PTR ES:[EDI]
0040915D   98               CWDE
0040915E   C3               RETN
0040915F   5E               POP ESI
Теперь хорим тем, что должно было быть.

Код:
	4b4c2ca4
    xor
	00097be8
      ____________
	4b45574c  (KEWL)


	5ec398ab
    xor
	0d8bd1ff
      ___________
	53484954 (SHIT)
Вставляем в пасс новые буковки))

Password: K75E-WACL-S75H-I66T

Проверяем!
 
Ответить с цитированием