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

CrackME by _taha_
  #8  
Старый 13.04.2007, 09:00
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

Репутация: 1077
По умолчанию CrackME by _taha_

CrackMe: CrackME by _taha_(мой тобишь)
Цель: найти верный пароль
Сложность: легко
link: искать в разделе крякмисы

Поскольку на мой кякмис было только три ответа, я решил последовать примеру Rascal’a и написать небольшой солюшен. Сейчас я расскажу о неновых, зато довольно интересных, антиотладочных приёмах затронутых в этом крякмисе. Из множества приёмчиков я отобрал именно эти.

Итак начнём... Открываем файл в OllyDbg. Первое, что бросается в глаза не стандартное начало. Это явно не стартап..

Первое что вы увидели это переход, войдя в него - инкремент [ESP], затем стандартное продолжение установки обработчика исключений.

Код:
0040103C  |.  64:FF35 00000>PUSH DWORD PTR FS:[0]                                  ; |
00401043  |.  64:8925 00000>MOV DWORD PTR FS:[0],ESP                               ; |
Из чего вы должны были сделать вывод, что следующий, после call, байт – это мусор, запутывающий дизассемблер Olly. Поэтому вместо этого

Код:
 call opa
 db   68h
 mov  eax, [esp+0Ch]
 inc  dword ptr [eax+0B8h]
 xor  edx,edx
вы видели это

Код:
00401000 >/$  E8 34000000   CALL _CrackME.00401039
00401005  |.  68 8B44240C   PUSH 0C24448B
0040100A  |.  FF80 B8000000 INC DWORD PTR DS:[EAX+B8]
Теперь понятно почему я выбрал байт 68h. Olly отказывается верить, что там нет push’а. Далее идёт исключительная ситуация, int3. В результате чего мы попадаем на адрес 401006. Здесь вы должны заметить, что программа проверяет хардваровые бряки.

Код:
0040101E  |.  66:3115 26304>XOR WORD PTR DS:[403026],DX
Если breakpoint’ов нет, то в dx должен быть ноль. Соответсвенно константа [403026] не пострадает. А пока перенесёмся на следущую после int3 команду. Восстанавливается старый обработчик исключний. А уже ненужный кадр стека не затерается как обычно, а увеличивается на 24h, в результате чего в стеке останется указатель на строку “%s%s%s%s”, и используется в качестве параметра к функции OutputDebugStringA. Это exploit, так сказать. OutputDebugStringA отправляет Olly строку “%s%s%s%s”, которую та не может коректно обработать. В результате Olly просто вылетает. Поэтому нужно использовать либо пофикшеные модификации отладчика, либо выравнить стек, а функцию забить нопами.
Далее вроде всё тихо, всё за исключением одной функции

0040106C |. E8 6A010000 CALL _CrackME.004011DB

Код:
  mov eax, fs:[30h]			;
  lea eax, [eax+2]			; Это своеобразный вызов IsDebuggerPresent
  movzx ebx, byte ptr [eax]	; 

  test ebx, ebx
  je	ex_
  xor [00403026],0EA43h		; херю константу
ex_:
  mov byte ptr [eax],90h
  ret
Дальше интересней.. Проверить я проверил, но в подлиности результата в 99% случаев можно сомневаться, тк редкий реверсИр не использует плагин для скрытия. И проблема большенства из них в том, что они патчат не PEB, а функцию IsDebuggerPresent. Естественно API IsDebuggerPresent будет возвращать ноль в любом случае. И это как раз проблема плагина. Я кладу в PEB число 90h и если при следующем вызове IsDebuggerPresent возвратит не 90h, то смело можно предполагать – нас отлаживают. Убедится в этом вы можете, найдя эти строки

Код:
004010B9   .  E8 4C010000   CALL <JMP.&kernel32.IsDebuggerPresent>                 ; [IsDebuggerPresent
004010BE   .  3D 90000000   CMP EAX,90
004010C3   .  75 09         JNZ SHORT _CrackME.004010CE
004010C5   .  66:8135 28304>XOR WORD PTR DS:[403028],0DEAD
Перейдём к GetDlgItemTextA и продолжим исследовать. Дальше идёт вот эта функция

00401145 . E8 3D000000 CALL _CrackME.00401187

Исследовав внутренности этой функции, вы должны были понять, что хэшируется. Но это не всё! Одна из главных “интересностей” крякмиса скрывается ИМЕНО ЗДЕСЬ.

Код:
0040118E  |.  8B1424        MOV EDX,DWORD PTR SS:[ESP]
00401191  |.  66:8B12       MOV DX,WORD PTR DS:[EDX]
Этот код сохранит в dx следующие после CALL _CrackME.00401187 два байта, которые будут учавствовать в хэшировании. И что же тут интересного? – спросит читатель. А дело в том, что когда программа трассируется по F8, Olly ставит на следующий после call байт бряк – int3 и отпускает программу в “свободный полёт”. Когдаже программа “нагуляется” по внутреностям CALL _CrackME.00401187 и перейдёт на следующий байт, Olly всё вернёт на место. Соответсвено после прохождения функции по F7 и вызова её по F8, будут разные результаты. Что повлияет на результат.

Далее идёт вызов Int1, что должно повлечь исключительную ситуацию. Фитча в том, что Olly не считает прирывание INT1 исключением если оно идёт с префиксом, а вот Windows считает.

Код:
0040114A   .  F3:64:        PREFIX REP:                                            ;  Superfluous prefix
0040114C   .  F1            INT1
Так что, без отладчика мы должны попасть на SEH-обработчик. Итак пойдём на действующий обработчик.

Код:
004011B4  /$  8B4424 0C     MOV EAX,DWORD PTR SS:[ESP+C]                           ;  Structured exception handler
004011B8  |.  8B1D 42354000 MOV EBX,DWORD PTR DS:[403542]                          ;  _CrackME.0040114D
004011BE  |.  8998 B8000000 MOV DWORD PTR DS:[EAX+B8],EBX
004011C4  |.  8B90 A8000000 MOV EDX,DWORD PTR DS:[EAX+A8]
004011CA  |.  80FA CC       CMP DL,0CC
004011CD  |.  74 09         JE SHORT _CrackME.004011D8
004011CF  |.  66:8135 26304>XOR WORD PTR DS:[403026],9696
004011D8  |>  33C0          XOR EAX,EAX
004011DA  \.  C3            RETN
Как вы можете заметить, здесь устанавливается EIP и ещё раз проверяется была ли трассеровка по F8.

С анти дебагом всё! Дальше идёт сравнение:

Код:
0040114D   .  3B05 26304000 CMP EAX,DWORD PTR DS:[403026]
00401153   .  75 13         JNZ SHORT _CrackME.00401168
Как вы могли заметить, [403026] складывается из тех двух word’ов, которые менялись в процессе отладки.

Если вы проделали всё правильно, то у вас должно храниться по этому адресу число 2D5253F3h.

Теперь о том как найти пароль. Ведь хэш – это необратимое преобразование, следовательно ничего кроме брута вам не остается. Как вы должны были подметить, пароль состоит из 4’х символов. К тому же, как я написал пароль состоит из русских букв. Заметьте это значительно снижает область брута. Приводить код брутера не буду, только дам вам вот эти линки:

http://www.reversing.be/article.php?story=20050302175850923&query=brutefor cing
http://www.reversing.be/article.php?story=20050414211341413&query=brutefor cing

Замечу только, что если всё проделанно верно, то пароль брутится считанные секунды.