![]() |
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс |
Новичку | Ссылки | Программирование | Интервью | Архив | Связь |
Shareware программа - готовый генератор ключей. Обзор защиты L0pht Crack 4Обсудить статью на форумеХорошая подборка видеоуроков, инструментов крэкера, книг и статей - здесь. Автор: (ry0 <cryo@cydem.org.ua> Привет! Таймаут окончен, я вернулся.На этот раз я хотел рассказать вам о защите @stake LC4. Мы разберемся с процедурой генерации правильного серийника, само собой построим генератор, а также рассмотрим, как можно сделать (при помощи небольшого хирургического вмешательства, конечно же) так, чтобы программа, по сути, ломала сама себя (так что и разбираться с алгоритмом генерации не надо!). Оборудование.SoftICE .IDA, W32Dasm .LordPE .hutch's MASM32 (ничто из перечисленного в рекламе, уверен, не нуждается) Итак, начнем...Найти необходимую часть кода труда не составит. Ищем в дизасме (W32Dasm) ссылку на строку "You have entered an invalid code" и поднимаемся по jump'ам немного выше: :00411BEB 8B4500 mov eax, dword ptr [ebp+00] :00411BEE 8D4C2420 lea ecx, dword ptr [esp+20] :00411BF2 51 push ecx :00411BF3 50 push eax :00411BF4 E8B722FFFF call sub_403EB0 ;генерация с/н ;на выходе ECX держит адрес правильного ключа :00411BF9 8B07 mov eax, dword ptr [edi] :00411BFB 8D542428 lea edx, dword ptr [esp+28] :00411BFF 52 push edx :00411C00 50 push eax :00411C01 E8955C0100 call sub_42789B ;проверка правильности :00411C06 83C410 add esp, 00000010 :00411C09 85C0 test eax, eax :00411C0B 7523 jne 00411C30 ;перейти к выдаче сообщения об ошибке :00411C0D 8B07 mov eax, dword ptr [edi] :00411C0F 50 push eax :00411C10 6850134700 push 00471350 :00411C15 685C134700 push 0047135C :00411C1A 8BCE mov ecx, esi :00411C1C 899E3C010000 mov dword ptr [esi+0000013C], ebx :00411C22 E89AB20300 call sub_44CEC1 :00411C27 53 push ebx :00411C28 53 push ebx :00411C29 6834144700 push 00471434 :00411C2E EB07 jmp 00411C37 :00411C30 53 push ebx :00411C31 53 push ebx :00411C32 6800144700 push 00471400 ;"You have entered an invalid code..." :00411C37 E8D3720300 call sub_448F0FЧто ж, в принципе, взлом закончен успешно :) В SoftICE трассируем до адреса 00411BF9, а там "d ecx". Регистрируем и радуемся... Но дело в том, что защита LC4 построена таким образом, что Serial Number генерится все время новый, и после переустановки винды придется ломать прогу заново. Поэтому надо-таки замутить универсальный crack. Если разбираться с алгоритмом вам совсем не интересно, а патчить не хочется (дабы сохранить .exe в первозданной форме) могу предложить выход: создать загрузчик, который заставит программу саму выдать вам правильный регистрационный ключ. На том и порешили... Алгоритм таков: 1. Загрузчик запускает и патчит образ lc4.exe в ОЗУ. 2. Юзер вводит ложный Unlock Code и давит OK. 3. L0pht генерит у себя в нутре правильный Unlock Code, и выдает его (благодаря патчу) вместо сообщения об ошибке. 4. Загрузчик завершает работу, оставляя LC4 наедине с собой. Давайте его реализуем. Во-первых, мы решили, что правильный с/н будет выводиться вместо строки "You have entered an invalid code...". Она дислоцируется по адресу 00471400h, а смещение строки в файле равно .71400h. Итак, нам нужно будет копировать строку, на которую указывает регистр ECX после выполнения процедуры sub_403EB0 в буффер по адресу 00471400h. Чтобы сообщение выглядело красивее, можно разбавить его чем-то типа "Try again. Your valid Unlock Code is: ". В этом случае строку с настоящим серийником следует прописывать по адресу 00471425h. Во-вторых, нам нужно добавить некоторое количество байт, образующих собой ту самую процедуру копирования правильного серийника в буффер по адресу 00471400h. Для этого с помощью LordPE нужно найти свободное место. Я решил добавить код в секцию .text начиная с адреса 0045DF00h. Переход к процедуре осуществим с адреса 00411C30h - это начало вызова сообщения об ошибке. Т. о. меняем :00411C30 push ebx :00411C31 push ebx :00411C32 push 00471400 на :00411C30 jmp 0045DF00h :00411C35 nop :00411C36 nop А сама процедура будет выглядеть примерно так: push esi ;сохраняем регистры push edi ;мы ведь не хотим вылететь с ошибкой:) mov esi, ecx ;исходная строка mov edi, 00471425h ;буффер _label1: ;а теперь копируем lodsb stosb cmp al, 0 jnz _label1 pop edi ;восстанавливаем регистры pop esi push ebx ;восстанавливаем часть кода, push ebx ;которую пропатчили ранее. push 00471400h jmp 00411C37h ;и возвращаемся в основную программу.Ну, кажется ничего не забыл. Ниже приведен пример загрузчика в синтаксисе для hutch's MASM32. файл RSRC.RC ----------------------вырезать------------------------------ #include "E:\masm32\Templates\Resource.h" /* укажите свой путь */ DLG_MAIN DIALOGEX 0, 0, 150, 50 STYLE DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "LC4 KeyRevealer" FONT 8, "Verdana" { CONTROL "Load 'n' patch LC4", 201, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 5, 5, 140, 19 , 0x00020000 CONTROL "close", 1004, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 5, 26, 140, 19 , 0x00020000 } ----------------------вырезать------------------------------ файл lc4pp.asm ----------------------вырезать------------------------------ .586 .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\comdlg32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\comdlg32.lib WndProc proto :DWORD, :DWORD, :DWORD, :DWORD .data DlgMainName BYTE 'DLG_MAIN',0 OpenFileFilter BYTE 'L0phtCrack 4 (lc4.exe)',0,'lc4.exe',0,0 wrongSN BYTE 'You have entered an invalid code. Please try again.',0 yourSN BYTE 'Try again. Your valid Unlock Code is: ',0 originalcode BYTE 53h,53h,68h,00h,14h,47h,00h,0E8h,0D3h,72h,03h,00h patch2 BYTE 56h, 57h, 8Bh, 0F1h, 0BFh, 26h, 14h, 47h, 00h, 0ACh,\ 0AAh, 3Ch, 00h, 75h, 0FAh, 5Fh, 5Eh, 53h,\ 53h, 68h, 00h, 14h, 47h, 00h, 0E9h, 18h, 3Dh, 0FBh, 0FFh patch1 BYTE 0E9h,0CBh,0C2h,04h,00h,90h,90h errStr BYTE 'Patching failed.',0 errCapt BYTE 'Error',0 of OPENFILENAME <> startupinfo STARTUPINFO <> processinfo PROCESS_INFORMATION <> sa SECURITY_ATTRIBUTES <> sd SECURITY_DESCRIPTOR <> .data? hInstance DWORD ? dwErrCode DWORD ? hFile DWORD ? OpenFilePath BYTE 256 dup(?) buffer BYTE 256 dup(?) .code start: invoke GetModuleHandle, 0 mov hInstance, eax invoke DialogBoxParam, hInstance, addr DlgMainName, 0, addr WndProc, 0 invoke ExitProcess, eax WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD .IF uMsg == WM_INITDIALOG mov of.lStructSize, SIZEOF OPENFILENAME push hWnd pop of.hWndOwner push hInstance pop of.hInstance mov of.lpstrFile, offset OpenFilePath mov of.nMaxFile, 256 mov of.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or\ OFN_EXPLORER or OFN_HIDEREADONLY or OFN_NOCHANGEDIR .ELSEIF uMsg == WM_CLOSE invoke EndDialog, hWnd, 0 .ELSEIF uMsg == WM_COMMAND mov eax, wParam mov edx, eax shr edx, 16 .IF edx == BN_CLICKED .IF ax == 201 mov of.lpstrFilter, offset OpenFileFilter invoke GetOpenFileName, addr of .IF eax == TRUE invoke CreateProcess, addr OpenFilePath, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, addr startupinfo, addr processinfo .IF eax != 0 ;ждем, пока LC4 полностью загрузится и будет готов к работе. invoke WaitForInputIdle, processinfo.hProcess, INFINITE lea edi, buffer invoke ReadProcessMemory, processinfo.hProcess, 411C30h, edi, 12, 0 ;проверяем частично правильность прочитанных данных cmp dword ptr [edi], 685353h jnz _err ;читаем данные. Должна быть строка "You have entered an inva..." invoke ReadProcessMemory, processinfo.hProcess, 471400h, addr buffer, 56, 0 invoke lstrcmp, addr buffer, addr wrongSN cmp eax, 0 jnz _err ;пишем строку "Try again. Your valid Unlock Code is: " invoke WriteProcessMemory, processinfo.hProcess, 471400h, addr yourSN, 38, 0 cmp eax, 0 jz _err ;патчим память - ставим переход на новую процедуру invoke WriteProcessMemory, processinfo.hProcess, 411C30h, addr patch1, 7, 0 cmp eax, 0 jz _err ;патчим память - записываем новую процедуру invoke WriteProcessMemory, processinfo.hProcess, 45DF00h, addr patch2, 31, 0 cmp eax, 0 jz _err invoke SendMessage, hWnd, WM_CLOSE, 0, 0 .ELSE _err: invoke MessageBox, hWnd, addr errStr, addr errCapt, MB_ICONERROR or MB_OK invoke TerminateProcess, processinfo.hProcess, 0 invoke CloseHandle, processinfo.hProcess .ENDIF .ENDIF .ELSEIF ax == 1004 invoke SendMessage, hWnd, WM_CLOSE, 0, 0 .ENDIF .ENDIF .ELSE xor eax, eax ret .ENDIF mov eax, TRUE ret WndProc endp end start ----------------------вырезать------------------------------Хорошо, но вам все-таки интересно, что же представляет собой процедура генерации серийника в L0pht'е? Давайте посмотрим... Как отмечалось ранее, за генерацию отвечает процедура sub_403EB0. Углубляемся... :00403EB0 83EC0C sub esp, 0000000C :00403EB3 8B442410 mov eax, dword ptr [esp+10] :00403EB7 6A08 push 00000008 :00403EB9 40 inc eax :00403EBA 50 push eax :00403EBB 8D4C2408 lea ecx, dword ptr [esp+08] :00403EBF 51 push ecx :00403EC0 E8AB1E0200 call sub_425D70 :00403EC5 8D54241C lea edx, dword ptr [esp+1C] :00403EC9 52 push edx :00403ECA 8D442410 lea eax, dword ptr [esp+10] :00403ECE 6888FA4600 push 0046FA88 :00403ED3 50 push eax :00403ED4 C644242000 mov [esp+20], 00 :00403ED9 E865240200 call sub_426343 :00403EDE 8B442428 mov eax, dword ptr [esp+28] :00403EE2 3552AE376F xor eax, 6F37AE52 :00403EE7 8BC8 mov ecx, eax :00403EE9 C1E11B shl ecx, 1B :00403EEC C1E805 shr eax, 05 :00403EEF 03C8 add ecx, eax :00403EF1 51 push ecx :00403EF2 894C242C mov dword ptr [esp+2C], ecx :00403EF6 8B4C2430 mov ecx, dword ptr [esp+30] :00403EFA 6880FA4600 push 0046FA80 :00403EFF 51 push ecx :00403F00 E8EC230200 call sub_4262F1 :00403F05 33C0 xor eax, eax :00403F07 83C430 add esp, 00000030 :00403F0A C3 retПосмотрим на процедурку повнимательней. У нас имеется три функции и несколько строк математики. Разберемся сначала с функциями. Сказать особо нечего: sub_425D70 - это API функция strncpy sub_426343 - это API функция sscanf sub_4262F1 - это API функция sprintf Все три расположены в библиотеке msvcrt.dll. И маньяки из @stake, уверен, хотели скрыть этот факт. Извращенцы! Они вырезали функции из .dll'ки и прописали их в коде L0pht'а! Но тем не менее нельзя не признать оригинальности решения. Но не будем удаляться от темы. Вот примерное описание функций. Подробности смотрите в MSDN. 1.strncpy синтаксис: push nCount push lpOut push lpIn call strncpy Тут все ясно. Функция копирует nCount символов из буффера по адресу lpOut в буффер по адресу lpIn. 2.sscanf синтаксис: ... push lpArgument1 push lpFmt push lpOut call sscanf Функция читает данные из буффера по адресу lpOut, колдует над ними в соответствии с заданным форматом (у нас это '%08x') и пишет результат в буффер по адресу lpArgument1. Количество аргументов может быть различным от одного и более (как в wsprintf). Тип аргумента зависит от формата. 3.sprintf синтаксис: ... push lpArgument1 push lpFmt push lpOut call sprintf Подобно wsprintf форматирует и записывает набор символов из буффера по адресу lpOut в другой буффер, адресуемый параметром lpArgument1. Аргументов может быть несколько, в зависимости от формата. В LC4 эта API функция вызывается с форматом '%04x', а lpOut указывает на место, где по завершении процедуры будет лежать правильный Unlock Code.Предельно просто, не так ли? Ниже привожу сырье генератора в синтаксисе для hutch's MASM32. файл RSRC.RC ----------------------вырезать------------------------------ #include "E:\masm32\Templates\Resource.h" /* укажите свой путь */ DLG_MAIN DIALOGEX 0, 0, 186, 55 STYLE DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "LC4 Keygen" FONT 8, "VERDANA" { CONTROL "", 101, EDIT, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 61, 5, 120, 10 , 0x00020000 CONTROL "", 102, EDIT, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 61, 17, 120, 10 , 0x00020000 CONTROL "Serial Number:", -1, STATIC, SS_LEFT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 5, 54, 10 CONTROL "Unlock Code:", -1, STATIC, SS_LEFT | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE | WS_GROUP, 5, 17, 54, 10 CONTROL "Generate", 201, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 61, 32, 55, 19 , 0x00020000 CONTROL "close", 1004, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 128, 32, 55, 19 , 0x00020000 } ----------------------вырезать------------------------------ файл lc4kg.asm ----------------------вырезать------------------------------ .586 .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib WndProc proto :DWORD, :DWORD, :DWORD, :DWORD .data DlgMainName BYTE 'DLG_MAIN',0 scanFormat BYTE '%08x',0 printFormat BYTE '%04x',0 _sprintf BYTE 'sprintf',0 _sscanf BYTE 'sscanf',0 szLibrary BYTE '\msvcrt.dll',0 szMsgCaption BYTE '!error',0 szLibNotFound BYTE 'msvcrt.dll library not found.',13,10,\ 'Terminating...',0 .data? hInstance DWORD ? szPath BYTE 256 dup(?) hDLL DWORD ? sprintf DWORD ? sscanf DWORD ? .code start: invoke GetModuleHandle, 0 mov hInstance, eax ;--- ПОДГРУЖАЕМ БИБЛИОТЕКУ msvcrt.dll --- lea esi, szPath invoke GetSystemDirectory, esi, 244 invoke lstrlen, esi add esi, eax invoke lstrcpy, esi, addr szLibrary invoke LoadLibrary, addr szPath .IF eax != 0 mov hDLL, eax invoke DialogBoxParam, hInstance, addr DlgMainName, 0, addr WndProc, 0 invoke FreeLibrary, hDLL .ELSE invoke MessageBox, 0, addr szLibNotFound, addr szMsgCaption, MB_ICONERROR or MB_OK .ENDIF invoke ExitProcess, 0 WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD LOCAL snBuffer[16]:BYTE LOCAL ucBuffer[16]:BYTE .IF uMsg == WM_INITDIALOG ;--- ПОЛУЧАЕМ АДРЕСА НУЖНЫХ API ИЗ msvcrt.dll --- invoke GetProcAddress, hDLL, addr _sprintf mov sprintf, eax invoke GetProcAddress, hDLL, addr _sscanf mov sscanf, eax .ELSEIF uMsg == WM_CLOSE invoke EndDialog, hWnd, 0 .ELSEIF uMsg == WM_COMMAND mov eax, wParam mov edx, eax shr edx, 16 .IF edx == BN_CLICKED .IF ax == 201 ;--- ГЕНЕРАЦИЯ СЕРИЙНИКА --- lea esi, snBuffer invoke GetDlgItemText, hWnd, 101, esi, 16 add esi, 1 mov byte ptr [esi+8], 0 lea edi, ucBuffer push edi lea eax, scanFormat push eax push esi call sscanf mov eax, [edi] xor eax, 6F37AE52h mov ecx, eax shl ecx, 1Bh shr eax, 5 add ecx, eax push ecx lea edx, printFormat push edx push edi call sprintf invoke SetDlgItemText, hWnd, 102, edi .ELSEIF ax == 1004 invoke SendMessage, hWnd, WM_CLOSE, 0, 0 .ENDIF .ENDIF .ELSE xor eax, eax ret .ENDIF mov eax, TRUE ret WndProc endp end start ----------------------вырезать------------------------------Так вот! Порой мне кажется, что создав нечто великолепное, люди так хотят побыстрее на этом заработать, что забывают обо всем другом на свете. Жажда богатства и славы затмевает рассудок, убивает душу. Алчность - путь к нищете. adios. P.S. Crack 'em all Дата: август l6, 2OO3 Автор: (ry0 E-mail: cryo#cydem.org.ua ICQ #: l79S2lSOS Материалы находятся на сайте https://exelab.ru ![]() |
Вы находитесь на EXELAB.rU |
![]() |