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

Автор: Fess

Target: Irfan View 3.17

Tools:

  • Some brains
  • TRW2000/Soft-Ice
  • Win32Dasm 8.93
  • Pe Identifier 0.7 beta
  • Распаковщик AsPack'a 2000
  • ProcDump32 1.6.2
  • Hex-редактор (QView, Hiew)
  • Delphi

Все, кроме мозгов, можно найти на www.exetools.com

Вступление

Как это начиналось:

Было скучно и решил я накатать какой-нибудь тьториал. Так вот давным-давно, когда я мало что умел нашел я код (подсмотрел в отладчике) для этой замечательной проги. Теперь же, поскольку я еще кой-чему научился, решил сбацать еще и кей-ген. Кстати, регистрационный код подходит к любой версии Виева, так что... ВПЕРЕД!!!

Что за прога:

Очень рульный (ИМХО: самый лучший) просмотрщик графических файлов, поддерживает кучу форматов, с помощью плагинов еще больше, быстрый, удобный, занимает мало места и главное БЕСПЛАТНЫЙ.

Отсебятина

Вы можете подумать, что я дурак ломаю бесплатную программу, но это не так! Первое: В программе все-таки предусмотрена регистрация для зарегист- рированных юзеров тех.поддержка и всякое такое. Второе: если вы сломаете эту прогу, вы тем самым не нарушите ничьи авторские права, поскольку ее стоимость равна 0$. Третье: для крэкера не важна цена, а важен процесс взлома, моральные ощущения от этого, я еще напишу об этом в каком-нибудь крэкерско-филосовском мануале "Зачем ломают программы или крэкеры на воле" Как сказал Гагарин: Пое-е-ехали! (ЗЫ: вообще-то, он сказал ЧТО У ВАС ТАМ КРЫШИ ПОЕ-Е-ЕХАЛИ?!!)

Начало

Хм.Хм.

Перво-наперво определимся, чем защищена программа, для этого проверим не запакована ли она. Для этих целей воспользуемлся программой PeIdentifier она правильно определила это AsPack 2000 для снятия воспользуйтесь любым доступным унпакером (я пользовался сборкой UN-PACK 2.2). После этого, если вы любите дизассемблировать в Win32Dasm'e, а я люблю, то придется немного подправить таблицу импорта для этого воспользуемся программой ProcDump32 нажимает PE Editor открываем распакованый файл. Нажимаем на кнопку Section и появляемся в разделе секций. По содержащимся секциям можно предположить, что это C++ (первая секция .text). Вот ее-то и правим в поле Section Characteristics заносим E0000020 вместо C0000040. Теперь можно дизассемблировать и текст дизассемблируется нормально.

Листинг дизассемблера есть проверим программу, заходим в Help\Registration и вводим любое имя и любой код, должна появится строка Incorrect Registration, если вы угадали и у Вас такая строка не появилась, то искренне Вас с этим поздравляю и направляю в казино в Лас-Вегасе (если выйграете меня не забывайте!).

Строка есть, заходим в Win32Dasm и ищем ее там, и откудова она вызывается, для этого заходим в раздел строк и ищем там нашу, а после того как найдете, нажмите на нее два раза и окажитесь здесь


:00446587 8D8C2474140000  lea ecx, dword ptr [esp+00001474]
:0044658E 8D942474130000  lea edx, dword ptr [esp+00001374]
:00446595 51              push ecx
:00446596 52              push edx
:00446597 E8640BFEFF      call 00427100
:0044659C 83C408          add esp, 00000008
:0044659F 85C0            test eax, eax
:004465A1 752C            jne 004465CF

* Possible StringData Ref from Data Obj ->"Incorrect registration !"
                                  |
:004465A3 A138F94B00      mov eax, dword ptr [004BF938]

Из этого участка кода ясно видно, что по адресу 446597 находится процедура проверки. И в ecx и edx в нее вносятся введенный код и введенный ключ.

Давайте все же определимся, что нам предстоит сделать нам предстоит три раза взломать эту программу тремя разными способами:

Способы:

  • Подсмотр настоящего кода
  • Создание кейгена на основе самой программы
  • Написание кейгена на Делфи

Подсмотр настоящего кода

Самый простой и самый применяемый начинающими метод взлома, поскольку подсмотреть легко и вроде настоящий ключ на руках. (В первый раз я ее так и сломал)

Сперва заходим в процедуру проверки и идем в самый конец, а там смотрим, что творится перед выходом!

Запускаем любой отладчик, я использовал TRW 2000, поскольку перезагружаться не хотелось.


:00427370 8D542410   lea edx, dword ptr [esp+10]
:00427374 52         push edx
:00427375 E816130700 call 00498690
:0042737A 83C404     add esp, 00000004
:0042737D 33C9       xor ecx, ecx
:0042737F 3BE8       cmp ebp, eax
:00427381 5F         pop edi
:00427382 5E         pop esi
:00427383 0F94C1     sete cl

Тут все просто, если сравнение верное, то в ecx будет 1, если нет то 0. Но что заносится параметром edx в процедуру? Давайте посмотрим для этого запускаем отладчик, ставим бряк на этот адрес bpx 427374. Вводим любое имя и код, я использовал Fess и 11002233. Когда вываливаемся, набираем команду d edx и что мы видим? Какие-то циферки, списываем их себе на бумажку, у меня 202382506, еще раз запускаем и вводим их вместо регистрационного номера. И что мы видим - МЫ ЗАРЕГЕНЫ!!! УРА!!! Вот и все, можете успокоится, а мы продолжаем.

Создание кейгена на основе самой программы

Я уже много раз описывал эту процедуру, но для Вас повторюсь еще разок. Так вот вы уже видели, как подсмотреть регистрационный номер в отладчике, а теперь мы сделаем, чтобы программа сама выдавала его в MessageBox'е. Для этого нужно, посмотреть hex-представление каманды MessageBoxA. Заходим в таблицу импорта в Win32Dasme щелкаем на USER32.MessageBoxA и видим


:0040114F 50           push eax

* Reference To: USER32.MessageBoxA, Ord:0195h
                            |
:00401150 FF1554834A00 Call dword ptr [004A8354]
:00401156 33C0         xor eax, eax

Hex-представление FF1554834A00 запишем, нам это еще пригодится. Теперь будем думать, как это осуществить на вот этом участке кода, знаком * в конце строки, я помечу, чем можно здесь пожертвовать и выкинуть


:00427374 52         push edx        *
:00427375 E816130700 call 00498690   *
:0042737A 83C404     add esp, 00000004   *
:0042737D 33C9       xor ecx, ecx    *
:0042737F 3BE8       cmp ebp, eax    *
:00427381 5F         pop edi
:00427382 5E         pop esi
:00427383 0F94C1     sete cl         *

Готово осталось написать последовательность команд не длиннее, заданного участка кода. Я решил сделать вот так: (Описание параметров функции MessageBoxA смотри в WinAPI или других моих тьюториалах)


 6A00         push 00000000
 52           push edx
 52           push edx
 6A00         push 00000000
 FF155483A400 Call MessageBoxA
 90           nop
 5F           pop edi
 5E           pop esi
 31C9         xor ecx,ecx
 90           nop

Вы, наверно, думаете почуму я заменил sete cl на xor ecx,ecx и nop очень просто, если так оставить, то получится обыкновенный патч и он зарегистрируется на введенное вами имя и чтобы повторно использовать этот кейген вам понадобится лезть в каталог WINDOWS и удалять из файла I_VIEW32.INI информацию о регистрации, а можно и весь файл, а тут она никогда не зарегистрируется и всегда можно генерить новые ключи.

Начинаем. Заходим в hex-редактор набираем для поиска такую строку 52E81613070083C404. Почему такую? Нам надо найти место правки кода, для этого мы переписываем достаточное кол-во байт исходного кода и ищем, где они встречаются. У меня все нашлось на 26774. Теперь начиная с этого места переписываем представление всех команд из блока выше. Если все выполнено правильно, то теперь после ввода регистрационных данных, в окне отображается истинный ключ для вашего имени. Гейген готов, но хочется большего, поэтому продолжаем.

Написание кейгена на Делфи

Для написания гейгена надо полностью исседовать код процедуры генерации и воссоздать его заново, это обычно делается в отладчике, но поскольку вы читаете этот тьюториал, я рядом с кодом буду писать, что он делает.


..
:0042710E E87D150700    call 00498690 <- Процедура проверки введенного s/n, чтобы были
                                         только цифры
..
:00427125 F2     repnz         <- Проверка длинны имени
:00427126 AE     scasb
:00427127 F7D1   not ecx
:00427129 49     dec ecx       <- В ecx длинна имени
:0042712A 85C9   test ecx, ecx <- Если длинна равна 0, то уходим из процедуры
:0042712C 7E17   jle 00427145
..
:0042712E 0FBE0C32 movsx ecx, byte ptr [edx+esi] <- Берем символ имени
:00427132 03D9     add ebx, ecx <-Добавляем его к ebx
:00427134 8BFE     mov edi, esi
:00427136 83C9FF   or ecx, FFFFFFFF
:00427139 33C0     xor eax, eax
:0042713B 42       inc edx <- Увеличиваем счетчик (переход на след.символ)
:0042713C F2       repnz
:0042713D AE       scasb
:0042713E F7D1     not ecx
:00427140 49       dec ecx
:00427141 3BD1     cmp edx, ecx <- Пока счетчик не будет равен длинне имени повтояем
:00427143 7CE9     jl 0042712E
              (Общий смысл фрагмента сумма всех кодов имени в ebx)
..
:00427145 B804010000    mov eax, 00000104 <- eax=104
:0042714A 6A0A          push 0000000A
:0042714C 2BC3          sub eax, ebx      <- eax=eax-ebx(сумма кодов)
:0042714E 99            cdq
:0042714F 33C2          xor eax, edx      <- eax = eax xor edx (edx=FFFFFFFF)
:00427151 2BC2          sub eax, edx      <- eax = eax-edx
:00427153 054C010000    add eax, 0000014C <- eax = eax+14C
:00427158 8BD0          mov edx, eax      <- edx= eax
:0042715A C1E203        shl edx, 03       <- edx = shl edx, 3
:0042715D 2BD0          sub edx, eax      <- edx= edx-eax
:0042715F 8D0C90        lea ecx, dword ptr [eax+4*edx]  <- ecx= eax+4*edx
:00427162 8D542414      lea edx, dword ptr [esp+14]     <- edx=адрес памяти
:00427166 52            push edx                        <- заносим адрес памяти в стек
:00427167 8D3448        lea esi, dword ptr [eax+2*ecx]  <- esi= eax+2*ecx
:0042716A C1E603        shl esi, 03                     <- esi = shl esi,3
:0042716D 56            push esi                        <- заносим esi в стек
:0042716E E84DE60700    call 004A57C0                   <- по адресу в edx выдается символьное
                                                        представление числа в esi
:00427173 83C40C        add esp, 0000000C
:00427176 81FE3F420F00  cmp esi, 000F423F               <- Если esi больше, то переход
:0042717C 0F87ED000000  ja 0042726F
...

:00427182 8A4C2414     mov cl, byte ptr [esp+14] <- Берем 5 символ кода
:00427186 8A442415     mov al, byte ptr [esp+15] <- Берем 6 символ
:0042718A 8A542413     mov dl, byte ptr [esp+13] <- Берем 4 символ
:0042718E 884C2416     mov byte ptr [esp+16], cl <- На место 7 пишем 5
:00427192 8A4C2411     mov cl, byte ptr [esp+11] <- Берем 2
:00427196 88442418     mov byte ptr [esp+18], al <- На место 9 пишем 6
:0042719A 8A442412     mov al, byte ptr [esp+12] <- Берем 3
:0042719E 884C2412     mov byte ptr [esp+12], cl <- На место 3 пишем 2
:004271A2 8B4C2418     mov ecx, dword ptr [esp+18] <- Берем 9
:004271A6 88442413     mov byte ptr [esp+13], al <-На место 4 пишем 3
:004271AA 81E1FF000000 and ecx, 000000FF
:004271B0 88542415     mov byte ptr [esp+15], dl <- На место 6 пишем 4
:004271B4 8B542414     mov edx, dword ptr [esp+14] <- Берем 5
:004271B8 8D0489       lea eax, dword ptr [ecx+4*ecx] eax=ecx+4*усч
:004271BB 81E2FF000000 and edx, 000000FF
:004271C1 C1E003       shl eax, 03    <- eax= shl eax,3
:004271C4 2BC1         sub eax, ecx   <- eax=eax-ecx
:004271C6 8BCA         mov ecx, edx   <- ecx=edx
:004271C8 C1E105       shl ecx, 05    <- ecx= shl ecx,5
:004271CB 2BCA         sub ecx, edx   <- ecx=ecx-edx
:004271CD 8D1449       lea edx, dword ptr [ecx+2*ecx] <-edx=ecx+2*ecx
:004271D0 2BC2         sub eax, edx   <- eax=eax-edx
:004271D2 99           cdq
:004271D3 8BC8         mov ecx, eax   <- ecx=eax
:004271D5 33CA         xor ecx, edx   <- ecx=ecx xor edx
:004271D7 2BCA         sub ecx, edx   <- ecx=ecx-edx
:004271D9 8D0489       lea eax, dword ptr [ecx+4*ecx] <- eax=ecx+4*ecx
:004271DC C1E003       shl eax, 03  <- eax=shl eax,3
:004271DF 2BC1         sub eax, ecx <- eax=eax-ecx
:004271E1 B909000000   mov ecx, 00000009 <- ecx=9
:004271E6 99           cdq
:004271E7 F7F9         idiv ecx  <- eax=eax/ecx остаток в edx
:004271E9 8B442413     mov eax, dword ptr [esp+13] <- Берем 4 символ
:004271ED 25FF000000   and eax, 000000FF
:004271F2 83C230       add edx, 00000030      <- edx=edx+30
:004271F5 88542417     mov byte ptr [esp+17], dl <- Пишем 8-ым символом

А дальше вы и сами разберетесь, просто иначе место много займет, а там все аналогично. Я ту попарился минут с 40 (не сложно, а писанины много) и соорудил такой кейген. Создаете новое приложение, ставите на форму два компонента Edit с именами Edit1 (для ввода имени) и Edit2 (для вывода ключа) {они по умолчанию такие}, ставите одну кнопку. Нажимаете на нее два раза, вы окажитесь в процедуре обработки нажатия на кнопку, теперь замените ее моей и разбирайтесь:


procedure TForm1.Button1Click(Sender: TObject);
Var
  B,B1:Byte;
  Z:Dword;
  S:String;
begin
  Z:=0;
  For B:=1 To Length(Edit1.Text) Do Z:=Z+ORD(Edit1.Text[B]); // Сумма кодов имени
  asm
   xor edx,edx;
   mov dl,B;
   mov ebx,Z;
   mov eax,104h;
   sub eax,ebx;
   cdq;
   xor eax,edx;
   sub eax, edx;
   add eax, 14Ch;
   mov edx, eax;
   shl edx, 03;
   sub edx, eax;
   mov ecx, eax
   imul edx,edx,4;
   add ecx, edx;
   mov ebx, eax;
   imul ecx,ecx,2
   add ebx,ecx;
   shl ebx, 03;
   mov Z, ebx;
  end;
  S:=IntToStr(Z)+'   ';
  if Z<$0F423F then
   begin
    S[9]:=S[6];
    s[7]:=S[5];
    S[6]:=S[4];
    S[4]:=S[3];
    S[3]:=S[2];
    B:=Ord(S[5]);
    B1:=Ord(S[9]);
    asm
    xor ecx,ecx;
    mov cl,B1;
    xor edx,edx;
    mov dl, B;
    imul eax, ecx,5;
    shl eax, 03;
    sub eax, ecx;
    mov ecx, edx;
    shl ecx, 05;
    sub ecx, edx;
    imul edx, ecx,3;
    sub eax, edx;
    cdq;
    mov ecx, eax;
    xor ecx, edx;
    sub ecx, edx;
    imul eax,ecx,5;
    shl eax, 03;
    sub eax, ecx;
    mov ecx, 00000009;
    cdq;
    idiv ecx;
    add dl,30h;
    mov B,dl;
    end;
    S[8]:=CHR(B);
    B:=Ord(S[4]);
    B1:=Ord(S[6]);
    asm
    xor eax,eax;
    mov al,B;
    imul edx,eax,3
    shl edx, 04;
    sub edx, eax;
    xor eax,eax;
    mov al, B1;
    imul ecx, eax,9;
    imul ecx,ecx,4;
    add eax, ecx;
    add eax, eax;
    add eax,edx;
    cdq;
    xor eax, edx;
    sub eax, edx;
    imul ecx, eax,9;
    imul ecx,ecx,4;
    add eax,ecx;
    mov ecx, 9;
    shl eax, 1;
    cdq;
    idiv ecx;
    add dl,30h;
    mov B,dl;
    end;
    S[5]:=CHR(B);
    B:=ORD(S[1]);
    B1:=ORD(S[2]);
    asm
    xor ecx,ecx;
    mov cl, B;
    imul eax, ecx,3;
    imul eax, eax,9;
    shl eax, 1;
    sub eax, ecx;
    xor edx,edx;
    mov dl, B1;
    mov ecx, edx;
    shl ecx, 03;
    sub ecx, edx;
    imul edx, ecx,5;
    sub eax, edx;
    cdq;
    mov ecx, eax;
    xor ecx, edx;
    sub ecx, edx;
    imul eax, ecx,3;
    imul eax, eax,9;
    shl eax, 1;
    sub eax, ecx;
    cdq;
    mov ecx, 09;
    idiv ecx
    add dl, 30h;
    mov B,dl
   end;
   S[2]:=CHR(B)
  end
  else
   begin
   S[9]:=S[7];
   S[7]:=S[6];
   S[6]:=S[5];
   S[4]:=S[3];
   S[3]:=S[2];
   B:=ORD(S[7]);
   B1:=Ord(S[9]);
   asm
   xor eax,eax
   mov al, B;
   mov ecx, eax
   shl ecx, 06
   sub ecx, eax
   xor eax,eax
   mov al, B1
   imul eax, eax,9
   shl eax, 02
   sub eax, ecx
   mov ecx, 09
   cdq
   xor eax, edx
   sub eax, edx
   imul eax, eax,9
   shl eax, 02
   cdq
   idiv ecx
   add dl, 30h
   mov b,dl
   end;
   S[8]:=CHR(B);
   B:=ORD(S[5]);
   B1:=ORD(S[4]);
   asm
   xor eax,eax
   mov al, b
   add eax, 00000020
   mov edx, eax
   shl edx, 03
   sub edx, eax
   imul edx,edx,4
   add eax,edx
   imul ecx, eax,3
   xor eax,eax
   mov al, B1
   imul edx, eax,5
   shl edx, 03
   sub edx, eax
   mov eax,ecx
   add edx,edx
   add eax,edx
   cdq
   xor eax, edx
   sub eax, edx
   mov ecx, eax
   shl ecx, 03
   sub ecx, eax
   imul ecx,ecx,4
   add eax, ecx
   mov ecx, 00000009
   imul eax, eax,3
   cdq
   idiv ecx
   add dl, 30h
   mov B,dl
   end;
   S[5]:=CHR(B);
   B:=ORD(S[1]);
   B1:=ORD(S[2]);
   asm
   xor eax,eax
   mov al,b
   mov edx, eax
   shl edx, 03
   sub edx, eax
   imul edx,edx,4
   add eax, edx
   xor edx,edx
   mov dl, B1
   mov ecx, edx
   shl ecx, 04
   add ecx, edx
   shl eax, 1
   imul ecx, ecx,5
   sub eax, ecx
   cdq
   xor eax, edx
   sub eax, edx
   mov edx, eax
   shl edx, 03
   sub edx, eax
   imul edx,edx,4
   add eax, edx
   shl eax, 1
   cdq
   mov ecx, 09
   idiv ecx
   add dl, 30h
   mov B,dl
   end;
   S[2]:=CHR(b);
   end;
   Edit2.Text:=S;
end;

Процедура генерации опробована и проверена!! Так что ошибок нет. Сдалана на Delphi 4.5, я думаю, подойдут все версии, начиная с 4.

Будем надеятся, что вы все поняли из выше сказанного, если что-то непонятно пишите на мыло. Я помогу!

Спасибо за интерес к моему творчеству!

Удачи в Reversing Engeneering!

Послесловие

Спасибо автору за предоставленный для исследования продукт. Было очень интересно.

Господа, если у Вас есть деньги, то скиньте немного автору, поскольку продукт и правда замечательный. Так же выражаю ему благодарность за интересное времяпрепровождение.

Вредный совет

 Если ночью Вы не спите,
 Жмете клавиши на клаве,
 А соседи ваши ночью
 Очень любят отдыхать.
 То купите себе принтер
 Матричный, обыкновенный
 И тогда они узнают,
 Что такое тишина."
	           (Fess)

Все ругательства отправлять в null
Все остальное на lomovskih@yandex.ru

З.Ы. Возможны ошибки. Взлом игры 3 минуты. Написание статьи 50 минут, видите как старался.

With best wishes Fess

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