Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Исследование Winamp Skin Maker v1.2

Оформил: DeeCo
Автор: http://www.cracklab.narod.ru

Предисловие Сама защита в этой программе - почти никакая, и все обычно ограничиваются нахождением кода для своего имени, а кейгенов я до сих пор не видел. Однако алгоритм генерации ключа если не сложный, то довольно муторный, и разбираться в не хочется. Но кейген писать придётся. Воспользуемся особенностью нашего человека - нестандартным мышлением.

Приступим к делу. Что нам сейчас нужно:
Softice 4.*
Icedump 6.* - только для того, чтобы копировать текст из Softice"а на диск.
Можете заменить его W32Dasm и ручкой с бумагой.
Hiew 32 6.5
Delphi 4-6 (6 recommended).
ResHacker, WinRar.

Итак, запускаем программу(перед этим Softice и т.д.).
Идем на Help->About->Register. Вводим РИ. Ставим брейкпоинт на hmemcpy.
Жмем OK. Попадаем в Softice. Снимаем брейкпоинт.
Теперь жмем F12 до тех пор, пока не вылезем в Skinner.exe. После этого наблюдаем следующее:
--------------------------------------------------byte--------------PROT---(0)--
-вырезано-
-------------------------------------------------------------------------PROT32-
 -вырезано-
016F:00406D7A        MOV       EDI,[USER32!GetDlgItemTextA]       
016F:00406D80         PUSH      ESI                                
016F:00406D81 CALL    EDI  (То есть USER32!GetDlgItemTextA) Name>      
016F:00406D83  LEA       EAX,[ESP+38]                       
016F:00406D87   PUSH      29                                 
016F:00406D89   PUSH      EAX                                
016F:00406D8A  PUSH      000003FD                           
016F:00406D8F   PUSH      ESI                                
016F:00406D90 CALL      EDI (То есть USER32!GetDlgItemTextA) Our reg.#>  
016F:00406D92    LEA       EAX,[ESP+0C]                       
016F:00406D96       PUSH      EAX                                
016F:00406D97 CALL      00407E30                            
016F:00406D9C      ADD       ESP,04                            
016F:00406D9F       MOV       EBX,EAX           

------------------------------------SKINNER!.text+5D64--------------------------
Break due to BPX KERNEL!HMEMCPY  (ET=1.26 seconds)                              
:bc *                                                                           
:/Screendump C:\f1.dos
Далее:
016F:00406DA1         LEA       EAX,[ESP+38]                      
016F:00406DA5         PUSH      EAX                                
016F:00406DA6  CALL  00407D00 
016F:00406DAB        ADD       ESP,04                             
016F:00406DAE         MOV       EDI,EAXТеперь в EDI результат (код)! 
016F:00406DB0          TEST      EDI,EDI        
016F:00406DB2           JNZ       00406DEB                            
И вот:
016F:00406DEB    CMP    ED(наш>,EBX(правильный>  
016F:00406DED      JNZ       00406E24
А EBX мы последний раз меняли ещё в первом случае!
Теперь остаётся "всего-то" узнать значение EBX программным способом для Skinner.exe в момент сравнения кодов :)!
Я видел где-то старый некрасивый способ, который предполагает спровоцировать сбой, Windows 95/98 покажет вам табличку с регистрами и сообщением об ошибке. Потом надо взять значение EBX , перевести в десят. систему и это будет код. Нудно, некрасиво, и не работает под другими ОС.
Я нашел способ, который проще и лучше. На это I've spent 24 hours.
Мне всегда нравилась функция ExitProcess(ExitCode:Cardinal). Говорят, что под Win X в ExitCode можно ставить любое число.
Пишем свой код после: (using Hiew)
016F:00406D97 CALL      00407E30 
016F:00406D9C      ADD       ESP,04
push eax
call Kernel32!ExitProcess
это ассемблируется до:
50+FF1548244300,
причем второе я подсмотрел в Imported Functions в W32Dasm, а 1-е написал сам Hiew.
Ну что, теперь программа по нажатию О.К. просто закрывается. Надо как-нибудь получить то, что она передаёт из EAX. Воспользуемся Delphi 6.
Sources:
program Project1;
uses Windows, SysUtils, Messages; //необходимый миниму>
{$APPTYPE GUI} //У нас Gui-приложение>
{$R Icon.res} //иконку возьме>
{$R Dlg.res} //и диалог тож>

var
  rc: Cardinal; //код на>
  StartupInfo: TStartupInfo; //необ. с>
  ProcessInfo: TProcessInformation; //необ. с>

procedure StartProcess(hWnd: THandle); //процедура наш>
begin
  rc := 0;
  FillChar(StartupInfo, Sizeof(StartupInfo), #0); //заполняем с>
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_SHOWDEFAULT;
  CreateProcess(nil, Pchar('WSV1.20.KG.exe'), nil, nil, false,
    NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo); //создаем процес>
  WaitforSingleObject(ProcessInfo.hProcess, INFINITE); //ждем завершени>
  GetExitCodeProcess(ProcessInfo.hProcess, rc); //получаем ко>
  if rc<
  >
  0 then
  begin
    SetDlgItemText(hWnd, 108, Pchar(IntToStr(rc)));
    SetDlgItemText(hWnd, 0, Pchar('Here is your Reg.#: '));
  end
  else //если кто-то не может ввести свое имя, то..>
    SetDlgItemText(hWnd, 108, Pchar('Incorrect name.'));
end;

function DialogProc(hWnd: THandle; Msg: Integer; wParam, lParam: Integer): Bool;
  stdcall;
begin
  if Msg = WM_INITDIALOG then
    RESULT := true //нужно для создания диалог>
  else if Msg = WM_CLOSE then
    ExitProcess(0) //если нас захотят закрыт>
  else if (Msg = WM_COMMAND) and (Wparam = 106) then //если нажали нашу кнопк>
  begin
    ShowWindow(hWnd, SW_Hide);
    StartProcess(hWnd);
    ShowWindow(hWnd, SW_Show);
  end
  else
    Result := false;
end;

//===========Не знаю зачем я это сделал================/>

procedure MessageBox(Wnd: Integer; Text: PChar; Caption: PChar; Typ: Integer);
  stdcall;
  external 'user32.dll' name 'MessageBoxA';
//=====================//
begin
  //А это официальное начало программы :-)>
  DialogBoxParam(GetModuleHandle(nil), PChar('DIALOG_0'), 0, @DialogProc, 0);
end.
Файл ресурсов:
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * * * * *
file: D: \SLAVAPROJECTS\DELPHI\SK_KG\DLG.RC
Generated by Resource Builder 1.0.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * * * * /
// Below are important 3 lines, don't change them!
/ *
OutputExt = RES
* /
DIALOG_0 DIALOG 127, 65, 180, 86
STYLE DS_ABSALIGN | DS_MODALFRAME | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX |
  WS_POPUP |WS_CAPTION |WS_BORDER |WS_DLGFRAME
CAPTION "
KeyGen for Winamp Skin Maker 1.20 "
FONT 8, "
MS Sans Serif"
LANGUAGE LANG_NEUTRAL, 0
begin
  CONTROL "
  Start generating - >
  >
  "
  , 106, "
  BUTTON"
  , BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP, 7, 62, 165, 20
    CONTROL "
Crack - type
  : KeyGen Author: wersion E - mail: wcrkgroup2002@mail.ru "
  , 65535, "
  STATIC"
  , BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP, 10, 7, 159, 26
    CONTROL "
  "
  , 108, "
  EDIT"
  , BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|WS_BORDER, 92, 43, 83, 12
    CONTROL "
  Here will be your Reg.#0"
  , 65536, "
  STATIC"
  , BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP, 11, 44, 75, 10
end
Все! Сие приложение занимает 40 кб, упакованное UPX"ом 20 кб. да, а нам нужен ещё и исходный Exe-file(388 кб - написано на MSVC). дабы уменьшить его размер, произведём следующие изменения. дойдём до окна About, затем поставим брейкпоинт на DialogBoxParamA
Жмем Register и попадаем в SoftIce, жмем F12.
016F:00406B8E    JNZ       004068A6                        
016F:00406B94     MOV       ESI,[ESP+78]                      
                                
016F:00406B9A   PUSH      00406D00                           
016F:00406B9F    MOV       EAX,[0042FB70]                     
016F:00406BA4   PUSH      ESI                                
016F:00406BA5   PUSH      0000008A                           
016F:00406BAA  PUSH      EAX                                
016F:00406BAB  CALL      [USER32!DialogBoxParamA]
Хорошо бы с самого начала прыгнуть на Но пусть программа сделает все свои дела, подгрузит ресурсы и т.д., а потом уж и покажет диалог.
Найдем call, который показывает основное окно. для этого загрузим программу в SymBol Loader. Будем заходить по F8 во все call'ы, после которых происходит показ окна, пока не дойдем до конечного, который занимается CreateWindowExA и т.д. Вот он:
  50                  PUSH      EAX
016F:00401D14  56                  PUSH      ESI                                
016F:00401D15  E8B6010000          CALL      00401ED0
С адреса впишем прыжок на . (A) вы уже сделали.
Теперь подредактируйте сей диалог в Skinner.exe. А потом вырежьте все ненужные ресурсы окромя иконок и его. Упакуйте все WinRar"ом.
Вот мой скрипт.
Setup=Start.exe 
Silent=1
Overwrite=1
TempMode
Эпилог Итак, что мы получили?
Кейген в 120 кб. Учитывая, что он содержит ориг. программу, а сам написан на Delphi, то это неплохо.
Чему мы научились?
Рационально работать. Первыми(я, по крайней мере) сделали кейген к этой программе.
Created by Wersion. 11/10/02. E-mail: wcrkgroup2002@mail.ru
Вопросы/пожелания/угрозы - приветствуются.

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay