Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Реверсинг (https://forum.antichat.xyz/forumdisplay.php?f=94)
-   -   Solutions (https://forum.antichat.xyz/showthread.php?t=30897)

taha 09.01.2007 23:48

Solutions
 

Описание: Это тема представляет из себя сборник решений наиболее интерсных задачек(CrackMe). Думаю новичкам и не только будет полезно почитать решения таких людей как hidden, ProTeuS, Ra$cal. ИМХО не писать же из-за пары интересных приёмов статьи.

Условие: Не выкладывать решения до прохождения, расчитанным автором crackme, определённого числа людей или истечения срока давности!

Формат: Придерживайтесь следующего формата!

Код:

CrackMe: ...
Цель: пропатчить/закейгенить/найти верный пароль/...
Сложность: легко/средне/сложно
Коментарий: Ваши комментарии. Если есть.
link: где искать
Решение: Само решение


taha 09.01.2007 23:49

..::[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

Проверяем!

taha 09.01.2007 23:51

hiddCrackMeImp
 

CrackMe: hiddCrackMeImp
Цель: найти последовательность действий для регистрации
Сложность: средне
Решение:

Запускаем, видим функцию. Нужно зайти, тк лично у меня по f8 прога упала.

Код:

00401BB7 > E8 16000000      CALL HidCreck.00401BD2
Трейсим, функция преобразовывается налицо. И получается следующий цикл который тоже что то расшифровывает.

Код:

00401BE2  8D41 FF          LEA EAX,DWORD PTR DS:[ECX-1]
00401BE5  83E0 0F          AND EAX,0F
00401BE8  8A0428          MOV AL,BYTE PTR DS:[EAX+EBP]
00401BEB  30040E          XOR BYTE PTR DS:[ESI+ECX],AL
00401BEE  ^E2 F2            LOOPD SHORT HidCreck.00401BE2

Пройдя этот цикл и mov следующий за ним переж нами появится ret.

Код:

00401BF3  C3              RETN
Пройдя его, мы идём дальше. И после прохода следующей функции

Код:

00401009  E8 02040000      CALL HidCreck.00401410
,мы видим, что подгружаются новые библиотеки. Это даёт нам право предполагать, что внутри лежит загрузчик и импортёр апи. Перезапускаемся и заходим в функцию. Поанализировав её, мы замечаем следующие строки:

Код:

0040143E  66:8338 8B      CMP WORD PTR DS:[EAX],0FF8B
00401442  75 03            JNZ SHORT HidCreck.00401447

Если первые байты апи mov edi,edi (0FF8B), то они пропускается, что дезориентирует Олю. Просто перебиваем условный на безусловный переход. И ставим бряк на cmp. Жмём f9, в eax появляются загружаемые функции. Ищем что-нибудь подозрительное. И находим))).

Код:

EAX 77D48666 user32.RegisterHotKey
Единственная функция получения данных)). И слава Богу)) Далее я полез в Executable Modules (Ctrl-E) > user32.dll > ctrl-N > RegisterHotKey. Ставим бряк на первый байт. F9. Сработало моментально:

Код:

0006F848  00401BB5  /CALL to RegisterHotKey from HidCreck.00401BB0
0006F84C  003204CE  |hWnd = 003204CE (class='HiddenClass')
0006F850  00000001  |HotKeyID = 1
0006F854  00000007  |Modifiers = MOD_ALT|MOD_CONTROL|MOD_SHIFT
0006F858  00000075  \Key = VK_F6

Нужно нажать Ctrl-Alt-Shift-F6. Жмём в Olly F9, и полученную комбинацию в окне крякмиса. И снова брякаемся на апи.

Код:

0006FD80  00401BB5  /CALL to RegisterHotKey from HidCreck.00401BB0
0006FD84  003204CE  |hWnd = 003204CE (class='HiddenClass')
0006FD88  00000001  |HotKeyID = 1
0006FD8C  00000007  |Modifiers = MOD_ALT|MOD_CONTROL|MOD_SHIFT
0006FD90  00000072  \Key = VK_F3

Нужно нажать Ctrl-Alt-Shift-F3.

Код:

0006FD80  00401BB5  /CALL to RegisterHotKey from HidCreck.00401BB0
0006FD84  003204CE  |hWnd = 003204CE (class='HiddenClass')
0006FD88  00000001  |HotKeyID = 1
0006FD8C  00000007  |Modifiers = MOD_ALT|MOD_CONTROL|MOD_SHIFT
0006FD90  00000077  \Key = VK_F8

Нужно нажать Ctrl-Alt-Shift-F8

Код:

0006FD80  00401BB5  /CALL to RegisterHotKey from HidCreck.00401BB0
0006FD84  003204CE  |hWnd = 003204CE (class='HiddenClass')
0006FD88  00000001  |HotKeyID = 1
0006FD8C  00000007  |Modifiers = MOD_ALT|MOD_CONTROL|MOD_SHIFT
0006FD90  00000074  \Key = VK_F5

Нужно нажать Ctrl-Alt-Shift-F5

Ну вот!! registred))

Лично мой путь был более длинным(( Я ставил бряк на CreateWindowExA, искал функцию окна, там нашол сравнение при получении uMsg равного 111h и ток потом до меня допёрло, для чего нужна была эта функция. Я просто не ждал, что регистрация будет проходить так необычно))

taha 09.01.2007 23:53

First CrackMe by ProTeuS
 

CrackMe: First CrackMe by ProTeuS
Цель: найти верный пароль
Сложность: средне
link: http://www.forum.antichat.ru
Решение:

Запускаем, вводим чтонить!
Брякаемся по 004578AE.

Код:

004578AE    21            DB 21                                    ;  CHAR '!'
004578AF    A7            DB A7
004578B0    CD FE          INT 0FE
004578B2    0D            DB 0D

Первый вывод - зашифрованная функция. Следовательно в стеке должен лежать
адрес возврата (помимо SEH-обработчика). Смотрим в стек. Так оно и есть)).

Код:

0012F920  004579C5  RETURN to CrackMe.004579C5
Идём по адресу!!

Код:

004579B7  . 64:FF30        PUSH DWORD PTR FS:[EAX]
004579BA  . 64:8920        MOV DWORD PTR FS:[EAX],ESP
004579BD  . 8D05 AC784500  LEA EAX,DWORD PTR DS:[4578AC]
004579C3  . FFD0          CALL EAX        ; <- Вот вызов криптованной функции
004579C5  . 33C0          XOR EAX,EAX
004579C7  . 5A            POP EDX

Поднимимся выше. Видим интересные функции.

Код:

0045796C  . E8 3FE5FAFF    CALL <JMP.&kernel32.GetCurrentProcess>  ; |[GetCurrentProcess
00457971  . 50            PUSH EAX                                ; |hProcess
00457972  . E8 51E6FAFF    CALL <JMP.&kernel32.ReadProcessMemory>  ; \ReadProcessMemory
...
004579A0  . E8 8BE6FAFF    CALL <JMP.&kernel32.WriteProcessMemory>  ; \WriteProcessMemory

Начало функции в которую мы попали:

Код:

0045793C  . 55            PUSH EBP
0045793D  . 8BEC          MOV EBP,ESP
0045793F  . 83C4 F0        ADD ESP,-10
00457942  . 53            PUSH EBX
00457943  . 56            PUSH ESI

Ctrl-F2(перезапускаемся). Ctrl-G > 0045793C. Ставим бряк. F9.

Вводим чтонить. И брякаемся. Дальше трейсим.

Код:

0012F5F8  00457977  /CALL to ReadProcessMemory from CrackMe.00457972
0012F5FC  FFFFFFFF  |hProcess = FFFFFFFF
0012F600  004578AC  |pBaseAddress = 4578AC
0012F604  0045AC03  |Buffer = CrackMe.0045AC03
0012F608  00000001  |BytesToRead = 1
0012F60C  0012F61C  \pBytesRead = 0012F61C

4578AC - не далеко от адреса по которому упала прога. Истина гдето рядом))

Код:

0045798D  . 3013          XOR BYTE PTR DS:[EBX],DL
____________________________________
DL=01
DS:[0045AC03]=99

Настоящее начало криптованной функции. В 90% случаях функции начинаются
с push ebp. Алго криптования нам известен)). 99 xor 55 = 0CCh = 204d

Пасс: 204

_Great_ 10.01.2007 13:21

CrackMe: CrackMe by [Great]
Цель: найти верный пароль
Сложность: средне
Решение:
Выложу сам свое решение нормальное :)
Во-первых прога запакована UPX'ом, поэтому быстро распаковываем.
Открываем прогу в олли, ждем окончания анализа, запускаем по F5, и.... она закрывается. Причем вместе с олли. Аналогичная фишка и в других отладчиках, например, встроенном в MS Visual Studio. Что-то тут не так :)
Вообще можно обойтись плагином IsDebuggerPresent hide для олли, но ввиду того, что он есть не у всех, мы пойдем влоб)
Код:

004010B5  |.  B8 01000000  MOV EAX, 1
004010BA  |.  40            INC EAX
004010BB  |.  68 8C114000  PUSH ucrackme.0040118C
004010C0  |.  64:8B40 FE    MOV EAX, DWORD PTR FS:[EAX-2]
004010C4  |.  50            PUSH EAX
004010C5  |.  64:8925 00000>MOV DWORD PTR FS:[0], ESP

Это, очевидно, установка SEH, только слегка измененная, чтобы Олли её не опознал, как таковую :) Дальше идет код, который всегда вызовет исключение нарушения доступа, слегка замаскированный. Поэтому просто ставим бряк на 0040118c и жмем F9(Run). Брякаемся на 40118c. Идет расшифровка строк kernel32.dll и IsDebuggerPresent и запуск этой функции:
Код:

0040120F  .  FF55 FC      CALL DWORD PTR [EBP-4]                  ;  kernel32.IsDebuggerPresent
Конечно же, без плагина, она возвратит 1. Смело ставим в EAX 0 и двигаемся дальше. Нопим call EnumWindows, т.к. она ищет окно Olly и грохает его. Подходим к DialogBoxParamA. DlgProc устроена так, что после нажатия ОК она возвращает указатель на строку и дропает окно. Поэтому вводим что-нибудь и нажимаем ОК. Видим:
Код:

004012DA  .  68 90304000  PUSH ucrackme.00403090                  ;  ASCII "ertwrwe"
004012DF  .  E8 DC010000  CALL ucrackme.004014C0
004012E4  .  83C4 04      ADD ESP, 4
004012E7  .  8BF0          MOV ESI, EAX
004012E9  .  68 64304000  PUSH ucrackme.00403064                  ;  ASCII "rqugvPo`ac[mehgvPrduqsnva"
004012EE  .  E8 CD010000  CALL ucrackme.004014C0
004012F3  .  83C4 04      ADD ESP, 4
004012F6  .  3BF0          CMP ESI, EAX

ertwrwe - это введено в поле. Очевидно, это сравнене длин. Смело нопим, чтобы не мешало или просто ставим курсор на инструкцию JE, Ctrl-*, делаем флаг Z=1. Перескакиваем вывод ругательства из-за неправильной длины. Далее идет цикл проверки:
Код:

00401365  .  0FBE8A 903040>MOVSX ECX, BYTE PTR [EDX+403090]
0040136C  .  8B45 F8      MOV EAX, DWORD PTR [EBP-8]
0040136F  .  33D2          XOR EDX, EDX
00401371  .  BE 0B000000  MOV ESI, 0B
00401376  .  F7F6          DIV ESI
00401378  .  0FBE92 803040>MOVSX EDX, BYTE PTR [EDX+403080]
0040137F  .  33CA          XOR ECX, EDX
00401381  .  0FBEC1        MOVSX EAX, CL
00401384  .  8B4D F8      MOV ECX, DWORD PTR [EBP-8]
00401387  .  0FBE91 643040>MOVSX EDX, BYTE PTR [ECX+403064]
0040138E  .  3BC2          CMP EAX, EDX

Самый обычный XOR циклически с ключем. Расшифровывая быстренько правильный пароль, получим super_mega_lamer_password.
Перезапускаем, вводим super_mega_lamer_password и Registration completed!

taha 19.01.2007 16:15

CrackMe #3 by anorganix
 

CrackMe: CrackMe #3 by anorganix
Цель: найти верный пароль
Сложность: средне
link: http://arteam.accessroot.com/releases/ (Crackmes 1 To 8 By Anorganix)
Решение:

Грузим прогу в Olly!

Код:

100A45BC > 9C              PUSHFD
100A45BD  60              PUSHAD
100A45BE  E8 00000000      CALL CrackMe3.100A45C3
100A45C3  5D              POP EBP

Это даёт нам понять, что прога чем то запакованна. F8 и ставим бряк на esp (в command bar ввести hr esp). F9 и брякаемся тут:

Код:

100A482D  9D              POPFD
100A482E  -E9 15F3FAFF      JMP CrackMe3.10053B48

Удаляем бряк (в command bar ввести hd esp-4). F8 и мы на oep! Мдя o e p....

Код:

10053B48    55            DB 55                                    ;  CHAR 'U'
10053B49    8B            DB 8B
10053B4A    EC            DB EC
10053B4B    83            DB 83
10053B4C    C4            DB C4
10053B4D    F0            DB F0
10053B4E    B8            DB B8
10053B4F    60390510      DD CrackMe3.10053960
10053B53    E8            DB E8
10053B54    6C            DB 6C                                    ;  CHAR 'l'
10053B55    22            DB 22                                    ;  CHAR '"'
10053B56    FB            DB FB
10053B57    FF            DB FF
10053B58    E8            DB E8

Меня утешило то, что я знал: 55h - "push ebp", 8BECh - "mov ebp,esp" и тп. А следовательно можно попытаться объяснить это Olly, разуж Ctrl-A не всилах нам помочь.
F10 > Analysis > During next analysis ... > command. После третьей команды я опять попробовал нажать Ctrl-A и, о чудо, Olly всё проанализировала как надо!!

Код:

10053B48  . 55            PUSH EBP
10053B49  . 8BEC          MOV EBP,ESP
10053B4B  . 83C4 F0        ADD ESP,-10
10053B4E  . B8 60390510    MOV EAX,CrackMe3.10053960
10053B53  . E8 6C22FBFF    CALL CrackMe3.10005DC4
10053B58  . E8 73FDFFFF    CALL CrackMe3.100538D0
10053B5D  . 84C0          TEST AL,AL
10053B5F  . 75 09          JNZ SHORT CrackMe3.10053B6A
10053B61  . E8 8EFDFFFF    CALL CrackMe3.100538F4
10053B66  . 84C0          TEST AL,AL
10053B68  . 74 05          JE SHORT CrackMe3.10053B6F
10053B6A  > E8 3903FBFF    CALL CrackMe3.10003EA8
10053B6F  > A1 3C500510    MOV EAX,DWORD PTR DS:[1005503C]
10053B74  . 8B00          MOV EAX,DWORD PTR DS:[EAX]
10053B76  . E8 D5D9FFFF    CALL CrackMe3.10051550
10053B7B  . A1 3C500510    MOV EAX,DWORD PTR DS:[1005503C]
10053B80  . 8B00          MOV EAX,DWORD PTR DS:[EAX]
10053B82  . BA C03B0510    MOV EDX,CrackMe3.10053BC0                ;  ASCII "CrackMe #3"
10053B87  . E8 D4D5FFFF    CALL CrackMe3.10051160
10053B8C  . 8B0D 684F0510  MOV ECX,DWORD PTR DS:[10054F68]          ;  CrackMe3.10056C00
10053B92  . A1 3C500510    MOV EAX,DWORD PTR DS:[1005503C]
10053B97  . 8B00          MOV EAX,DWORD PTR DS:[EAX]
10053B99  . 8B15 C4320510  MOV EDX,DWORD PTR DS:[100532C4]          ;  CrackMe3.10053310
10053B9F  . E8 C4D9FFFF    CALL CrackMe3.10051568
10053BA4  . A1 3C500510    MOV EAX,DWORD PTR DS:[1005503C]

Я начал трейсить!! И после

Код:

10053B6A  > E8 3903FBFF    CALL CrackMe3.10003EA8
Прога вылетела! Пришлось проходить всё заново! Беглый анализ функции дал понять, что она проверяла под отладчиком мы или нет! Не долго думая, я решил обойти злощастную функцию! Дойдя до неё, я поменял eip (с помощью New origin here). F9 и прога запустилась и вылетела. Что удивило вылетела в отладчике и норамльно функционировала со мной! Единственное что пришло в голову, так это - пред тем как прога убивает себя она создаёт новый процесс! А с помощь чего можно создать процес? Правильно CreateProcessA! Поищем эту апи. И вот код:

Код:

10053657  |. 6A 04          PUSH 4
10053659  |. 6A 00          PUSH 0
1005365B  |. 6A 00          PUSH 0
1005365D  |. 6A 00          PUSH 0
1005365F  |. 8D95 C0FEFFFF  LEA EDX,DWORD PTR SS:[EBP-140]
10053665  |. 33C0          XOR EAX,EAX
10053667  |. E8 78F3FAFF    CALL crackme3.100029E4
1005366C  |. 8B85 C0FEFFFF  MOV EAX,DWORD PTR SS:[EBP-140]
10053672  |. E8 E10DFBFF    CALL crackme3.10004458
10053677  |. 50            PUSH EAX                                ; |CommandLine
10053678  |. 6A 00          PUSH 0                                  ; |ModuleFileName = NULL
1005367A  |. E8 3D29FBFF    CALL <JMP.&kernel32.CreateProcessA>      ; \CreateProcessA
1005367F  |. C785 18FFFFFF >MOV DWORD PTR SS:[EBP-E8],10007
10053689  |. 8D85 18FFFFFF  LEA EAX,DWORD PTR SS:[EBP-E8]
1005368F  |. 50            PUSH EAX                                ; /pContext
10053690  |. 8B85 0CFFFFFF  MOV EAX,DWORD PTR SS:[EBP-F4]            ; |
10053696  |. 50            PUSH EAX                                ; |hThread
10053697  |. E8 F029FBFF    CALL <JMP.&kernel32.GetThreadContext>    ; \GetThreadContext
1005369C  |. 8D45 F4        LEA EAX,DWORD PTR SS:[EBP-C]
1005369F  |. 50            PUSH EAX                                ; /pBytesRead
100536A0  |. 6A 04          PUSH 4                                  ; |BytesToRead = 4
100536A2  |. 8D45 F8        LEA EAX,DWORD PTR SS:[EBP-8]            ; |
100536A5  |. 50            PUSH EAX                                ; |Buffer
100536A6  |. 8B45 BC        MOV EAX,DWORD PTR SS:[EBP-44]            ; |
100536A9  |. 83C0 08        ADD EAX,8                                ; |
100536AC  |. 50            PUSH EAX                                ; |pBaseAddress
100536AD  |. 8B85 08FFFFFF  MOV EAX,DWORD PTR SS:[EBP-F8]            ; |
100536B3  |. 50            PUSH EAX                                ; |hProcess
100536B4  |. E8 7B2AFBFF    CALL <JMP.&kernel32.ReadProcessMemory>  ; \ReadProcessMemory
100536B9  |. 6A 40          PUSH 40
100536BB  |. 68 00300000    PUSH 3000
100536C0  |. 8B45 F0        MOV EAX,DWORD PTR SS:[EBP-10]
100536C3  |. 50            PUSH EAX
100536C4  |. 8B45 E4        MOV EAX,DWORD PTR SS:[EBP-1C]
100536C7  |. 8B40 34        MOV EAX,DWORD PTR DS:[EAX+34]
100536CA  |. 50            PUSH EAX
100536CB  |. 8B85 08FFFFFF  MOV EAX,DWORD PTR SS:[EBP-F8]
100536D1  |. 50            PUSH EAX
100536D2  |. E8 BD2AFBFF    CALL <JMP.&kernel32.VirtualAllocEx>
100536D7  |. 8D45 F4        LEA EAX,DWORD PTR SS:[EBP-C]
100536DA  |. 50            PUSH EAX                                ; /pBytesWritten
100536DB  |. 8B45 F0        MOV EAX,DWORD PTR SS:[EBP-10]            ; |
100536DE  |. 50            PUSH EAX                                ; |BytesToWrite
100536DF  |. 8B45 E8        MOV EAX,DWORD PTR SS:[EBP-18]            ; |
100536E2  |. 50            PUSH EAX                                ; |Buffer
100536E3  |. 8B45 E4        MOV EAX,DWORD PTR SS:[EBP-1C]            ; |
100536E6  |. 8B40 34        MOV EAX,DWORD PTR DS:[EAX+34]            ; |
100536E9  |. 50            PUSH EAX                                ; |Address
100536EA  |. 8B85 08FFFFFF  MOV EAX,DWORD PTR SS:[EBP-F8]            ; |
100536F0  |. 50            PUSH EAX                                ; |hProcess
100536F1  |. E8 BE2AFBFF    CALL <JMP.&kernel32.WriteProcessMemory>  ; \WriteProcessMemory
100536F6  |. 8D45 F4        LEA EAX,DWORD PTR SS:[EBP-C]
100536F9  |. 50            PUSH EAX                                ; /pBytesWritten
100536FA  |. 6A 04          PUSH 4                                  ; |BytesToWrite = 4
100536FC  |. 8B45 E4        MOV EAX,DWORD PTR SS:[EBP-1C]            ; |
100536FF  |. 83C0 34        ADD EAX,34                              ; |
10053702  |. 50            PUSH EAX                                ; |Buffer
10053703  |. 8B45 BC        MOV EAX,DWORD PTR SS:[EBP-44]            ; |
10053706  |. 83C0 08        ADD EAX,8                                ; |
10053709  |. 50            PUSH EAX                                ; |Address
1005370A  |. 8B85 08FFFFFF  MOV EAX,DWORD PTR SS:[EBP-F8]            ; |
10053710  |. 50            PUSH EAX                                ; |hProcess
10053711  |. E8 9E2AFBFF    CALL <JMP.&kernel32.WriteProcessMemory>  ; \WriteProcessMemory
10053716  |. 8B45 E4        MOV EAX,DWORD PTR SS:[EBP-1C]
10053719  |. 8B40 34        MOV EAX,DWORD PTR DS:[EAX+34]
1005371C  |. 8B55 E4        MOV EDX,DWORD PTR SS:[EBP-1C]
1005371F  |. 0342 28        ADD EAX,DWORD PTR DS:[EDX+28]
10053722  |. 8945 C8        MOV DWORD PTR SS:[EBP-38],EAX
10053725  |. 8D85 18FFFFFF  LEA EAX,DWORD PTR SS:[EBP-E8]
1005372B  |. 50            PUSH EAX                                ; /pContext
1005372C  |. 8B85 0CFFFFFF  MOV EAX,DWORD PTR SS:[EBP-F4]            ; |
10053732  |. 50            PUSH EAX                                ; |hThread
10053733  |. E8 342AFBFF    CALL <JMP.&kernel32.SetThreadContext>    ; \SetThreadContext
10053738  |. 8B85 0CFFFFFF  MOV EAX,DWORD PTR SS:[EBP-F4]
1005373E  |. 50            PUSH EAX                                ; /hThread
1005373F  |. E8 002AFBFF    CALL <JMP.&kernel32.ResumeThread>        ; \ResumeThread
10053744  |. 33C0          XOR EAX,EAX
10053746  |. 5A            POP EDX

Поставив бряк на CreateProcessA, я нажал F9 (не забывайте обходить ту вредную функцию). Брякаемся и вот параметры функции:

Код:

0012FC6C  1005367F  /CALL to CreateProcessA from crackme3.1005367A
0012FC70  00000000  |ModuleFileName = NULL
0012FC74  00DB3A30  |CommandLine = "C:\crackme3u.exe"
0012FC78  00000000  |pProcessSecurity = NULL
0012FC7C  00000000  |pThreadSecurity = NULL
0012FC80  00000000  |InheritHandles = FALSE
0012FC84  00000004  |CreationFlags = CREATE_SUSPENDED
0012FC88  00000000  |pEnvironment = NULL
0012FC8C  00000000  |CurrentDir = NULL
0012FC90  0012FCC0  |pStartupInfo = 0012FCC0
0012FC94  0012FD04  \pProcessInfo = 0012FD04

Действительно создаёт новый процес и тормозит его! А как же нам попасть туда? Аттачится конечно! Но вот беда, Olly видит процес только после выполнения

Код:

1005373F  |. E8 002AFBFF    CALL <JMP.&kernel32.ResumeThread>        ; \ResumeThread
А после выполнения этой функции программу на ep нам не застать! Лан жмём F9 в Olly прога вылетает, новый процесс остаётся! Открываем ещё раз Olly (ну чтоб было два процесса)! Аттачимся!

Открываем карту памяти и вот что замечаем:
Код:

Memory map, item 15
 Address=00400000
 Size=000A0000 (655360.)
 Owner=CrackMe3 00400000 (itself)
 Section=
 Contains=PE header
 Type=Priv 00021040
 Access=RWE
 Initial access=RWE

Новый image base => новый ep, код которого записывается старым процесом. Посмотрим новый EP!

Код:

00400068  BC950700    DD 000795BC          ;  AddressOfEntryPoint = 795BC
Ладно всё что нужно мы узнали закрываем окно! Перезапускаем прогу и опять проходим до CreateProcessA. Идём до WriteProcessMemory. И пока не выполняем её! Вот параметры этой функции:

Код:

0012FC80  100536F6  /CALL to WriteProcessMemory from crackme3.100536F1
0012FC84  000000A8  |hProcess = 000000A8 (window)
0012FC88  00400000  |Address = 400000
0012FC8C  00D13A24  |Buffer = 00D13A24
0012FC90  000A0000  |BytesToWrite = A0000 (655360.)
0012FC94  0012FDF0  \pBytesWritten = 0012FDF0

Отправляемся по адресу, с которого ведётся запись в новый процесс! 00D13A24 - это image base в новом процессе, а значит по 00D13A24+795BC будет код ep. Отправляемся по 00D8CFE0. Этот код вызвал у меня истерический смех:

Код:

$+795BC  > 9C              PUSHFD
$+795BD  > 60              PUSHAD
$+795BE  > E8 00000000      CALL 00D8CFE7
$+795C3  > 5D              POP EBP
$+795C4  > 83ED 07          SUB EBP,7

Судя по всему процесс будет ещё распаковываться =)) Спросите зачем я вас сюда завёл! Смотрите, если в каком-нибудь процессе возникнет исключение, то мы можем поймать его Olly, правильно сконфигурировав её. Итак перебиваем pushfd на int3. Именно int3; не int 3; разница в целый байт! Нам нужен int3 = 0CCh. Теперь конфигурируем Olly. В Options > Just-in-time debugging > Make OllyDbg just-in-time debugger. Теперь когда процесс вызовит исключение, а он вызовит первой же коммандой =), Olly среагирует на это и мы окажемся но ep!

F9 и открывается новый процесс Olly! Ура мы на EP! Возвращаем на место pushf и обходим пакер, благо использовался старый!

Мдя.. На первый взгляд ничего не изменилось...

Код:

00454DFC  55              PUSH EBP
00454DFD  8BEC            MOV EBP,ESP
00454DFF  83C4 F0          ADD ESP,-10
00454E02  B8 1C4C4500      MOV EAX,CrackMe3.00454C1C
00454E07  E8 540EFBFF      CALL CrackMe3.00405C60
00454E0C  E8 7BFDFFFF      CALL CrackMe3.00454B8C
00454E11  84C0            TEST AL,AL
00454E13  75 09            JNZ SHORT CrackMe3.00454E1E
00454E15  E8 96FDFFFF      CALL CrackMe3.00454BB0
00454E1A  84C0            TEST AL,AL
00454E1C  74 05            JE SHORT CrackMe3.00454E23
00454E1E  E8 39EFFAFF      CALL CrackMe3.00403D5C
00454E23  A1 98604500      MOV EAX,DWORD PTR DS:[456098]
00454E28  8B00            MOV EAX,DWORD PTR DS:[EAX]
00454E2A  E8 71DFFFFF      CALL CrackMe3.00452DA0
00454E2F  A1 98604500      MOV EAX,DWORD PTR DS:[456098]

И та функця проверки осталась. На этот раз мы в неё зайдём, только через enter. И поставим бряк на первый байт! Теперь если туда попадёт управление мы будем об этом знать! "-" и обходим с помощью New origin here! F9.

Попадание на ep нам практически ничего не дало! Пытал прогу и на String reference и бряки на апи ставил, естественно на последние байты, но это ничего не дало. ппц! Но у меня в запасе был ещё один приём. Я ввёл dimok и вылетело сообщение о неправильности пароля. В ArtMoney нашёл адреса, в которых лежит это слово. Поставил на них бряки и ещё раз нажал ввод!

Бряк сработал мгновенно я оказался внутри какойто функции!

Посомотрим на стек, там несколько раз встречается слово dimok. Но мы ищем первый адрес вазврата в секцию кода и находим

Код:

0012F45C  |00437B10  RETURN to CrackMe3.00437B10 from CrackMe3.00406278
Идём по адресу!

Код:

00437B03  50              PUSH EAX
00437B04  8B86 74010000    MOV EAX,DWORD PTR DS:[ESI+174]
00437B0A  50              PUSH EAX
00437B0B  E8 68E7FCFF      CALL CrackMe3.00406278                  ; JMP to USER32.CallWindowProcA
00437B10  8943 0C          MOV DWORD PTR DS:[EBX+C],EAX
00437B13  8B03            MOV EAX,DWORD PTR DS:[EBX]
00437B15  83F8 0C          CMP EAX,0C
00437B18  75 1B            JNZ SHORT CrackMe3.00437B35
00437B1A  8B53 08          MOV EDX,DWORD PTR DS:[EBX+8]
00437B1D  52              PUSH EDX

Снимаем старые бряки и поставим новый на 437b1a. Нажмём на кнопочку, и бряк срабатывает!

Код:

00437B1A  8B53 08          MOV EDX,DWORD PTR DS:[EBX+8]
00437B1D  52              PUSH EDX
00437B1E  8B4B 04          MOV ECX,DWORD PTR DS:[EBX+4]
00437B21  8BD0            MOV EDX,EAX
00437B23  8BC6            MOV EAX,ESI
00437B25  E8 56B7FFFF      CALL CrackMe3.00433280

Один из параметров этой функции адрес Warning. Следовательно функция проверки гдето выше, а то куда мы попали это функции отрисовки MessageBoxA. Начинаем трассировать. В стеке должны храниться адреса строк о неправильности. Мыже находимся в вызываемой функции отрисовки. Короче жмём F8 пока в стеке нам не встретятся строчки о неправильности! Дальше нам встретится

Код:

0012F93C  00DB2448  ASCII "dimok"
0012F940  00DB3B90  ASCII "351239814584495632156"
0012F944  00DB23F8  ASCII "651236594485418932153-XNA"
0012F948  00DB2420  ASCII "ANX-351239814584495632156"

а после этого следует адрес возврата

Код:

0012F950  |00434C7A  RETURN to CrackMe3.00434C7A
идём по нему и мы окажемся в этой функции, если подняться выше.

Код:

004549BC  55              PUSH EBP
004549BD  68 CC4A4500      PUSH CrackMe3.00454ACC
004549C2  64:FF30          PUSH DWORD PTR FS:[EAX]
004549C5  64:8920          MOV DWORD PTR FS:[EAX],ESP
004549C8  8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]

Кароче, если вы её проанализируете, то поймёте, что пароль ANX-351239814584495632156.

Ra$cal 05.02.2007 01:32

Ra$cal KeyGenMe 2
Написал как автор крякми. То есть на что я делал ставку. Ждём солюшена человека, взломавшего сей крякми...
Итак. Основная фича этого творения - антиотладка используется с интересной целью. Не просто выдаёт месаджбокс и выходит. А данные получаемые от проверок изменяют внутренний ключ, который участвует в проверке. Таким образом если программа отлаживается и хоть одна проверка обнаружила отладчик, то найденный ключ не подойдёт при запуске программы без отладчика. Теперь про реализацию...

Сначала была придумана константа - 0x7DA3EF10. Далее вспомнил какие проверки знаю. Всего решил сделать 5 штук. Соотв решил какие биты в константе должны быть изменены. 3 бита должны быть изменены, 2 должны остаться. 0x7923EF14. Далее для сложности обнаружения обращений к этому дворду (в олли очень просто найти всю работу с конкретным адресом в секции данных. то есть легко локализовать и изменения и использование этой константы) сделал так. Дворд был разбит на 2: ControlDW_L = 0x5ca3ef14 и ControlDW_H = 0xba617923. В сладших словах находятся части константы. А для собсно скрытия обращений сделал ещё две переменные. Итог - static DWORD DummyBefore = 0x547298f0, ControlDW_L = 0x5ca3ef14, ControlDW_H = 0xba617923, DummyAfter = 0xba45910f;
Компилятор сделает так что эти переменные в памяти находятся последовательно. Следовательно чтоб обратиться к нужной достаточно получить адрес подставной переменной и и прибавить/удалить 4. Или 8. Вобщем как это работает:

Код:

_asm{
lea eax, DummyBefore;
add eax, 8;
mov eax, [eax]; получили ControlDW_H
}

Дальше...
Для реализации идеи пришлось придумывать, как связать возвращаемое значение проверки (причём не просто cmp jnz, а именно то значение, которое возвращает апи(например) при наличии отладчика и при его отсутствии). Так для IsDebuggerPresent задумано, что при отсутствии отладчика он вернёт 0. То есть если вернёт 1 константа будет испорчена...
Код:

temp = IsDebuggerPresent();
_asm{
        lea eax, DummyBefore;
        add eax, 8;
        mov ecx, temp;
        xor [eax], ecx;
}

Ещё из применённых проверок.

Код:

004016D0 >/$  55              PUSH EBP
004016D1  |.  8BEC            MOV EBP,ESP
004016D3  |.  83EC 08          SUB ESP,8
004016D6  |.  8D45 FC          LEA EAX,DWORD PTR SS:[EBP-4]
004016D9  |.  50              PUSH EAX                                                          ; /pThreadId
004016DA  |.  6A 00            PUSH 0                                                            ; |CreationFlags = 0
004016DC  |.  6A 00            PUSH 0                                                            ; |pThreadParm = NULL
004016DE  |.  68 30164000      PUSH KeyGenMe.CheckMemoryCrc                                      ; |ThreadFunction = KeyGenMe.CheckMemoryCrc
004016E3  |.  6A 00            PUSH 0                                                            ; |StackSize = 0
004016E5  |.  6A 00            PUSH 0                                                            ; |pSecurity = NULL
004016E7  |.  FF15 1C104000    CALL NEAR DWORD PTR DS:[<&KERNEL32.CreateThread>]                ; \CreateThread
004016ED  |.  C745 F8 00000000 MOV DWORD PTR SS:[EBP-8],0
004016F4  |.  EB 09            JMP SHORT KeyGenMe.004016FF
004016F6  |>  8B4D F8          /MOV ECX,DWORD PTR SS:[EBP-8]
004016F9  |.  83C1 01          |ADD ECX,1
004016FC  |.  894D F8          |MOV DWORD PTR SS:[EBP-8],ECX
004016FF  |>  817D F8 88130000  CMP DWORD PTR SS:[EBP-8],1388
00401706  |.  7D 30            |JGE SHORT KeyGenMe.00401738
00401708  |.  817D F8 D0070000 |CMP DWORD PTR SS:[EBP-8],7D0
0040170F  |.  7E 25            |JLE SHORT KeyGenMe.00401736
00401711  |.  817D F8 C4090000 |CMP DWORD PTR SS:[EBP-8],9C4
00401718  |.  7D 1C            |JGE SHORT KeyGenMe.00401736
0040171A  |.  C705 18214000 01>|MOV DWORD PTR DS:[CanCheck],1
00401724  |.  6A 00            |PUSH 0                                                          ; /Timeout = 0. ms
00401726  |.  FF15 18104000    |CALL NEAR DWORD PTR DS:[<&KERNEL32.Sleep>]                      ; \Sleep
0040172C  |.  C705 18214000 00>|MOV DWORD PTR DS:[CanCheck],0
00401736  |>^ EB BE            \JMP SHORT KeyGenMe.004016F6
00401738  |>  8BE5            MOV ESP,EBP
0040173A  |.  5D              POP EBP
0040173B  \.  C3              RETN

Вот пример. Цикл в 5000 итераций. Причём с сомнительным содержимым. Тут надежда что поставят бряк на 3 последние команды цикла. А суть простая - Sleep (0) приводит к прекращению обработки текущего потока (его квант процессорного времени обнуляется) и начале работы другого потока процесса (если такой есть). А он, как видим немного выше, как раз создаётся. Как видно из инфы в pdb, функцию я назвал CheckMemoryCrc.Так вот Sleep (0) приведёт к тому, что второй поток будет сработывать при вызове Sleep(0)...

Код:

00401630 >/.  55              PUSH EBP
00401631  |.  8BEC            MOV EBP,ESP
00401633  |>  813D 14214000 C7>/CMP DWORD PTR DS:[ThreadCounter],0C7
0040163D  |.  75 32            |JNZ SHORT KeyGenMe.00401671
0040163F  |.  8B0D 28204000    |MOV ECX,DWORD PTR DS:[MemoryCrc]
00401645  |.  BA 01000000      |MOV EDX,1
0040164A  |.  22D1            |AND DL,CL
0040164C  |.  C1C9 10          |ROR ECX,10
0040164F  |.  22D1            |AND DL,CL
00401651  |.  C1C9 08          |ROR ECX,8
00401654  |.  22D1            |AND DL,CL
00401656  |.  C1C2 06          |ROL EDX,6
00401659  |.  8D05 18204000    |LEA EAX,DWORD PTR DS:[DummyBefore]
0040165F  |.  83C0 08          |ADD EAX,8
00401662  |.  C1C2 04          |ROL EDX,4
00401665  |.  3110            |XOR DWORD PTR DS:[EAX],EDX
00401667  |.  C705 28204000 00>|MOV DWORD PTR DS:[MemoryCrc],0
00401671  |>  813D 14214000 C8>|CMP DWORD PTR DS:[ThreadCounter],0C8
0040167B  |.  7E 0B            |JLE SHORT KeyGenMe.00401688
0040167D  |.  833D 18214000 01 |CMP DWORD PTR DS:[CanCheck],1
00401684  |.  75 02            |JNZ SHORT KeyGenMe.00401688
00401686  |.  EB 40            |JMP SHORT KeyGenMe.004016C8
00401688  |>  A1 14214000      |MOV EAX,DWORD PTR DS:[ThreadCounter]
0040168D  |.  83C0 01          |ADD EAX,1
00401690  |.  A3 14214000      |MOV DWORD PTR DS:[ThreadCounter],EAX
00401695  |.  C705 28204000 00>|MOV DWORD PTR DS:[MemoryCrc],0
0040169F  |.  833D 14214000 0F |CMP DWORD PTR DS:[ThreadCounter],0F
004016A6  |.  75 05            |JNZ SHORT KeyGenMe.004016AD
004016A8  |.  E8 03010000      |CALL KeyGenMe.HRChecker
004016AD  |>  B9 D0164000      |MOV ECX,KeyGenMe.MemoryCheckFaker
004016B2  |.  8B51 68          |MOV EDX,DWORD PTR DS:[ECX+68]
004016B5  |.  8915 28204000    |MOV DWORD PTR DS:[MemoryCrc],EDX
004016BB  |.  6A 00            |PUSH 0                                                          ; /Timeout = 0. ms
004016BD  |.  FF15 18104000    |CALL NEAR DWORD PTR DS:[<&KERNEL32.Sleep>]                      ; \Sleep
004016C3  |.^ E9 6BFFFFFF      \JMP KeyGenMe.00401633
004016C8  |>  5D              POP EBP
004016C9  \.  C3              RETN

Здесь тоже цикл и Sleep (0). То есть тут просто синхронизированы потоки. Далее.

Установка бряка в олли осуществляется просто. В целевой процесс пишут байт 0xCC по нужному адресу. Поэтому я читаю 4 байта с конца функции (куда я ожидаю установки бряка).

Код:

004016B2  |.  8B51 68          |MOV EDX,DWORD PTR DS:[ECX+68]
004016B5  |.  8915 28204000    |MOV DWORD PTR DS:[MemoryCrc],EDX

Прикинув как выглядят байты 0x8B, 0x5D, 0xC3 и 0xCC я нашёл, что СС - нечётное число, остальные чётные. Соответственно первый бит равен единице, если бряк не установлен, и 0, если установлен. Эта проверка должна изменить константу. Если хоть один бряк установлен бит будет обнулён.

Код:

0040163F  |.  8B0D 28204000    |MOV ECX,DWORD PTR DS:[MemoryCrc]
00401645  |.  BA 01000000      |MOV EDX,1
0040164A  |.  22D1            |AND DL,CL
0040164C  |.  C1C9 10          |ROR ECX,10
0040164F  |.  22D1            |AND DL,CL
00401651  |.  C1C9 08          |ROR ECX,8
00401654  |.  22D1            |AND DL,CL
00401656  |.  C1C2 06          |ROL EDX,6
00401659  |.  8D05 18204000    |LEA EAX,DWORD PTR DS:[DummyBefore]
0040165F  |.  83C0 08          |ADD EAX,8
00401662  |.  C1C2 04          |ROL EDX,4
00401665  |.  3110            |XOR DWORD PTR DS:[EAX],EDX

Плюс ещё есть вызов 004016A8 |. E8 03010000 |CALL KeyGenMe.HRChecker
Эта проверка проверят, установлен ли хардбряк. Для этого вызывает исключение и проверяет переданнвый контекст потока в функцию обработчик исключения, в котором было исключение. Отладчик для полноты картины ставит в контекст ВСЕХ потов хард бряки, заданные пользователем в каком-то одном. Чтобы мы не пропустили никаких интересующих нас событий. Следовательно, даже если бряк поставлен в другом потоке, в нашем созданном потоке он тоже будет. Поэтому в контексте можно проверить их наличие.

Код:

00401748  |.  33DB            XOR EBX,EBX
0040174A  |.  0B59 04          OR EBX,DWORD PTR DS:[ECX+4]
0040174D  |.  0B59 08          OR EBX,DWORD PTR DS:[ECX+8]
00401750  |.  0B59 0C          OR EBX,DWORD PTR DS:[ECX+C]
00401753  |.  0B59 10          OR EBX,DWORD PTR DS:[ECX+10]
00401756  |.  0B59 18          OR EBX,DWORD PTR DS:[ECX+18]
00401759  |.  8D05 24204000    LEA EAX,DWORD PTR DS:[DummyAfter]
0040175F  |.  83E8 04          SUB EAX,4
00401762  |.  3118            XOR DWORD PTR DS:[EAX],EBX

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

Собсно есть ещё проверки, но логика их такая же. Перечислю только их суть - проверка отладочного порта и фича с обработкой CloseHandle с неправильным параметром.

Теперь что с алгоритмом. Как я и говорил он простой. Напишу тока код моего генератора

Код:

DWORD        Control = 0x7DA3EF10;

void Generate(char* UserName, char* Password)
{
        DWORD        Hash = 0;
        long        Summ = 0;
        DWORD        Pass = 0;
        for (int i  = strlen (UserName); i >= 0; i--){
                Hash ^= UserName[i];
                _asm{
                        rol Hash, 8;
                }
                Summ += UserName[i];
        }
        Pass = (Summ + Hash) ^ Control;
        _itoa(Pass, Password, 16);
        int len = strlen (Password);
        if (len < 8){
                int d;
                d = 8 - len;
                memcpy (Password + d, Password, len);
                memset (Password, '0', d);
                Password [8] = '\0';
        }
}


taha 13.04.2007 09:00

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

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

0x0c0de 03.08.2007 14:41

CrackMe: CrackMe by taha
Цель: найти пару имя+ключ
Сложность: легко
link: в разделе реверсинг
Решение:

В этой статье я постараюсь максимально подробно описать взлом данного крекми, но если у вас есть замечания/дополнения/ прием не нравится какой-либо (или способ лучше есть), пишите в пм или icq-буду рада конструктивной критике.
Приступим
Итак, загружаем crackme в отладчик
Entry point

Код:

00401185 >  B9 C7010000                MOV ECX,1C7
0040118A    BB 78104000                MOV EBX,CrackME.00401078
0040118F    21CB                      AND EBX,ECX
00401191    81F1 FF000000              XOR ECX,0FF
00401197    09F2                      OR EDX,ESI
00401199    83C1 4D                    ADD ECX,4D
0040119C    BE 220F4000                MOV ESI,CrackME.00400F22

Видно,что на обычную точку входа это мало похоже. Значит, это начало расшифровки кода. А если быть точнее- выполнение вспомогательных операций. В частности в по окончанию этого фрагмента в ecx окажется количество зашифрованных байт а именно 185h (хекс).
Шифровщик простой - ксорный.

Код:

004011A7    80340E 18                  XOR BYTE PTR DS:[ESI+ECX],18 ; с каждым проходом значение уменьшается, двигаемся к началу
Исходя из начальных значений можно посчитать с какого адреса начинается расшифровка кода.
В esi в самом начале цикла 400FFF=>адрес с которого начинается расшифровка=00400FFF+185=401184.
Так как ecx после каждого прохода цикла декрементируется => расшифровываться код начинает с конца.

Самый конец цикла
Код:


004011E2    83EC 01                    SUB ESP,1
004011E5    83C4 05                    ADD ESP,5
004011E8  ^ FF6424 FC                  JMP DWORD PTR SS:[ESP-4]                            ; CrackME.004011A7

Ставим точку останова на этот джамп, в дампе идем по адресу 401000 и наблюдаем за тем,
как расшифровывается код. Пока идет расшифровка кода - управление передается на адрес 004011A7.
В ecx в этот момент считается количество оставшихся байт... Когда код расшифруется- джамп передаст управление на адрес 00401001... Начинаем трассировать.
Вызов функций в уже раскриптованом коде имеет вид, подобный этому

Код:

00401035  . /EB FF                    JMP SHORT CrackME.00401036
00401037  .  15 C4204000              ADC EAX,<&USER32.DialogBoxParamA>

Интересно... Это значит, что срабатывает джамп JMP SHORT CrackME.00401036 и передает управление на
инструкцию call [адрес] (опкод FF15 хххххххх).
Но это еще не все. Довольно неприятна и такая конструкция

Код:

00401090  . /74 01                    JE SHORT CrackME.00401093
00401092  . |3B83 C404E800            CMP EAX,DWORD PTR DS:[EBX+E804C4]

Из-за этого всего оля неправильно анализирует инструкции. Напишем скрипт, исправляющий это дело. Конечно, в данном конкретном случае не вижу особого смысла этого делать. Так как замусоривание не очень страшное и глобальное) Честно говоря, взломала без скрипта, - итак все было вполне понятно=) Если бы не статья- скрипт бы писать, конечно, не стала.

Код:


var nachalo ; все, что начинается с var - объявление переменных
var conez
var str_2
var str_3

mov str_3,00402000 ; куда данные инструкции впихнуть должно быть 5 байт свободно! указать можно и свой адрес
mov nachalo,00401001 ; начало исправляемого кода == entry point
mov conez,004011e8 ; конец исправляемого кода
start:
cmp nachalo,conez ; мы в конце?
je final ; тогда на выход
mov [str_3],[nachalo]
mov str_2,str_3
inc str_2 ; первый байт в последовательности меняющийся, его пропускаем
cmp [str_2],15ffeb  ; если последовательность совпадает-идем исправлять
je ispr_call ;если равно- замусоренная инструкция call
cmp [str_2],3b0174  ; если последовательность совпадает-идем исправлять
je ispt_inst
inc nachalo
jmp start ; на начало
final:
ret

ispr_call:
mov [str_2],15ff90 ; нопим злой негодяйский байт
dec str_2
mov [nachalo],[str_2]
inc nachalo ; идем вперед
jmp start ; на начало

ispt_inst:
mov [str_2],909090 ; нопим три паразитных байта
dec str_2
mov [nachalo],[str_2]
inc nachalo ; идем вперед
jmp start ; на начало

Суть в том, что я пробегаюсь по коду и ищу опкоды замусоренных команд. Нехорошо, то, что обе постоянные последовательности имеют размер 3 байта- было бы двойное слово-было б гораздо удобнее. Поэтому приходится хитрить. Недаром буфер должен быть 5 байт. То есть мы читаем очередной дворд, пишем его в буфер, инкрементируем, пропускаем переменный (изменяющийся от инструкции к инструкции) байт и тогда уже сравниваем. Чтобы было понятней, о чем я говорю, рассмотрим все ту же обработанную инструкцию call:

Код:

00401035  . /EB FF                    JMP SHORT CrackME.00401036
00401037  .  15 C4204000              ADC EAX,<&USER32.DialogBoxParamA>

Итак смотрим первые 4 байта eb,ff,15,0c4.. Посмотрим аналогичную инструкцию

Код:

00401003  /EB FF                      JMP SHORT CrackME.00401004
00401005    15 82204000                ADC EAX,<&KERNEL32.GetModuleHandleA>

Первые 4 байта eb,ff,15,82. Значит меняется только один байт. Аналогично поступаем с другой замусоренной инструкцией. Потом записываем нопы, декрементируем, возвращаясь на начало буфера и записываем содержимое на место старой команды. И так пока не проштудируем весь код. Остальной мусор (мелочи жизни) вычищается плагином analyse this!. Возможно, способ который я избрала довольно примитивен, так как эта последовательность может принадлежать, например другой инструкции... и тогда мы занопим совсем не то, что надо. Но опять же писала скрипт для этого крекми, объем кода в котором совсем не большой. И для данного конкретного случая он вполне подходит.
После работы скрипта код выглядит так

Код:

00401023  |> \830424 09                ADD DWORD PTR SS:[ESP],9
00401027  \.  C3                      RETN
00401028      15                      DB 15
00401029  .  6A 00                    PUSH 0                                              ; /lParam = NULL
0040102B  .  68 45104000              PUSH CrackME.00401045                                ; |DlgProc = CrackME.00401045
00401030  .  6A 00                    PUSH 0                                              ; |hOwner = NULL
00401032  .  6A 25                    PUSH 25                                              ; |pTemplate = 25
00401034  .  50                      PUSH EAX                                            ; |hInst
00401035  .  90                      NOP                                                  ; |
00401036  .  FF15 C4204000            CALL DWORD PTR DS:[<&USER32.DialogBoxParamA>]        ; \DialogBoxParamA
0040103C  .  6A 00                    PUSH 0                                              ; /ExitCode = 0
0040103E  .  90                      NOP                                                  ; |
0040103F  .  FF15 86204000            CALL DWORD PTR DS:[<&KERNEL32.ExitProcess>]          ; \ExitProcess
00401045  .  55                      PUSH EBP

Красотища)))))
Теперь поиск всех вызовов имортируемых функций (Search for -> All intermodular call's).
Отлично. Найдены все функции. А их всего ничего

USER32.DialogBoxParamA
kernel32.ExitProcess
USER32.GetDlgItemTextA
USER32.GetDlgItemTextA
SHLWAPI.StrToIntA
USER32.MessageBoxA
USER32.EndDialog

И проанализировано верно)
Что ж. Пора запускать программу. Жмем f9. Высвечивается диалог для ввода имени и пароля. Теперь назначение по крайне мере двух вызовов функции GetDlgItemTextA нам ясно) Первый читает имя, второй-код. Это я узнала, загрузив файл в Restorator и посмотрев идентификаторы эдитов для ввода имени 101 (в хексе -65h), а пароля-102 (66 в хексе). Теперь смотрим на параметры функции GetDlgItemTextA. В первом случае как раз в качестве ид-а идет 65h, а во втором - 66h. После прочтения имени и пароля вызывается функция StrToIntA, принимающая в качестве параметра указатель на строку, которую требуется перевести в число.
В качестве параметра в данном случае-строка с паролем. Из этого можно сделать вывод, что пароль состоит из цифр. Потом берется имя юзера и с ним проводятся следующие манипуляции

Код:

004010B9  .  52                      PUSH EDX      ;строка с паролем
004010BA  .  90                      NOP                                             
004010BB  .  FF15 1E214000            CALL DWORD PTR DS:[<&SHLWAPI.StrToIntA>]            ;Великая функция
004010C1  .  31C9                    XOR ECX,ECX
004010C3  .  21CB                    AND EBX,ECX
004010C5  .  8D75 E0                  LEA ESI,DWORD PTR SS:[EBP-20] ;строка с именем
004010C8  >  8A1E                    MOV BL,BYTE PTR DS:[ESI] ;дальше манипуляции с именем
004010CA  .  84DB                    TEST BL,BL
004010CC  .  74 08                    JE SHORT CrackME.004010D6
004010CE  .  31D9                    XOR ECX,EBX
004010D0  .  C1C1 04                  ROL ECX,4
004010D3  .  46                      INC ESI
004010D4  .^ EB F2                    JMP SHORT CrackME.004010C8
004010D6  >  31DB                    XOR EBX,EBX
004010D8  .  66:39C1                  CMP CX,AX ; ключевое сравнение
004010DB  .  0F94C3                  SETE BL ; false-true
004010DE  .  8B049D F4114000          MOV EAX,DWORD PTR DS:[EBX*4+4011F4]
004010E5  .  35 78563412              XOR EAX,12345678
004010EA  .  FFE0                    JMP EAX

Особое внимание надо уделить инструкции SETE. Данная инструкция работает следующим образом. Сначала перед ней идет сравнение,она анализирует флаги и устанавливает значение своего операнда (bl) логическим значением 0 или 1 (false или true). То есть, если cx будет равен ax- после выполнения инструкции sete в bl окажется "истина", то есть 1. Ну и следующая инструкция напрямую зависит от значения ebx

Код:


004010DE  .  8B049D F4114000          MOV EAX,DWORD PTR DS:[EBX*4+4011F4]

Если ebx будет 1 - значение в еах окажется 12744695, потом оно проксорится следующей инструкцией

Код:


004010E5  .  35 78563412              XOR EAX,12345678

и получим адрес перехода... И прыгнем на него инструкцией jmp eax. В хорошем случае прыгаем на 004010ED. Вплохом случае ebx будет равен 0, в eax мы получим 12744721, а после ксора - совершенно другой адрес перехода - 00401159.

И еще. Сначала я, как порядочная, ввела свой семисимвольный ник, но крекми наглым образом проигнорировал этот факт и урезал до 6-ти символов.... Хм( Присмотрелась к функции чтения имени

Код:


00401073  .  6A 07                    PUSH 7                                              ; /Count = 7
00401075  .  8D55 E0                  LEA EDX,DWORD PTR SS:[EBP-20]                        ; |
00401078  .  52                      PUSH EDX                                            ; |Buffer
00401079  .  6A 65                    PUSH 65                                              ; |ControlID = 65 (101.)
0040107B  .  FF75 08                  PUSH DWORD PTR SS:[EBP+8]                            ; |hWnd
0040107E  .  90                      NOP                                                  ; |
0040107F  .  FF15 C8204000            CALL DWORD PTR DS:[<&USER32.GetDlgItemTextA>]        ; \GetDlgItemTextA
00401085  .  6A 00                    PUSH 0

Нда. Если бы в count было 8- ник бы прочитался нормально)
В общем далее вникать в суть происходящего дальше не имеет смысла, так как у нас есть функция StrToIntA. Как она работает-известно.
Что должно получится-нам тоже известно - это содержимое регистра cx.
Возьмем, например, число 1111 и переведем его в хекс. Получим 457. Введем 1111 в поле пароль и посмотрим что вернет функция
StrToIntA. А вернет она..... то самое 457... Это означает, что в поле пароля мы должны ввести число, полученое путем
перевода регистра cx в десятичную систему. Все элементарно=)

Вот и все...

desTiny 25.03.2008 14:16

Crackmy2 by Xserg
 
CrackMe:
Цель: найти верный пароль
Сложность: автором позиционируется как "сложно"
Коментарий: предупреждаю - буду краток.
link: http://ifolder.ru/5872875
Решение:

Запускаем крякми... Имя, пароль... Вводим чён-ть... Need good password.
Запускаем под Олей - debug detected.
Ну что ж, будем лечить. Трассируем программу с начала.
Узнаём начало DialogProc 401810. Оставляем бряк после DialogBoxIndirectParamA, так как там мы окажемся после ввода пароля, а так же ставим бряк на саму DialogProc. Пускаем программу (F9) брякаемся, идём - всё пролетает до RETN 10. Поэтому жмём ещё раз F9. Видим - по адресу 401836 создаётся таймер. Смотрим процедуру таймера - ничего интересного она не делает - что-то увеличивает, что-то уменьшает и тп. Значит ясно - нужен для антиотладки. Отключать его нельзя, ибо вероятна проверка на его запущенность.
Соображаем... А давайте поставим огромный интервал? Доходим до самого вызова, а дальше в стеке правим в 12FC88 100ms на сколько влезет. Например 0FFFFFFF ms (не забываем писать байты в обратном порядке!).
Теперь снимаем бряк с 401810 - ничего нового уже не происходит, происходит обыкновенная прорисовка окна.

Посмотрим дальше. Видим взятие имени и пароля.
Теперь либо ставим бряк на попадающиеся на глаза команды по адресам типа 40185F - GetDlgItem, то есть те команды, которые мы только что проскачили, трассируя программу до формы, либо ищем эти команды в прыжках на импортируемые функции, видим там Local call from xxxx и ставим бряк на xxxx.
F9.
Вводи чтон-ть в логин и пасс, нажимаем ок. Брякаемся на GetDlgItem. Трассируем... До EndDialog ничего интересного нет. После EndDialog трассировать бесполезно, поэтому нажимаем F9 и ждём пока сработает наш бряк в 401802.
Сработал! Трассируем (заходя во все call'ы)... Видим создание потока. Наверняка тоже для антиотладки!
Смотрим ThreadFunction... 40101D... Там что-то страшное... ладно, поставим туда бряк и попробуем запуститься по F9.
Трассируя её, смотрим, что у нас там происходит. Проверяется содержимое dword [403063], если там ноль, то выводим сообщение про отладчик, иначе уменьшаем это значение на 1. Сейчас там 1F. А давайте поставим FFFFFFFF. Итак, у нас есть очень много времени, чтобы закончить это крякми. Снимем бряки и запустим его выполняться. (В опциях надо поставить, чтобы все ошибки обрабатывала программа). Ждём-с... Замечательно! Пишет, что пасс неверен, но ничего не говорит про отладчик!


Посмотрим на код - в нём появились команды типа MessgeBox, появились слова "need good password"
Запомним то место, где мы видим MessageBox(401567), перезапустим программу и, сделав те же манипуляции с таймером и с числом 1F, поставим бряк Memory Breakpoint on write на 401567. Смотрим после каждого бряка, что там. Однажды видим появился call! Смотрим назад - там "Congratulations", а перед этим проверка пароля. Нехитрый анализ показывает, что прыжок в случае неверного пароля идёт с 4014AD. Поставим бряк на предшествующий CMP. Жмём F9... Попадаем как раз туда. теперь осталось собрать пароль :) Побайтно смотрим буковки из AL...

Для имени Ter я получил пароль X43Vr3U6qQ74Up9Q. Закрываем всё, запускаем крякми, вставляем буковки...
Цитата:

You are a good crack'er!


Время: 06:42