Все нижесказанное, помеченное *, является моими советами в дизассемблировании в среде WinDasm.
Сколько я не лазил в этой проге, не нашел, где генерируется рег. ключ, поэтому не отчаявшись (самое главное! никогда не бросать начатое!), я решил не обойти саму защиту, а сделать так, чтобы прога сама зарегистрировалась (хе-хе).
Ломать будем в WinDasm v8.93, т.к. я считаю маловато про WinDasm в этих статьях сказано, а ведь
такая вещица классная, многие с нее начинали. Многого знать не надо ну кроме базисов, вроде основные в статье Dr.Golova описаны.
TOOLZ:
WinDasm 8.93, Hiew 6.11, Far (или NC), ну и самаOpera 3.61
Ну, вернемся к нашим бар.. Opera.
Заходим в браузер… Мда непорядок, первое, что бросается в глаза — это «unregistered» вверху экрана, да и еще, если успели заметить, при загрузке идет Registered to : unregistered. Вот и начнем отсюда. Выходим из проги, заходим в Far( NC или что там у вас), в директории Opera, копируем файл opera.exe в opera.xxx и opera.w32
*Я советую использовать именно эти расширения, т.к. они являются наиболее удобными, где *.xxx — backup; *.w32 — этот файл мы будем дизассемблировать; а в opera.exe будем с помощью HIEW вносить изменения. Т.е. если что-нибудь запорем, то дорога в «copy opera.xxx opera.exe» ;))
Так, выходим из Far по Alt+Tab, т.к. он нам еще пригодится. Заходим в WinDasm и дизассемблируем файл opera.w32………………….. ;)))))))))))))))
*Следующий шаг — это просмотр SDR (т.е. String Data Reference), в меню Refs — последний пункт.
Здесь то мы и должны найти наш «unregistered».
*Если прога объемная, как в этом случае с Оперой, то удобно будет скопировать все references кнопкой Copy All.
Ура нашли: String Resource ID=21428: » (unregistered)», чтобы попасть в это место достаточно дважды щелкнуть по строке.
*ОЧЕНЬ ВАЖНО! В проге может быть не одно это место, а несколько, так что щелкайте несколько раз, и смотрите на адреса.
Смотрим первое совпадение:
* Referenced by a (U)nconditional or (C)onditional Jump at Address: <- Первый переход |:0045F8EF(C) | :0045F91F 381D58F55200 cmp byte ptr [0052F558], bl :0045F925 7535 jne 0045F95C :0045F927 BE80000000 mov esi, 00000080 :0045F92C 56 push esi :0045F92D 57 push edi * Possible Reference to String Resource ID=20092: "Opera 3.61" | :0045F92E 687C4E0000 push 00004E7C :0045F933 8BCD mov ecx, ebp :0045F935 E8850D0000 call 004606BF :0045F93A 57 push edi :0045F93B E8E0A60800 call 004EA020 :0045F940 59 pop ecx :0045F941 2BF0 sub esi, eax :0045F943 A30CF55200 mov dword ptr [0052F50C], eax :0045F948 56 push esi :0045F949 8D8058F55200 lea eax, dword ptr [eax+0052F558] :0045F94F 50 push eax * Possible Reference to String Resource ID=21428: " (unregistered)" <---- Это наш "unregistered" | :0045F950 68B4530000 push 000053B4 :0045F955 8BCD mov ecx, ebp :0045F957 E8630D0000 call 004606BF ************ ТОЖЕ ВАЖНО! ************ Q: Почему в WinDasm все пишут основные строчки внизу, а не вверху, это неудобно! A: Т.к. Программа идет сверху вниз ;), а нам нужно посмотреть ЧТО вызвало этот "unregistered" Q: До какого момента мы смотрим вверх, где останавливаться??? A: Обычно в WinDasm идем вверх до первого jne/je ; jl/jbl; test; cmp ... или до Reference Jump. *************************************** На данном этапе необходимо остановиться и задуматься, а то ли это место, ведь посмотрите: есть и "unregistered", и "Opera 3.61", и переходов между ними нет, а может это всего лишь: "Opera 3.61 (unregistered)" в главном окне вверху... ИСТИННУ ГЛАГОЛИШЬ. Смотрим другой адрес (надеюсь, еще не забыли то правило, насчет нескольких мест): * Possible Reference to Dialog: SPLASH, CONTROL_ID:2B27, "Opera 3.60" <--- Странно, 3.60, что разработчики по этому поводу думают? | :00495F64 68272B0000 push 00002B27 :00495F69 FF7508 push [ebp+08] :00495F6C FFD6 call esi :00495F6E 8D8540FBFFFF lea eax, dword ptr [ebp+FFFFFB40] :00495F74 50 push eax * Possible Reference to Dialog: SPLASH, CONTROL_ID:2B25, " " | :00495F75 68252B0000 push 00002B25 :00495F7A FF7508 push [ebp+08] :00495F7D FFD6 call esi :00495F7F 8D856CFCFFFF lea eax, dword ptr [ebp+FFFFFC6C] :00495F85 50 push eax * Possible Reference to Dialog: SPLASH, CONTROL_ID:2B26, " " | :00495F86 68262B0000 push 00002B26 :00495F8B FF7508 push [ebp+08] :00495F8E FFD6 call esi :00495F90 393D64005300 cmp dword ptr [00530064], edi <---Сравнивание с edi :00495F96 752A jne 00495FC2 <--- "ПЕРвЫй переХод" :00495F98 68FF000000 push 000000FF :00495F9D 8D85C4FEFFFF lea eax, dword ptr [ebp+FFFFFEC4] :00495FA3 50 push eax * Possible Reference to String Resource ID=21428: " (unregistered)" <--- Вот ОН наш REAL unreg. | :00495FA4 68B4530000 push 000053B4 :00495FA9 FF3570FA5200 push dword ptr [0052FA70] :00495FAF FFD3 call ebx :00495FB1 8D85C5FEFFFF lea eax, dword ptr [ebp+FFFFFEC5] :00495FB7 50 push eax МДАСССССС, спокуха, это все фигня на самом деле. ТАК, как всегда, ловим первый попавшийся переход, вот и он: :00495F90 393D64005300 cmp dword ptr [00530064], edi :00495F96 752A jne 00495FC2 <--- "ПЕРвЫй переХод" *Je/Jne - Unconditional(jump if equal)/Conditional(jump if not equal); здесь важно понять эти действия: "Если [00530064] НЕРАВНО edi, то перейти на ПРАВИЛЬНУЮ РЕГИСТРАЦИЮ". (Действительно запутывающе). Смотрите, до него идет сравнивание значения в [00530064] с edi. Ну, поняли? Всего лишь осталось сделать так, чтобы в этом значении И БЫЛО ЭТО edi !!! Давайте снова остановимся и задумаемся, каким образом сравнивается значение из [00530064] с edi? Ведь для того, чтобы сравнить что-либо, нужно поместить туда что-нибудь, А КАК ПОМЕСТИТЬ? Чтобы найти, место, где помещается определенное значение в [00530064], сделаем так: в WinDasm жмем поиск и печатаем, почти ничего не изменяя: mov dword ptr [00530064] Согласитесь, логично, если там cmp, то здесь mov (*ЧИТАТЬ СТАТЬЮ Dr.Golova ОБ ОСНОВАХ АССЕМБЛЕРА !) И WinDasm найдет нам всего лишь одну (в случае с Оперой) ссылку, туда и пойдем: :00495E1F E8C3630200 call 004BC1E7 :00495E24 3BC7 cmp eax, edi :00495E26 A364005300 mov dword ptr [00530064], eax <--- То, что искали. ЧТО отсюда можно извлечь? Самое главное: все происходит в :00495E1F E8C3630200 call 004BC1E7 Идем в эту функцию: :004BC1E7 8D8138010000 lea eax, dword ptr [ecx+00000138] :004BC1ED 85C0 test eax, eax :004BC1EF 741A je 004BC20B <--- 1 Переход. :004BC1F1 803800 cmp byte ptr [eax], 00 :004BC1F4 7415 je 004BC20B <--- 2 Переход. :004BC1F6 81C190030000 add ecx, 00000390 :004BC1FC 51 push ecx :004BC1FD E8A647FDFF call 004909A8 :004BC202 85C0 test eax, eax :004BC204 59 pop ecx :004BC205 7404 je 004BC20B <--- 3 Переход. :004BC207 6A01 push 00000001 <--- Еденицу на стек. :004BC209 58 pop eax <--- Снимаем еденицу из стека в еах. :004BC20A C3 ret * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:004BC1EF(C), :004BC1F4(C), :004BC205(C) | :004BC20B 33C0 xor eax, eax :004BC20D C3 ret Видим чудеса: 3 перехода на обнуление и выход да еще видим сравнение eax с 0 и снова выход, что же здесь думать-то, если после последнего перехода есть установка этой самой единицы!!! Нус, осталось всего-то с первого перехода прыгнуть на установку единицы! Теперь убеждаемся, что в WinDasm строка установлена на 4BC1EF (горит зеленым), потом на 4BC207 и смотрим внизу на смещение (Offset), это BC1EF и BC207. *Для использования в HIEW смещения (offsets) из WinDasm берем БЕЗ последней h (например "BC1EFh" из WinDasm) для использования в HIEW возьмем только "BC1EF". Переходим в Far Manager по Alt-Tab (remember the very begining?), и "hiew opera.exe", там переходим в F4 > Decode Mode, потом F5 > Search BC1EF и наконец редактируем: жмем F3 (Edit), потом F2 (Asm) и пишем: jmps BC207 (вместо je…), и наконец жмем F9 (Update), чтобы сохранить изменения.
(* Прим. Dr.Golova: Можно сделать иначе, поскольку HIEW умеет преводить виртуальные адреса из WinDasm в реальные файловые. Мы сразу наберем адрес 4BC1EF из WinDasm в окошке «GoTo» HIEW’a (те же самые F4 > DecodeMode > F5), только его надо дополнить точкой и нулями до вида «.004BC1EF». Попадем в то же самое место. Как проще — решать вам, но так по крайней мере не надо смотреть offset. *)
THAT’s All folks ;))))
Вот мой патч на ПАСКАЛЕ:
——————————cut———————————
program opera161_crack;
Const A: Array[1..2] of Record
A : Longint;
B : Byte;
End = ( (A : $BC1EF; B : $EB),
(A : $BC1F0; B : $16) );
Var Ch : Char;
I : Byte;
F : File;
Begin
Writeln(‘Kondor»s patch’, #10#13, ‘Crack for Opera v1.61′);
Assign(F, ‘OPERA.EXE’);
Reset(F, 1);
If IOResult <> 0 then
begin
Writeln(‘File not found!’);
Halt(1);
end;
For I := 1 to 2 do
Begin
Seek(F, A[I].A);
Ch := Char(A[I].B);
BlockWrite(F, Ch, 1);
End;
Writeln(#10#13, ‘File successfully patched!’);
End.