Yarins KeygenMe

Hey,
ich habe ein ich würde sagen mittelschweres KeygenMe (ein CrackMe dessen Ziel es ist einen Keygen zu erstellen, nicht es zu cracken)

Ihr findet es hier:
http://www.yarin.de/crackmes/keygenme1.exe
ODER als ZIP:
http://www.yarin.de/crackmes/keygenme1.zip
(Dieses Programm ist ungefährlich, das Ausführen bedenkenlos! Dat ZIP erst Recht!)

Es ist in einem C/C++ Gemisch mit purer WinAPI (also nicht mit MFC-Zeugs zugemüllt) geschrieben und stellt sich selbst als ein Registrierungsdialog für ein Programm dar. Das PE ist gepackt und es sind diverse Schutzmechanismen gegen das Debuggen (4 aktive, 1 passive Eigenentwicklung) eingebaut, die vielleicht mal ganz interessant anzusehen sind, eingebaut.

Ich habe auf komplexe Hash-Algorithmen verzichtet - das ganze soll ja nicht in Arbeit ausarten.

Ziel ist wie gesagt das Erstellen eines Keygens oder das Erkennen und Erklären des Mechanismus zur Erstellung der passenden Serials. Wer ein richtiges Serial eingibt wird vom Programm mit einem Zitat belohnt und wird in meinem nächsten CrackMe oder KeygenMe erwähnt

Viel Spaß beim debuggen, ich bin schon gespannt, wie lange ihr braucht!

p.s.: Versucht gar nicht erst, es zu cracken - das wäre zu langweilig. Eine Zeile zu noppen oder einen Jump zu ändern würde genügen..

p.p.s.: Ganz vergessen.. Benutzernamen unter 3 Zeichen sind immer ungültig. Ungültige Eingaben quitiert das Programm stumpf mit dem Programmende. Eventuelle Abstürze sind zu 95% beabsichtigt ^^ (Randale-Mode)
 
Eventuelle Abstürze sind zu 95% beabsichtigt ^^ (Randale-Mode)

Dann werd ich das sicher nicht anpacken.

btw: pack doch ein File bitte in ein Zip oder Rar. Direkt verliinkte Exe ist nicht so gern gesehen. ;)
 
Na dann ;)

Ich bin noch von Arthis einem CM geprägt, was das ganze System in den Abgrund riß. War nicht so lustig.

root
 
Was euch passieren kann, ist, dass ihr ne Exception abkriegt oder dass das Programm absichtlich ne Access Violation auslöst, weil es halt einfachmal stumpf an 0x0000 oder 0xDEADBEEF lesen oder schreiben will. Das wird euren PCs aber garantiert nicht schaden, ein Hoch auf den Protected Mode! Ich hab ganz sicher kein system("format /q c:") oder so eingebaut ^^

ICh will da gar nicht diskutieren, ich frage mich nur, was an einer direkt verlinkten EXE falsch ist? Die Größe wirds ja wohl kaum sein, das Programm liegt im unteren 2stelligen Kilobyte-Bereich..

p.s.: natürlich passiert das auch nur, wenn sich mein kleines KeygenMe angegriffen fühlt, also irgendwas entdeckt, was irgendwie nach Debugger riecht (eine offene Microsoft IDE sieht z.B. auch sehr nach Debugger aus für das kleine Ding, also vorsichtig :D )
 
Original von Yarin
ICh will da gar nicht diskutieren, ich frage mich nur, was an einer direkt verlinkten EXE falsch ist? Die Größe wirds ja wohl kaum sein, das Programm liegt im unteren 2stelligen Kilobyte-Bereich..

man könnte sich verklicken und die exe ausführen, ungewollt, bei ner zip/rar is das nich so arg (manche haben diese gedanken)

größere exe dateien sind auch in rar/zip archive gepackt, also warum nicht auch kleinere
 
Original von Sven
Original von Yarin
ICh will da gar nicht diskutieren, ich frage mich nur, was an einer direkt verlinkten EXE falsch ist? Die Größe wirds ja wohl kaum sein, das Programm liegt im unteren 2stelligen Kilobyte-Bereich..

man könnte sich verklicken und die exe ausführen, ungewollt, bei ner zip/rar is das nich so arg (manche haben diese gedanken)
Warum ist das Ausführen des ungefährlichen Programms arger als das Ausführung des Packprogramms?
größere exe dateien sind auch in rar/zip archive gepackt, also warum nicht auch kleinere
Das Programm ist doch schon UPX-ed. Zippen bringt eine weitere Verkleinerung der Datei um .. wow.. 1 ganzes Kilobyte :o)

Hat sich das Programm nun schon jemand angeschaut?
 
Warum ist das Ausführen des ungefährlichen Programms arger als das Ausführung des Packprogramms?

Weil es schon mehr als einmal vorkam, dass hier Viren direkt verlinkt wurden.
Natürlich ist dein Programm in Ordnung; trotzdem steigt das Misstrauen sprunghaft an, wenn eine EXE direkt verlinkt wurde.

Das ist alles. Es war auch keine Vorschrift, du wirst dazu auch keine Regel im Board finden. Es war lediglich eine Bitte/Hinweis.

Wenn du Exe-Files weiterhin verlinken willst, steht dir das frei.

root
 
Ich verstehe jetzt deine Bedenken, SUID:root - ich denke der Hinweis den ich unter den Link hinzugefügt habe ist fair.
 
hi

Ich verstehe jetzt deine Bedenken, SUID:root - ich denke der Hinweis den ich unter den Link hinzugefügt habe ist fair.

(Dieses Programm ist ungefährlich, das Ausführen bedenkenlos!)

:D :D :D nein, ich bin kein virus! du kannst mich ruhig anklicken und ausführen...

@Yarin:

es sollte dir eigentlich bewusst sein das, wenn du die exe in ein zip oder rar packst,
sich mehr leute trauen dein prog anzusehen.
wenn du das nicht machst, dann werden viele user dein prog einfach nicht anklicken und
es ist schade um deine zeit und mühe, die du dir damit gemacht hast.

es geht hier nicht um vertrauen ;)
wo kämen wir denn hin wenn hier jeder auf irgendwelche exen klickt!
denk mal darüber nach...

cu
-= pillepalle =-
 
Was habt ihr denn alle für komische Browser, dass die EXEs gleich Ausführen statt runterladen? :D

Naja, wie ihr wollt, hier das ganze nochmal als ZIP (s.o.)
 
schönes keygenme. ;)

auf schutzmechanismen gegens debuggen bin ich nicht gestoßen (using ollydbg + anti-IsDebuggerPresent() plugin @ windows 98 ).

kurzanleitung für den richtigen breakpoint:
- datei mit PEid laden -> UPX gepackt
- datein entpacken (zB. mit UPX Ripper)
- keygenme mit ollydbg öffnen (error mit ok wegklicken)
- keygenme zunächst starten (F9)
- rechtsklick -> search for all intermodular calls
- oben in der liste steht 3x "GetWindowTextA"
- mit doppelklick auf eines davon landet man an der stelle wo der relevante code beginnt

zunächst werden erstmal die strings eingelesen die man eingegeben hat und die variablen in den speicher gepackt.
00401BA3 . E8 68FBFFFF CALL KEYGENME.00401710
in dieser zeile gelangt dann man zu der berechnung der serial (-> step into mit F7).
ab zeile 40179f wirds dann interessant. es beginnt damit das CPU spezifische daten eingelesen werden. danach gehts dann mit diversen berechnungen weiter.
kurz gesagt werden zunächst 4 zwischenwerte berechnet (aus name, organisation und CPU-spezifischen werten ). aus diesen 4 zwischenwerten werden am ende in einer schleife dann nochmal die 4 endwerte für die serial berechnet.

keygen algo (keygen.exe siehe anhang):
Code:
#include <iostream>
#include <string>
#include <conio.h>

using namespace std;

int main(void)
{
	char name[999];
	char org[999];

	unsigned int werte[4];
	unsigned int EAX, EDI, ESI, EDX, ECX;
	unsigned int vendor1, vendor3, cpuModel;
	unsigned int tmp; 

	cout << "Enter name: ";
	cin.getline(name, sizeof(name));
	cout << "Enter organisation: ";
	cin.getline(org, sizeof(org));

	// CPU daten holen
	__asm {
		mov EAX,0;
		CPUID;
		mov [vendor1], EBX;	// erster  teil des vendor strings der cpu
		mov [vendor3], EDX;	// letzter teil des vendor strings der cpu
	}
	tmp = (vendor3 << 16) + (vendor1 >> 16);

	__asm {
		mov EAX,1;
		CPUID;
		mov [cpuModel],EAX;
	}
	cpuModel = ((cpuModel>>4) & 0xF);

	// zwischenwert1
	ECX = strlen(name);
	ESI = ECX + 0xdeadbeef;
	for(int i=0; i<strlen(name); i++) {
		EDX = (int)name[i];
		ESI += EDX;
	}
	werte[0] = ESI;

	// zwischenwert2
	EDX = strlen(org);
	ECX = EDX + 0xfeed1337;
	for(i=0; i<strlen(org); i++) {
		EDI = (int)org[i];
		ECX += EDI;
	}
	werte[1] = ECX;

	// zwischenwert 3 und 4
	EDI = ECX + 2;
	EAX = ECX + 3;
	EAX *= EDI;
	EAX *= EDI;
	EDX = EAX % EDI;
	EDI = 0xFFFFFFFF;
	ECX = ECX ^ ESI; // ESI = werte[0]
	EDX = EAX % EDI;
	ECX *= 2;
	ECX += cpuModel;
	EDX = vendor1 ^ tmp;

	werte[2] = ECX;
	werte[3] = EDX;

	// serialwerte 1 bis 4
	for(i=0; i<4; i++) {
		EAX = werte[i];
		EDI = 2 + EAX;
		EAX += 3;
		EAX *= EDI;
		EAX *= EDI;
		EDX =  EAX % EDI;
		ESI = 0xFFFFFFFF;
		EAX = EDX;
		EDX = EAX % ESI;
		EAX = EDX;
		ESI = 0x1869f;
		EDX = EAX % ESI;
		werte[i] = EDX;
	}

	cout << "Serial: ";
	cout << dec;
	for(i=0; i<3; i++) {
		cout << werte[i] << "-";
	}
	cout << werte[3] << endl;

	cout << endl << "Press any key to exit.";
	getch();
	return 0;
}

dein keygenme hat übrigens einen kleinen schönheitsfehler. bei bestimmten eingaben hat man teilweise weniger als 5 stellen bei einem wert. bei diesen müsste man dann als erste zeichen leerzeichen eingeben, was allerdings nur über copy & paste funktioniert.
 
wozu hab ich mir bloß die Mühe gemacht *auf ivegotmail schiel* :rolleyes:

auf schutzmechanismen gegens debuggen bin ich nicht gestoßen
dito (using nur OllyDbg auf Win XP ;))

Entpacken: PEID benutzen, aber nicht die ImportTable wiederherstellen lassen, stattdessen z.B pdump32 nutzen ("Rebuild PE").
wichtig ist der BP an 4017A1 - ab hier wird berechnet, bis dahin ist nur rumkopieren von strings (und die Eingegebene Serial wird zu einem "ganzen" String zusammengefügt).
Übrigens ist die Überprüfung auf EAX<1 nach CPUID etwas unsinnig weil ein "unterpentium" den Befehl eher nicht verstehen würde

einen kleinen schönheitsfehler. bei bestimmten eingaben hat man teilweise weniger als 5 stellen
Jep, und ich hab zuerst Rumgerätzselt wie man die Serial für "cdw" "organ" eingeben sollte.

Keygen samt Quelltext ist im Anhang (etwas kleiner als von ivegotmail :P ):

PS: Edit: also DEADBEEF und FEED1337 als Hexwerte zu nehmen war eine originelle Idee und hat mir gefallen :D
 
Herzlichen Glückwunsch ihr beiden,
KeygenMe gelöst! Es gab jetzt gleich 2 Dinge, die mich gewundert haben:
1) Warum taucht da GetWindowTextA in der Liste auf?
2) Warum haben sämtliche Schutzmechanismen bei CDW versagt (ivegotmail mit seinem Plugin war klar :-) )

Zu 1)
Sämtliche Funktionen, auf die ein Debugger als erstes einen Breakpoint setzen würde, werden mit LoadLibrary und GetProcAddress geladen. Um es dem Debugger noch schwieriger zu machen werden die Library-Namen (user32, kernel32) und die Funktionsnamen nicht einfach als const chars sondern c = c - 'Y' gespeichert damit sie vom Debugger nicht mehr als Strings erkannt werden (damit liegen die meisten chars nämlich irgendwo im Sonderzeichen bereich unter 32 oder sogar im Minusbereich). Der einzige Anhaltspunkt hätte eigentlich nur LoadLibrary+GetProcAddress sein dürfen... hmm??

Zu 2)
Das sind die Schutzmechanismen, die eingebaut waren:
Code:
__forceinline bool  isDebugger0()
{
	if (!pfOutputDebugStringA)
		return true;
	__ asm xor edx,edx
	pfOutputDebugStringA("");
	s32 nEDX;
	__asm mov nEDX,edx
	return nEDX != 0;
}
Borland-Debugger setzen edx auf != 0 nach einem OutputDebugString-Aufruf, zumindest hab ich das gehört.
Code:
__forceinline bool isDebugger1()
{
	if (!pfIsDebuggerPresent)
		return true;	
	BOOL bRes = pfIsDebuggerPresent();
	return bRes  == TRUE ? true : false;
}
Simpler Schutz gegen Ring 3 Debugger.

Code:
__forceinline bool isDebugger2()
{
	bool bFound = false;
	EnumChildWindows(HWND_DESKTOP, _enumChildren, (LPARAM)&bFound);
	return bFound;
}
Suche nach Fensternamen, liefert true wenn es irgendwas findet, was Debug, Dbg oder ICE enthält.

Code:
struct Uncatchable { int foo; };
__forceinline bool isDebugger3()
{
	LPTOP_LEVEL_EXCEPTION_FILTER p = SetUnhandledExceptionFilter(_handleUnhandledException);
	throw new Uncatchable;
	SetUnhandledExceptionFilter(p);
	return !bCaughtException;
}
Sollte eigentlich Debuggern eine Exception reinwürgen, falls sie den Ring3-Check mit isDebuggerPresent überstehen..

Und keine davon zieht bei euch? Mist ;)

Original von CDW
PS: Edit: also DEADBEEF und FEED1337 als Hexwerte zu nehmen war eine originelle Idee und hat mir gefallen :D
DEADBEEF ist nicht mein Werk, das hat IBM verbrochen. :-) Siehe auch das Jargon-File: http://www.jargon.net/jargonfile/d/DEADBEEF.html

p.s.: Sorry wegen des Problems mit den Leerzeichen im Key (lang lebe der Genetiv), mir das selber auch aufgefallen, ich habs mir aber nicht aufgeschrieben und dann schlichtweg vergessen :-/ Nächstes Mal halt %05d.
 
Warum haben sämtliche Schutzmechanismen bei CDW versagt
Die hatten wohl Angst ;)
Ich habs auch gerade ausprobiert Deine Keygenme im Olly zu laden - es kann geladen und ausgeführt werden.
Zu 1): ich kann auch bei geladener Keygenme alle API-Namen finden und lesen - allerdings bringt mir das wenig ohne die Adressen zu kennen, man kann aber neuladen und auf den Stringbereich einen "on Access Memory" Breakpoint setzen.
Oder GetProcAddress finden (die Importtabelle ist ja da) und da einen Memory-BP setzen. Dann kann man immer mitlesen was gerade importiert wird und noch wichtiger wo es landet -> hier kann man wieder an ausgesuchten APIs einen BP setzen.
Wenns hart kommen sollte, dann schaue ich in einem anderen Programm nach den selben APIs und deren Adressen im Kernel - und setze da einen BP drauf. Allerdings würde hier MFC wohl leichte Schwirigkeiten bereiten.

zu 2) Ssoweit ich weiß wird beim Debuggen mittels WinAPI vom System der Prozess eingeforen und wenn der fortgesetzt wird, gilt die nächste Anweisung als BP.
Übrigens, sicher dass Du IsDebuggerPresent eingebaut hast? Ich kann sie nirgendwo finden. Und von Exceptions wurde ich auch nicht behelligt, obwohl diese Methode eigentlich funktionieren sollte ;)
Wer Borlanddebugger verwendet ist selber schuld *g* (der ist zwar super für eigene Borlandanwendungen, aber sonst nicht so toll).Den OutputDebugString finde ich übrigens auch nicht.

Allerdings wie erwähnt haben wir uns schon mit entpackten Keygenmes rumgeschlagen. Wenn ich da so an sartres Crackmes denke, bei denen jeder Entpacker versagt hat und man schweres Geschütz auffahren musste *schauder*
 
Zurück
Oben