Keygen Me 1 - Lösungshinweise

Annährend 3 Monate ist es her, dass ich mich an einem Keygen Me versucht habe. Ziel war es ein “Algorithmus” zu entwickeln, den man nicht durch simples Rückrechnen der Rechenoperationen brechen kann. Blogpartner tr4ceflow hat einen Artikel dazu gewidmet, der schon gute Ansätze beinhaltet. In der Zukunft werden Keygen Mes mit einem nicht so überladenen Compiler wie Visual Studio kompiliert, da viel zu viel verwirrender Mist reinkommt. Das habe ich auch dadurch gelernt ;)

Alle 3-4 Tage werden hier neue Lösungshinweise erscheinen. Wieviele es insgesammt werden weiß ich nocht nicht.

13.09.2014:

Alle Infos von tr4ceflows Blogpost zusammengefasst: Per GetDlgItem und GetWindowTextA wird der Text aus den Textboxen Name, Serial1 und Serial2 ausgelesen. Diese werden an eine Funktion, die den eigentlichen Keycheck vornimmt übergeben (0x1E1C60). Nun muss gelten: usernameLength - 1 == strlen(key1)/4). Der Key wird nun in 4er Blöcke zerlegt und in shorts (2 byte) gespeichert. Aus 01234567 wird 0×0123 und 0×4567 . Dieses wird zu einem Float umgewandelt (0×0123 = 291d => 291.0f) und im Anschluss durch 100 geteilt. Nun wird gerechnet, und zwar mit Floats. Es werden nun alle Buchstaben durchlaufen. Dabei wird jeweils die Summe aus einer “Rechnung” gebildet und diese vom aktuellen Buchstaben abgezogen. Nun wird vergleichen, ob die Differenz in einem “Bereich” liegt, der durch die e-Funktion mit einem statischen Exponenten aus einem Array begrenzt wird. Wenn die Differenz kleiner als die expotentierte Zahl ist, so wird die Schleife Fortgesetzt. Wenn nein, so wird aus der Funktion rausgesprungen und der Key ist nicht gültig.

Ich möchte nochmal einen kleinen zusätzlichen Tipp geben: tr4ceflow hat eine Rechung aufgestellt, wie die Sache im ersten, zweiten und dritten Durchgang aussieht.

- berechne    - hex(e) / 100.0
              - hex(f) / 100.0
              - hex(g) / 100.0
- berechne die Summe 
	1. Durchgang :  hex(e) / 100.0 + hex(f) / 100.0 + hex(g) / 100.0
	2. Durchgang :  4*hex(e) / 100.0 + 2*hex(f) / 100.0 + hex(g) / 100.0
	3. Durchgang :  9*hex(e) / 100.0 + 3*hex(f) / 100.0 + hex(g) / 100.0
- hole einzelnen Buchstaben "a" aus Namen und berechne die Differenz

Schaut euch dabei mal die Vorfakoren der hex(e/f/g) an. Beim ersten Durchlauf ist dieser stets 1, beim zweiten durchlauf ist er 1,2,4, …, beim dritten Durchlauf 1,3,9,… . Kommen euch diese Folgen bekannt vor? Wenn ja, wo finden sie Anwendung? Vorallem im Zusammenhang mit einer Addition ! Dieser (relativ) große Tipp hilft hoffentlich, auf die richtige Spur zu kommen. Denn tra4ceflow hat bereits alle vorarbeit geleistet, jetzt gilt es nur noch 1+1 zusammenzuzählen.

16.09.2014:

save(2)

Entspricht dem Polynom: f(x) = -0.054166*x^6 + 1.02083*x^5 -6.3125*x^4 + 10.0625*x^3 + 32.866*x^2 -106.583*x^1 + 138

Entspricht auch dem Usernamen: EASYSURF

Schaut euch mal den Y-Wert des Polynoms an den ganzen Zahlen an, also: f(1), f(2), … Vergleicht es mit EASYSURF!

18.09.2014:

Mit den obigen Zeilen ist der Hauptteil des Keygens, nämlich Key1 bereits errechnet. Das sind also einfach die Koeffizienten des Polynoms was den Usernamen bzw die ASCII Characters des Usernamens abzüglich dem letzten Buchstaben annährt. Hier der Beispielkey für EASYSURF.

Key1: fffb0066fd8903ee0cd6d65e35e7

Doch was ist mit Key 2? Dort wird ebenfalls ein Polynom verwendet. Doch welchen Wert muss es haben? Es ist ganz ähnlich. Doch das hebe ich mir für den nächsten und finalen Tipp auf ;)

22.09.2014:

Abschliesend gibt es die volle Auflösung und auch den Sourcecode zum Keygen. Fangen wir mit dem zweiten Key an. Auch hierbei handelt es sich um encodierte Koeffizienten des Polynoms des “strlen(username) - 1″-Grades. Allerdings geht es hier auch noch um Grenzwertberechnung. Der Grenzwert Polynom2/Polynom1 gegen Unendlich muss gegen den letzten Buchstaben/10 gehen. Dabei ist bekanntlich nur größte Exponent entscheidend, welcher im Nenner, als auch im Zähler ausgeklammert wird. Beim oben genannten Key ist der größte Exponent 0xfffb, was nach umrechnen -0,0541 ergibt. Der Grenzwert, also der letzte Buchstabe, muss F = 70d sein. Die Gleichung umzustellen müsste jeder hinbekommen: x/-0,0541=7.0 => x = -0,0541*7.0 = -0.3787. Encodieren wir das wieder in unsere Short-Schreibweise, so erhalten wir: ffdb. Da die restlichen Exponenten egal sind, können wir da einfach die restlichen Koeffizenten von Key1 ranhängen. Damit erhalten wir als gültige Keykombination:
Key1 = fffb0066fd8903ee0cd6d65e35e7
Key2 = ffdb0066fd8903ee0cd6d65e35e7

Sourcecode (nur die interessante CheckKey und GetPoly Funktion)

bool CheckKey(const char* username,  const char* key1, const char* key2)
{
	int usernameLength = strlen(username);
	if (usernameLength - 1 != strlen(key1)/4)
	{
		return false;
	}
 
	int countElements_Key1 = strlen(key1)/4;
	int countElements_Key2 = strlen(key2)/4;
 
	const char *pos = key1;
	short coeffKey1_short[20];
	float coeffKey1[20];
 
	short tmpShort;
	for(int count = 0; count < countElements_Key1; count++) 
	{
		sscanf_s(pos, "%4hx", &tmpShort);
		coeffKey1_short[count] = tmpShort;
		pos += 4 * sizeof(char);
	}
 
	short coeffKey2_short[20];
	float coeffKey2[20];
 
	pos = key2;
	for(int count = 0; count < countElements_Key2; count++) 
	{
		sscanf_s(pos, "%4hx", &tmpShort);
		coeffKey2_short[count] = tmpShort;
		pos += 4 * sizeof(char);
	}
 
 
	for (int i = 0; i < countElements_Key1; i++)
	{
		coeffKey1[i] = (float)(coeffKey1_short[i]/100.0f);
	}
 
	for (int i = 0; i < countElements_Key1; i++)
	{
		coeffKey2[i] = (float)(coeffKey2_short[i]/100.0f);
	}
 
	// Prüfen ob das Polynom die Punkte annährt
	for (int i = 0; i < countElements_Key1; i++) 	{ 		float diff = abs(GetPoly(i+1,&coeffKey1[0], countElements_Key1) - (float)username[i]); 		float checkExp2 = checkExp[countElements_Key1]; 		if (diff > 0.1f*exp(checkExp2*i))
		{
			return false;
		}
	}
 
	// Prüfen ob der Grenzwert gegen das letzte Char geht
	float a1 = GetPoly(9999999,&coeffKey1[0], 3);
	float a2 = GetPoly(9999999,&coeffKey2[0], 3);
	float a12Res = a2/a1;
 
	float diff = abs(a12Res - (float)username[usernameLength-1]/10) ;
	if (diff > 1.0f)
	{
		return false;
	}
 
	return true;
}
 
double GetPoly(int x, float* coeff, int count)
{
	double res = 0.0f;
	for (int i = 0; i < count; i++)
		res += coeff[i]*pow(x, count - i - 1);
 
	return res;
}

Greez

3 people like this post.
  1. Noch keine Kommentare vorhanden.

  1. Noch keine TrackBacks.