Исследование программы Audio Mp3 Maker v 1.10-1.13 by Wersion
Программист коллегам:
- Сегодня на работе опять весь день @нанизмом занимался.
- Что, винды переставлял?
- Да нет... просто др#чил...
Итак, как это было. Когда-то, очень давно, я скачал эту довольно неплохую вещь для того, чтобы наделать
Mp3-файлов с одного Audio-диска. У меня тогда не было ни времени, ни знаний, поэтому я решил
воспользоваться Crack-сайтами. Нашедши около 7 серийных номеров к версии 1.10, я убедился, что ни
один из них не работает. Позже я кое-что делал с этой программой, поменял кучу байтов,она даже стала
похожей на зарегистрированную, но в конце концов выкинула мне сообщение о истечении *0-дневного
срока.
И я закинул сию вещь на год. После, набравшись ума, вновь принялся за исследование.
Вот оно:
Что используем:
Softice 4.x & Icedump 6.x
Win32 Disassembler v X.X.
Delphi 4-6.
Начнём.
Запускаем программу. Жмём Register, вводим имя и любой код. Видим сообщение "Invalid...",
запоминаем. Запускаем W32Dasm. Ищем строку в String Data References. Я нашёл следующий код:
:0040D844 53 push ebx (1)
:0040D845 51 push ecx (2)
:0040D846 E8AE9E0000 call 004176F9 (3)
:0040D84B 83C408 add esp, 00000008
:0040D84E 85C0 test eax, eax (4)
:0040D850 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"Message"
|
:0040D852 68BC7B4400 push 00447BBC
:0040D857 7518 jne 0040D871 (5)
* Possible StringData Ref from Data Obj ->"Thank you, please restart programs"
|
:0040D859 68E47D4400 push 00447DE4
:0040D85E 8BCE mov ecx, esi
:0040D860 E889CE0100 call 0042A6EE
:0040D865 8B16 mov edx, dword ptr [esi]
:0040D867 8BCE mov ecx, esi
:0040D869 FF92C4000000 call dword ptr [edx+000000C4]
:0040D86F EB37 jmp 0040D8A8
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040D857(C)
|
* Possible StringData Ref from Data Obj ->"Invalid reg code"
|
:0040D871 68D07D4400 push 00447DD0 (6)
:0040D876 8BCE mov ecx, esi
:0040D878 E871CE0100 call 0042A6EE
:0040D87D EB29 jmp 0040D8A8
Итак, что же мы видим? В (1) и (2) функции передаются 2 параметра, в (3) она вызывается.
В (4) мы проверяем значение EAX на равенство 0, потом в (5) прыгаем на (6) если это не так.
Соответственно, начиная с (6) идёт подготовка и выдача сообщения о неверности РИ.
Что мы делаем? Ставим брейкпоинт на (1), начинаем регистрироваться. Попадая в в Softice, делаем:
d ebx
d ecx
В одном из них адрес строки с нашим кодом, в другом - с реальным. Берём Icedump и копируем реальный код
на диск. Вводим их там где надо и получаем зарегистрированный Audio Mp3 Maker®.
0Днак0!
Всё это только начало. Меня всё время мучали следующие вопросы: при такой защите Coxsoft (теперь они
расцвели и стали MjSoft) загнулись бы на корню. Кроме того, мой код работал не только для версии 1.10, но
и для 1.13. Следовательно, алгоритм его генерации не меняли никогда. Тогда трудно объяснить
существование 7 неверных серийных номеров(см. начало).
Это всё значит, что код зависит от конфигурации компьютера или чего-нибудь ещё. На сем факте, не заметив
оного, proudly обломались 4 команды и 3 крэкера(и все ост., кот. я не нашёл). MjSoft специально сделали
такую ламерскую проверку(ост. на уровне), чтобы к ним скорее нашли с/н и оставили бы их в покое.
Наш кейген должен будет проделать всю нашу работу самостоятельно. Он станет интеллектуальным
отладчиком. Берем Delphi 6 и пишем.
Вот исходники:
program main;
{$APPTYPE CONSOLE}//мне так больше нравиться{$R KeyGen.res}//иконкаuses
SysUtils, Windows; //необходимый минимумvar
BW, BREAD: Cardinal;
Event: DEBUG_EVENT; //отладочное событие
XCode: array[1..255] of byte; //массив с нашим кодом
Answer: char; //ответ пользователя
WriteAddress_0, cAddress_0: Longint; //нужные нам адреса
WriteAddress_1, cAddress_1: Pointer;
NewByte: byte; //его будем писать в тело программы
CodeString: string; //строка с кодом
StartupInfo: TStartupInfo; //информация для запуска
ProcessInfo: TProcessInformation; //информация о процессе
Context: _CONTEXT; //контекст нашего процесса -- сод. значения регистров и т.д.
i: integer; //не помню чтоfunction SeekInBuffer(Buffer: arrayof byte): Longint;
//надо сначала найти нужный адресvar
posit: Integer;
begin
Result := 0;
for posit := 1 to 1024 dobeginif Buffer[Posit] = $8B then//ищем наши инструкции в 16-м виде(см. начало(асм. листинг))if Buffer[Posit + 1] = $1B then//это инструкции до push ebx, push ecxif Buffer[Posit + 2] = $8B thenif Buffer[Posit + 3] = $4D thenif Buffer[Posit + 4] = $E8 thenif Buffer[Posit + 5] = $53 then//$53=push ebxif Buffer[Posit + 6] = $51 then//$51=push ecxbegin//тут, надеюсь, вс¸ ясно.
Result := Posit;
Exit;
endelse
Result := 0;
end;
end;
function SeekBpPlace(ProcessHandle: Cardinal): Longint; //главная функция поискаvar
lpBaseAdr: Pointer;
BR: Cardinal;
StartAddr, SeekResult: Longint;
Buffer: array[1..1030] of byte; //для прочитанных кусков программы.begin
StartAddr := $401000;
repeatasm//си¸ делается так, чтобы присвоить lpBaseAdr значение StartAddr
mov eax, StartAddr //что обычными средствами Delphi сделать проблематично.
mov lpBaseAdr, eax;
end;
ReadProcessMemory(ProcessHandle, lpBaseAdr, @Buffer, 1030, BR);
//читаем кусок
SeekResult := SeekInBuffer(Buffer); //ищем в н¸м наши инструкцииif SeekResult = 0 thenbegin
Inc(StartAddr, 1024); //если ничего не нашли, ид¸м дальше.end;
until SeekResult <> 0; //пока поиск не закончится
Result := SeekResult + StartAddr; //добавляем StartAddr и получаем искомое.end;
//--------------------------------------------//begin
Writeln("THIS PROGRAM IS FOR EDUCATIONAL USE ONLY!");
Writeln("YOU CAN USE IT ONLY IF YOU HAVE REGISTERED COPY OF AUDIO MP3 MAKER!");
Writeln("OTHERWISE, IT IS ILLEGAL TO USE THIS PROGRAM!");
Writeln;
Write("Hit <Y>,<Enter> to agree or <N>,<Enter> to disagree/exit==>");
Read(Answer);
if UpCase(Answer) <> "Y" then
ExitProcess(0);
ifnot FileExists("keyinfo.key") then//чтоб нас не использовали как крэкbegin
Writeln("You aren""t registered user!");
Writeln("Hit <Enter> to exit...");
Readln;
ExitProcess(0);
end;
RenameFile("keyinfo.key", "keyinfo.key.org"); //делаем резервную копию
Writeln("Welcome."); //тут, надеюсь, тоже вс¸ ясно
Writeln(#4 + " This is keygen for Audio Mp3 Maker v. 1.10/1.11/1.12/1.13!");
Writeln(#4 + " Tested on Audio Mp3 Maker v. 1.10/1.13");
Writeln(#4 + " Author: Wersion");
Writeln(#4 + " E-mail: wcrkgroup2002@mail.ru");
Writeln("What do you need to do:");
Writeln(#4 +
"When program will be loaded, press ""Try it"" on the nag-screen");
Writeln(#4 + "After that, press ""Register"" in the program""s window!");
Writeln(#4 + "Enter your name.");
Writeln(#4 + "Enter any code, for example ""any code"" :-).");
Writeln(#4 + "Press""OK""");
Writeln(#4 + "Wait.");
Sleep(10000);
FillChar(StartupInfo, Sizeof(StartupInfo), #0); //заполняем структуру
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOWDEFAULT;
ifnot FileExists("amm.exe") then//он, конечно, нам нужен.begin
Writeln(#4 +
" File not found (""Amm.exe"") ! Please run me in program""s directory!");
Readln;
ExitProcess(0);
end;
{Созда¸м процесс и становимся отладчиком}if CreateProcess(nil, PChar("Amm.exe"), nil, nil, false,
DEBUG_ONLY_THIS_PROCESS, nil, nil, StartupInfo, ProcessInfo) then
Writeln(#4 + "Process created successfully...")
else
ExitProcess(0);
Writeln(#4 + "Seeking target...");
WriteAddress_0 := SeekBpPlace(ProcessInfo.hProcess) + 6;
//сюда надо поставить брейкпоинт
Writeln(#4 + " Target found at 0x" + IntToHex(WriteAddress_0, 6));
asm//вы это уже видели
mov eax,WriteAddress_0
mov WriteAddress_1,eax
end;
//--------------------------------------------//repeat
WaitForDebugEvent(Event, 0);
if event.dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT thenbegin
Writeln(#4 + " Process terminated by user! Unable to get code!");
Readln;
ExitProcess(0);
end;
if FindWindow(Pchar("#32770"), Pchar("Register")) <> 0 then//дожд¸мся начала регистрацииbegin
ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, DBG_CONTINUE);
//продолжаем отладку и выходим из цикла(бесконечного, кстати). Break;end;
ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, DBG_CONTINUE);
untilfalse;
NewByte := $CC;
//инструкция INT 03, воспринимается нами(отладчиком) как брейкпоинт.
WriteProcessMemory(ProcessInfo.hProcess, WriteAddress_1, @NewByte, 1, BW);
//устанавливаем его
Writeln(#4 + " Target patched...");
Writeln(#4 + " Breakpoint enabled...");
repeat//ждем появления INT 03
WaitForDebugEvent(Event, Infinite);
Writeln(#4 + " Waiting...");
if event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT thenif event.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT
thenbegin//дождались! Writeln(#04+" Breakpoint reached...");
NewByte := $51; //восстанавливаем старую инструкцию push ecx
WriteProcessMemory(ProcessInfo.hProcess, WriteAddress_1, @NewByte, 1,
BW);
Writeln(#4 + " Target patched again (original restored)...");
Context.ContextFlags := CONTEXT_INTEGER;
GetThreadContext(ProcessInfo.hThread, Context); //получаем контекст
cAddress_0 := Context.Ecx; //нам надо значение регистра Ecxasm
mov eax,cAddress_0
mov CAddress_1,eax
end;
Writeln(#4 + "Reading code...");
ReadProcessMemory(ProcessInfo.hProcess, cAddress_1, @Xcode, 255, BREAD);
//читаем код с мусором в буфер
TerminateProcess(ProcessInfo.hProcess, 0); //завершаем программу
Writeln(#4 + "Terminating process...");
Break; //выходим из бесконечного циклаend;
ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, DBG_CONTINUE);
untilfalse;
//-----------------------------------------------------//
CodeString := "";
for i := 1 to BREAD do//очищаем код от мусора и су¸м в строкуbeginif Xcode[i] <> 0 then
CodeString := CodeString + Chr(Xcode[i])
else
Break;
end;
Writeln(#4 + " Your code: " + CodeString);
Writeln(#4 + " Your have 1 minute to copy it to clipboard.");
Writeln(#4 + " Enjoy!");
Sleep(60000);
//собственно, это вс¸.end.
Что сказать в заключение?
Что сделать кейген с чистого листа при пратически полном отсутствии документации по функциям
отладки совсем не просто. А ещё, все исходники являются моей интеллектуальной собственностью и
защищаются законами об авторских правах.
Created by Wersion. E-mail: wcrkgroup2002@mail.ru
Комментарии/вопросы - приветствуются.
Greats to: Iczelion, Dr. Golova. <- наставили меня на путь истинный.
Если Вас заинтересовала или понравилась информация по разработке на Delph - "Исследование программы Audio Mp3 Maker v 1.10-1.13 by Wersion", Вы можете поставить закладку в социальной сети или в своём блоге на данную страницу: Так же Вы можете задать вопрос по работе этого модуля или примера через форму обратной связи, в сообщение обязательно указывайте название или ссылку на статью!