ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > Программирование > Реверсинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Solutions
  #1  
Старый 09.01.2007, 23:48
Аватар для taha
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

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


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

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

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

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

..::[FaTmiKE 2oo5]::.. CrackMe #2
  #2  
Старый 09.01.2007, 23:49
Аватар для taha
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

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

hiddCrackMeImp
  #3  
Старый 09.01.2007, 23:51
Аватар для taha
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

Репутация: 1077
По умолчанию 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 и ток потом до меня допёрло, для чего нужна была эта функция. Я просто не ждал, что регистрация будет проходить так необычно))
 
Ответить с цитированием

First CrackMe by ProTeuS
  #4  
Старый 09.01.2007, 23:53
Аватар для taha
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

Репутация: 1077
По умолчанию 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
 
Ответить с цитированием

  #5  
Старый 10.01.2007, 13:21
Аватар для _Great_
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию

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!

Последний раз редактировалось _Great_; 10.01.2007 в 13:24..
 
Ответить с цитированием

CrackMe #3 by anorganix
  #6  
Старый 19.01.2007, 16:15
Аватар для taha
taha
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме:
2472378

Репутация: 1077
По умолчанию 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.
 
Ответить с цитированием

  #7  
Старый 05.02.2007, 01:32
Аватар для Ra$cal
Ra$cal
Постоянный
Регистрация: 16.08.2006
Сообщений: 640
Провел на форуме:
1354067

Репутация: 599


По умолчанию

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';
	}
}
 
Ответить с цитированием

CrackME by _taha_
  #8  
Старый 13.04.2007, 09:00
Аватар для taha
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

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

  #9  
Старый 03.08.2007, 14:41
Аватар для 0x0c0de
0x0c0de
Постоянный
Регистрация: 25.05.2007
Сообщений: 448
Провел на форуме:
4226446

Репутация: 1564
Отправить сообщение для 0x0c0de с помощью ICQ
По умолчанию

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 в десятичную систему. Все элементарно=)

Вот и все...

Последний раз редактировалось 0x0c0de; 03.08.2007 в 18:34..
 
Ответить с цитированием

Crackmy2 by Xserg
  #10  
Старый 25.03.2008, 14:16
Аватар для desTiny
desTiny
Reservists Of Antichat - Level 6
Регистрация: 04.02.2007
Сообщений: 1,152
Провел на форуме:
3008839

Репутация: 1502


По умолчанию 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!
__________________
Bedankt euch dafür bei euch selbst.

H_2(S^3/((z1, z2)~(exp(2pi*i/p)z1, exp(2pi*q*i/p)z2)))=Z/pZ

Последний раз редактировалось desTiny; 25.03.2008 в 20:21..
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Украдены 40 миллионов номеров кредитных и дебетных карт Visa и MasterCard DRON-ANARCHY Мировые новости 0 22.07.2005 19:49



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ