Нахождение регистрационного кода тремя способами для 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
|