Вторник, 26.11.2024, 21:13
Приветствую Вас Гость | RSS
Главная | | Регистрация | Вход
Меню сайта
Форма входа
Поиск
Календарь
«  Февраль 2012  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
272829
Архив записей
Наш опрос
Оцените мой сайт
Всего ответов: 20
Мини-чат
Друзья сайта
  • Заказ Художник
  • Рыбалка
  • Новости
  • Наш университет io-96
  • Железо и другие
  • Наш Counter-Strike
  • Google ot Turbokherson
  • Google ot Turbokherson87
  • Android
  • Программы и Софт
  • Программирование
  • Лечение здоровья
  • О Ремонт компьютер
  • Наш сайт Turbokherson
  • Программирование ICQ 378204653 от Turbokherson
    Главная » 2012 » Февраль » 21 » Легальный взлом как разминка для ума
    11:38
    Легальный взлом как разминка для ума
    IT-шники часто придумывают себе упражнения для ума, пытливый ум постоянно требует разминки. Хочу рассказать об одном из самых жестких и спорных способах – взлом специально защищенных программ-головоломок (Часто их называют crackme).

    Одно из мест, где такие головоломки собраны — crackmes.de.

    Здесь находятся много интересных программ, на которых можно испробовать свои силы по взлому. Никакого криминала – программы специально написаны для этой цели (так называемые crackme и reverseme);

    Часто любят говорить «Все защиты можно взломать». Поковыряв некоторые из crackme вы возможно измените своё мнение.


    Итак приступим:


    Общая схема работы многих crackme — а давайте какую-то процеду в коде зашифруем, и «верный-неверный пароль» — в зависимости от сделанного хеша из расшифрованных этим паролем данных?

    Или как вариент — заюзаем SEH (Structured Exception Handling – механизм обработки аппаратных и программных исключений), в который положим месседжбокс о плохом пароле, перед этим передав управление на наш «расшифрованный» код, при этом если пароль – правильный, то в расшифрованном коде будут «верные» опкоды команд, а если нет, то процессор сгенерит исключение о неверном опкоде и «кошерно» задействует SEH, в котором у нас стоит уведомление об ошибке. Надо сказать, что в общем этот вариант не «святой» поскольку после расшифровки возможны и «полувалидные» опкоды- к примеру jmp-команда за пределами этой нашей процедуры.

    Но на первых порах и этого достаточно.

    Итак берём крекми отсюда: crackmes.de/users/sharpe/unlockme_crackme_8_by_sharpe/download или отсюда:
    crackmes.de/users/sharpe/unlockme_crackme_7_by_sharpe/download (седьмой, кстати, не взломан пока) и загружаем в дебаггер- я использовал олю (OllyDBG)- програмка – очень маленькая- сегмент кода всего 0х2В6=694 байта, очень легко найти часть кода отвечающего за чтение пароля:

    0040107F |. 3D F3030000 CMP EAX,3F3
    00401084 |. 75 4E JNZ SHORT 004010D4 
    00401086 |. 6A 21 PUSH 21 ; /Count = 21 (33.)
    00401088 |. 68 88314000 PUSH 403188 ; |Buffer = eight.00403188
    0040108D |. 68 F1030000 PUSH 3F1 ; |ControlID = 3F1 (1009.)
    00401092 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
    00401095 |. E8 04020000 CALL 0040129E ; \GetDlgItemTextA
    0040109A |. 83F8 07 CMP EAX,7 здесь сравниваем длину пароля
    0040109D |. 76 1F JBE SHORT 004010BE переход на смерть
    0040109F |. 83F8 20 CMP EAX,20 здесь тоже сравниваем длину пародя
    004010A2 |. 73 1A JNB SHORT 004010BE 
    004010A4 |. E8 D9000000 CALL 00401182 преобразователь пароля
    004010A9 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] 
    004010AC |. E8 FD000000 CALL 004011AE расшифровщтк кода
    004010B1 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] 
    004010B4 |. E8 61010000 CALL 0040121A не интересно
    004010B9 |. E9 85000000 JMP 00401143 ; eight.00401143
    004010BE |> 6A 30 PUSH 30 а здесь прыгать не надо)))
    004010C0 |. 68 34314000 PUSH 403134 ; |Title = "-=[ Unlock Code Error"
    004010C5 |. 68 4A314000 PUSH 40314A ; |Text = "The entered Unlock Code is invalid.
    004010CA |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
    004010CD |. E8 D8010000 CALL 004012AA ; \MessageBoxA
    004010D2 |. EB 6F JMP SHORT 00401143 ; eight.00401143


    Итак, на основании этого видим что длина пароля долна быть в диапазоне 8-32 знака, и если это так то прыгаем в функцию преобразования изначального пароля:

    00401182 /$ 57 PUSH EDI
    00401183 |. 33FF XOR EDI,EDI
    00401185 |. BE 88314000 MOV ESI,403188 ; здесь в регистр пишем указатель на пароль 
    0040118A |. B9 20000000 MOV ECX,20
    0040118F |. C705 A8314000 >MOV DWORD PTR DS:[4031A8],0 ;здесь мы запишем преобразован «хеш»
    00401199 |> AC /LODS BYTE PTR DS:[ESI]
    0040119A |. 85C0 |TEST EAX,EAX
    0040119C |. 74 08 |JE SHORT 004011A6 ; eight.004011A6
    0040119E |. 8BC8 |MOV ECX,EAX ;здесь мы сохраним «хеш» с пароля
    004011A0 |. 03F8 |ADD EDI,EAX ;процедура преобразования пароля
    004011A2 |. D3C7 |ROL EDI,CL ; процедура преобразования пароля
    004011A4 |.^EB F3 \JMP SHORT 00401199 ; eight.00401199
    004011A6 |> 893D A8314000 MOV DWORD PTR DS:[4031A8],EDI; сохраняем и выходим 
    004011AC |. 5F POP EDI
    004011AD \. C3 RETN


    А вот здесь живет расшифровщик кода:

    004011AE /$ 55 PUSH EBP
    004011AF |. 8BEC MOV EBP,ESP
    004011B1 |. 83EC 04 SUB ESP,4
    004011B4 |. 68 88314000 PUSH 403188 ; здесь вновь проверяем длину пароля 
    004011B9 |. E8 C2000000 CALL 00401280 ; но это – не обязательно
    004011BE |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
    004011C1 |. 837D FC 01 CMP DWORD PTR SS:[EBP-4],1
    004011C5 |. 77 16 JA SHORT 004011DD ; eight.004011DD
    004011C7 |. 6A 30 PUSH 30 
    004011C9 |. 68 34314000 PUSH 403134 ; |Title = "-=[ Unlock Code Error"
    004011CE |. 68 4A314000 PUSH 40314A ; |Text = "The entered Unlock Code is invalid.
    004011D3 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
    004011D6 |. E8 CF000000 CALL 004012AA ; \MessageBoxA
    004011DB |. EB 1E JMP SHORT 004011FB ; eight.004011FB
    004011DD |> B8 49114000 MOV EAX,401149 ; А вот здесь начинается расшифровка пароля
    004011E2 |. B9 7F114000 MOV ECX,40117F
    004011E7 |. 2BC8 SUB ECX,EAX 
    004011E9 |. 33DB XOR EBX,EBX
    004011EB |> 8B1418 /MOV EDX,DWORD PTR DS:[EAX+EBX]
    004011EE |. 3315 A8314000 |XOR EDX,DWORD PTR DS:[4031A8]; как видем простая ксор-функция
    004011F4 |. 891418 |MOV DWORD PTR DS:[EAX+EBX],EDX
    004011F7 |. 43 |INC EBX
    004011F8 |. 49 |DEC ECX
    004011F9 |.^75 F0 \JNZ SHORT 004011EB ; и выходим
    004011FB |> C9 LEAVE
    004011FC \. C2 0400 RETN 4


    Итак, теперь понятно: но как найти правильный хеш-код?
    Перебором?

    Это очень долго: надо сначала расшифровать, потом посчитать «энтропию» полученного кода и возможно код с минимумом «энтропии»- рабочий, но для этого надо писать или использовать уже написанные дизассемблерные движки;
    а можно использовать SEH, в теле которого прописать код брумфорсера, но тогда даже одна «ложно-правильная» инструкция может полностю изменить верный ход исполнения программы.
    Но я заметил, что хоть программа написана на чистом ассемблере, но автор всё-же много использовал в своём коде «открытие» стека, поэтому давайте думать, что первые правильные 4 байта в нашем «зашифрованном» коде:

    PUSH EBP
    MOV EBP,ESP
    

    Значение: 0х55, 0х8В, 0хЕС

    А сейчас(до прохождения процедуры шифрования) значения: 0x66, 0x71, 0x77, но мы же помним (можем посмотреть) свойства «ксор» функции и увидеть что тогда конечный хеш станет извесным:
    Не забываем о «little-endian» соглашении:

    77 71 66 ^
    АА ВВ СС ^
    ВВ СС ^
    СС
    **********
    ЕС 8В 55


    Итак, посчитав это дело в «Калькуляторе» мы видем, что СС=0х33; ВВ=0хС9; АА=0х61,
    Полученная последовательность: ХХ61C93.

    Последний байт, к сожалению, пришлось искать перебором с использованием «self-keygening»a (патчинга бинарника), и в конце получаем: E961C933.

    А расшифрованная процедура в действительности содержит много мусора(«обфускация»)
    Но «открытие стека» нас спасло, и расшифрованая процедура (в теле):
    00401149 $ 55 PUSH EBP
    0040114A . 8BEC MOV EBP,ESP
    0040114C . D3C8 ROR EAX,CL
    0040114E . 58 POP EAX
    0040114F . EB 04 JMP SHORT 00401155 ; eight.00401155
    00401151 D6 DB D6
    00401152 FE DB FE
    00401153 . 32C9 XOR CL,CL
    00401155 > BE 9C314000 MOV ESI,40319C ; ASCII "Secret: Marius!"
    0040115A . C706 53656372 MOV DWORD PTR DS:[ESI],72636553
    00401160 . C746 04 65743A>MOV DWORD PTR DS:[ESI+4],203A7465
    00401167 . C746 08 4D6172>MOV DWORD PTR DS:[ESI+8],6972614D
    0040116E . C746 0C 757321>MOV DWORD PTR DS:[ESI+C],217375
    00401175 . EB 00 JMP SHORT 00401177 ; eight.00401177
    00401177 > 58 POP EAX
    00401178 . FFE0 JMP EAX
    0040117A F7 DB F7
    0040117B ED DB ED
    0040117C 12 DB 12
    0040117D DA DB DA
    0040117E 3F DB 3F ; CHAR '?'
    0040117F 4E DB 4E ; CHAR 'N'
    00401180 40 DB 40 ; CHAR '@'
    00401181 C4 DB C4


    Всё что делает ета процедура-записывает слово: Secret: Marius! по соответственому указателю.
    Далее осталось узнать исходный пароль – Ну, тут – брутфорс вам в помощь))))

    Процедуру преобразования можна «ripp»ать у нашей програмы и оформить это дело как ассемблерную вставку.

     mov dword ptr [znach], 0 
     xor edi, edi
     mov esi, [str1]
     m:
     lodsb
     test al, al
     jz m1
     mov ecx, eax
     add edi, eax
     rol edi, cl
     jmp m


    Да, исходный пароль-005sj[Vg

    Только, если брутфорс будете писать под какую-то экзотику типа cuda или под шейдеры- помните там нет инструкции циклического сдвига- rol eax, 5 и ёё надо заменить на два простых сдвига (один влево и один вправо) и потом «or» над полученным; реализация в виде: #define ROT (n, m) (((n)<<(m))|((n)>>(32-(m))))
    В следующих постах вы узнаете о других интересных способах взлома неломаемых защит.

    PS. Автор статьи (ash — его пока нет на хабре) попросил меня опубликовать эту статью.
    Просмотров: 666 | Добавил: Turbokherson | Рейтинг: 0.0/0
    Всего комментариев: 0
    Имя *:
    Email *:
    Код *:
    Создать бесплатный сайт с uCozCopyright MyCorp © 2024