Контакты

Для связи с нами можно использовать:
irc://irc.chatnet.ru:#gfs
icq://546460
email://cobalt[@]gfs-team.ru

Все материалы предоставлены только с ознакомительной целью
ГлавнаяСтатьиКрэкингВзлом программы SuperCleaner 2.96 - Пишем KeyGenerator
© s0 21.12.2009

Сайт производителя - http://www.southbaypc.com/

Искал чем бы почистить комп от разных ненужных файлов, и наткнулся на эту прогу. После сканирования и удаления файлов, мой хард обогатился лишними 400мб места. Собственно решил я прожку оставить, но вот беда, программа Shareware и просит денежку, а без денежки будет работать только 30дней.

Но нам ведь это не помеха?

Что нам потребуется:
PEiD - анализатор файлов
OllyDbg - отдладчик
И все.
Анализ

Запускаем PEiD, открываем в нем SuperCleaner.exe и с радостью видим что программа ничем не запакованна. Что очень облегчает нам задачу.

При запуске программы, она выкидывает нам наг-скрин с указанием сколько осталось до окончания триала, предложение купить сию замечательную программу, ну и кнопочкой "Enter Registration". Приступим к насилию. Запускаем OllyDbg и грузим в него нашу программу.

Нажимаем F9, чтобы запустить программу на исполнение, и ждем пока загрузится. Как загрузилась, тыркаем в кнопочку "Enter Registration", вводим данные от балды, и жмем "OK". Для начала нам нужно выяснить, как программа реагирует на неверные данные. Нам повезло, программа выдает MessageBox о невернно введенных данных.

Пробуем поставить бряк(BreakPoint\Точка останова\int3) на функции MessageBoxA, MessageBoxW, из консоли в Ольге(ALT+F1 -> bpx MessageBoxA) Заново пытаемся зарегать программу, и...ничего. Бряки не сработали. Будем копать дальше. Какие еще существуют полезные функции для крякеров? Ну конечно же GetDlgItemTextA! Ставим бряк на эту функцию, вводим данные в окне регистрации, нажимаем ОК, и оказываемся вот тут

Как видим, тут подряд стоят два вызова функции GetDlgItemTextA. УРА! Теперь мы знаем где копать.

Трасируем по F8 до строчки
004250EB    . E8 70DCFFFF    CALL SuperCle.00422D60

Скажу сразу, заходить в эту функцию не стоит, она не несет никакой смысловой нагрузки, но очень большая и вообще не понятно зачем она там. Поэтому проходим это место дальше(F8) до строчек

Тут мы видим введенные нами данные, и теперь мы уж точно близко к цели. Заходим(F7) в функцию

004250FF    . E8 9C050000    CALL SuperCle.004256A0

Там трассируем(F8) до строчки

004256F9   |. E8 B2000000    CALL SuperCle.004257B0

И ее тоже пропускаем по F8 Дело в том, что после выполнения функции SuperCle.004257B0, в ebx находится правильный серийник, который программа генерировала сама.

Теперь его можно скопировать, и ввести в программу. Регистрация пройдет успешно, и вы станете счастливым обладателем полной версии этой программы.

Но зачем останавливаться на достигнутом? Почему бы не написать кейген, чтобы мы могли в любое время регистрировать программу на любые данные? Поставьте бряк(F2) на строчке

004256F9   |. E8 B2000000    CALL SuperCle.004257B0

и перезапустите(Ctrl+F2) процесс. Заново дойдите до это функции, но теперь не обходите ее, а зайдите в нее по (F7) Теперь мы находимся внутри функции, которая отвечает за генерацию верного серийника, по введенному нами имени(Name).

Сначала вычисляется длинна имени

004257DF   |. 57             PUSH EDI                                ; /String
004257E0   |. FF15 A8D24300  CALL DWORD PTR DS:[<&KERNEL32.lstrlenA>>; \lstrlenA

И если она >0, то начинается процесс генерации

Серийник состоит из четырех частей, и каждая часть генерируется отдельно. Я опишу только первый цикл, так как остальные в принципе идентичны, за исключением константы и умножения\сложения. Сам алгоритм генерации я опишу ниже.

Первая часть
004257F0   |. 8B15 8C654400  MOV EDX,DWORD PTR DS:[44658C] 			;В edx заносится константа 0x26(смотрим в окне регистров)
004257F6   |> 0FBE2C07       /MOVSX EBP,BYTE PTR DS:[EDI+EAX]		;В ebp заносится символ из имени
004257FA   |. 03EA           |ADD EBP,EDX							;складываем ebp+edx
004257FC   |. 83C0 01        |ADD EAX,1								;увеличиваем счетчик цикла
004257FF   |. 03CD           |ADD ECX,EBP							;складываем ecx+ebp(в ecx как раз и будет первая часть серийника
00425801   |. 3BC6           |CMP EAX,ESI							;дошло до конца имени?
00425803   |.^7C F1          \JL SHORT SuperCle.004257F6			;Да? Тогда идем дальше, иначе прыгаем к началу
00425805   |> 51             PUSH ECX                                ; /<%ld> 
00425806   |. 68 D01A4400    PUSH SuperCle.00441AD0                  ; |Format = "%ld-"
0042580B   |. 53             PUSH EBX                                ; |s
0042580C   |. FF15 8CD44300  CALL DWORD PTR DS:[<&USER32.wsprintfA>] ; \wsprintfA 			;Не ленимся, и читаем в MSDN описание этой функции

Вот в принципе и весь алгоритм. Теперь по пунктам

: -Имеется 4 константы:
0x26, 0x34, 0x0C, 0x0E(все это видим в окне регистров в отладчике) Соответственно каждая константа для своей части серийника.
-Берем первую константу, складываем с очередным символом имени и все что получили прибавляем в еще одной переменной. Это что касается первой и третей части серийника. Во второй и четвертой частях, вместо сложения add ebp, edx, используется умножение imul ebp, edx. Все остальное в точности как и раньше.

Надеюсь тут все понятно. Кто не понял, вернитесь к отладчику, и просмотрите каждую строчку шаг за шагом.

Теперь настало время писать сам кейген. Так как я ленивый, то я выбрал самый простой вариант VC++ 6.0 MFC.

-Создаем новый проект MFC.
-Говорим студии что мы ходим Dialog Based проект
-На форму кидаем два EditBox'a, удаляем кнопку Cancel и оставляем кнопку ОК.
-Два раза кликаем на кнопке ОК, у нас создастся обработчик этой кнопки, и после строчек
-Удаляем все что там напихала нам студия, и пишем свой код

Как говорится, простите меня за мой французский, но не люблю я Венгерскую Нотацию, так что переменные называл как больше нравится.

	char cName[40], cTemp[20];							//Объявляем переменные
	char  cLetter = 0, cBigCode[25];					//---------------/------------
	DWORD  cLittleCode = 0;								//---------------/------------
	int i = 0, ii = 0;									//---------------/------------
	GetDlgItemText(IDC_EDIT1, cName, sizeof(cName));	//Получаем Имя из первого EditBox'a
	
	
	/*		Вот тут вот мне стало лень делать отдельные функции, хотя это было бы намного рациональней */
	_asm
	{
		xor ecx, ecx				//Сказать честно, я часа 3 просидел, пытая написать все это на СИ,
		xor edx, edx				//Но моё терпение лопнуло, и я таки написал это на асме
		xor ebx, ebx				//По большому счету - это всего лишь скопированый кусок из програмы SuperCleaner
		xor eax, eax				//Чистим регистры

		lea eax, cName				//Адрес cName в eax
		mov edx, 0x00000026			//АхнтунГ! Первая константа
_circ:
		cmp byte ptr [eax], 00		//Закончились символы в имени?
		jz _home					//Янки, гоу хоум
		mov bl, byte ptr [eax]		//Ах вы не Янки? Ну тогда добро пожаловать
		inc eax						//Увиличиваем указатель
		add ebx, edx				//Вот ОНО! Складываем
		add ecx, ebx				//И опять складываем
		jmp _circ					//И все заного
_home:
		mov dword ptr [cLittleCode], ecx		//Копируем все это дело в нашу переменную
	}
	wsprintf(cBigCode, "%ld-", cLittleCode);	//И форматим под наш серийник

	_asm
	{
		xor ecx, ecx				//И опять все заного
		xor edx, edx				//------------//--------------
		xor ebx, ebx				//------------//--------------
		xor eax, eax				//------------//--------------

		lea eax, cName
		mov edx, 0x00000034 		//Опять константа
_circ1:
		cmp byte ptr [eax], 00
		jz _home1
		xor ebx, ebx				//Необходимо, так как умножение оно такое умножение....
		mov bl, byte ptr [eax]
		inc eax
		imul ebx, edx				//А вот и умножение
		add ecx, ebx
		jmp _circ1
_home1:
		mov dword ptr [cLittleCode], ecx
	}
	memset(cTemp, 0, sizeof(cTemp));			//Чистим буфер
	wsprintf(cTemp, "%ld-", cLittleCode);		//И опять форматим
	strcat(cBigCode, cTemp);					//А теперь объединяем строки

	_asm
	{
		xor ecx, ecx				//Уже даже не смешно....
		xor edx, edx
		xor ebx, ebx
		xor eax, eax

		lea eax, cName
		mov edx, 0x0000000C
_circ2:
		cmp byte ptr [eax], 00
		jz _home2
		mov bl, byte ptr [eax]
		inc eax
		add ebx, edx
		add ecx, ebx
		jmp _circ2
_home2:
		mov dword ptr [cLittleCode], ecx
	}
	memset(cTemp, 0, sizeof(cTemp));
	wsprintf(cTemp, "%ld-", cLittleCode);
	strcat(cBigCode, cTemp);

	_asm
	{
		xor ecx, ecx
		xor edx, edx
		xor ebx, ebx
		xor eax, eax

		lea eax, cName
		mov edx, 0x0000000E
_circ3:
		cmp byte ptr [eax], 00
		jz _home3
		xor ebx, ebx
		mov bl, byte ptr [eax]
		inc eax
		imul ebx, edx
		add ecx, ebx
		jmp _circ3
_home3:
		mov dword ptr [cLittleCode], ecx
	}
	memset(cTemp, 0, sizeof(cTemp));
	wsprintf(cTemp, "%ld", cLittleCode);
	strcat(cBigCode, cTemp);
	SetDlgItemText(IDC_EDIT2, cBigCode);			//Вуаля, во-втором EditBox'e у нас сгенереный серийник

Вот впрниципе и все. К статье прилагается архив, в котором лежат сорцы и готовый exe'шник кейгена

PS: Прошу не заывать, что все что вы прочитали, всего лишь бред сумашедшегО, и никоим образом не может быть использованно в качестве доказательства в суде




© s0 21.12.2009

e-Commerce Partners Network
MaXL написал:

Гы, статья конешно для новичков. Но зря ты не стал рассказывать про то, что это за функция:

004250EB    . E8 70DCFFFF    CALL SuperCle.00422D60


Я сильно не вдавался в подробности, так минут пять глянул, там короче есть массив "заголовков" окон, которые я так понел используются в кряках, вот часть из них:



Divide By Zero proudly presents...

SuperCleaner 2.43 Keygen

Super Cleaner 2.21 Keygen by Saiyajin [e!]

VNCRACKING : Super Cleaner v2.41 - Keygenerator

SuperCleaner v2.4 *KeyGen*

tEAM tSRH pROUDLY pRESENTS

SuperCleaner v1.6 KeyGen by ManKind/DSi


Так вот этот код:

004250EB . E8 70DCFFFF CALL SuperCle.00422D60 // вызов "ненужной" функции
004250F0 . 85C0 TEST EAX,EAX //проверка результата

004250F2 . 75 58 JNZ SHORT SuperCle.0042514C //прыжок если не нулевой

Ну а в самой функции используетца простой пробег по массиву "плохих" заголовков, с использованием FindWindow.
Ну и получается, что если найден один из таких окон, то ключ даже считаться не будет и проверятца, прога нас сразу пашлёт :)

Так что смотрите, чтобы не было запущено подобных окон :)))
P.S. если уж хочетца что-то такое запустить, то можно, например, тот

test eax, eax[quote]

заменить на

[quote]xor eax, eax

Ну и не понятно, в чём сложность на писать на С.

MaXL написал:

Вот до кучи, я думаю так красивее, правда оно кансольное ))))



#include <iostream>

#include <string>



int sum(const std::string& name, int k)

{

int res = k * name.length();

for (int i = 0; i < name.length(); ++i)

res += name[i] ;

return res;

}



int mul(const std::string& name, int k)

{

int res = 0;

for (int i = 0; i < name.length(); ++i)

res += k * name[i];

return res;

}



int main(void)

{

std::string name;

std::cout << "You name: ";

std::cin >> name;

std::cout << "key: " << sum(name, 0x26) << '-' << mul(name, 0x34) << '-';

std::cout << sum(name, 0xc) << '-' << mul(name, 0xe) << std::endl;

system("pause");

return 0;

}

INC написал:

Thanks

Ник:

Текст:
P Br B I Qute



Код: обновить
Последние комментарии
22.09.2017 18:36:49 Avito777jaf написал:
<b>Пополение баланса Авито (Avito) за 50%</b> | <b>Телеграмм @a1garant</b> <b>Здравствуйте,...
Новый релиз
22.09.2017 18:26:34 Avito777jaf написал:
<b>Пополение баланса Авито (Avito) за 50%</b> | <b>Телеграмм @a1garant</b> <b>Приветствую...
Сайт снова работает!
22.09.2017 18:12:48 Avito777jaf написал:
<b>Пополение баланса Авито (Avito) за 50%</b> | <b>Телеграмм @a1garant</b> <b>Приветствую...
Новая статья
Реклама

Тут должна была быть ваша реклама, но мы потеряли глиняную табличку с ее текстом. SapeId: 665044

Rambler's Top100