Was sind die
Intentionen für dieses Werk:
Ich bin selbst Shareware Programmierer und möchte allen anderen
Sharewareprogrammieren Tips geben, wie sie ihre Werke besser schützen
können. Ich habe wirklich sehr gute Sharewareprogramme gesehen, die
jedoch so einfach zu cracken waren, daß die Programmierer den richtigen
Registrierungscode gleich in die Anleitung schreiben könnten. Damit
so etwas nicht erneut passiert, versuche ich hier ein möglichst weites
Feld von Tips abzudecken, um Sharewareprogramme besser zu schützen.
Einige Passagen stammen aus Anleitungen von Fravia+ Webseite, die ich mehr
oder weniger frei übersetze.
Wie denkt ein Cracker
?
Um gute Schutzalgorhythmen zu schreiben, sollte man möglichst
viel über die Vorgehensweise von Crackern wissen.
Es gibt zwei Arten von Crackern. Die ersten wollen möglichst viele
Programme cracken, die zweiten wollen Wissen über Funktionen, die
Programme schützen erlernen und mit anderen Gleichgesinnten austauschen.
Ich gehe nur auf die zweiten ein.
Wenn ein Cracker ein Programm cracken will, macht er das aus zwei Motivationen
heraus: Entweder ist ein Programm besonders gut, oder das Programm ist
(auf den ersten Blick) sehr gut und trickreich geschützt. (Das stammt
z.B. von Fravia+ Seite.)
Wenn ein (idealer) Cracker die Arbeit beginnt, sollte er so anfangen:
Während das Programm im Hintergrund in Assembler zerlegt wird, durchforstet
man das Programm nach Anhaltspunkten. Dann startet man das Programm erneut
und schaut auf welche Windows Registry oder Dateien das Programm zugreift.
So jetzt beginnt man mit dem Suchen nach Anhaltspunkten im Assemblercode
und beginnt die Datei zu patchen. Neustart des Programms. Wenn es jetzt
registriert ist, dann war es nicht sonderlich geschützt. Ansonsten
lädt man das Programm in einen Debugger, geht in den Screen, in dem
man den Reg-Code eingeben kann und setzt einen Breakpoint auf die Funktion,
die die eingegebenen Werte in den Speicher lädt. Dort geht man dann
jede Assembleranweisung einzeln durch, bis man auf den fertigen Code trifft.
Überbrücken
Ich werde öfter von Überbrücken reden. Was meine ich
damit eigentlich ?
Bei Abfragen der Systemzeit ob Prüfzeit schon abgelaufen, niemals so was machen:
Systemzeit prüfen
Wenn abgelaufen, dann aussteigen
Sonst weitermachen
In Assembler sieht das (ungefähr) so aus:
GetSystemDate ; Systemzeit prüfen
????????????? ; Installationsdatum aus Datei
lesen
cmp eax, 10 ; Mit 10 hex vergleichen
jl XXXX ;
Wenn kleiner, dann Springe nach Adresse XXXX
Steigeaus ; und raus
man muss in einem Hex-Editor nur noch ein Byte ändern (in "immer
springen" ASM:jmp), um das Ende der Prüfphase niemals zu erreichen.Besser
zwischen Zeile 2 und 3 irgendwelchen Müll mit vielen Sprüngen
einfügen, um den Cracker zu verwirren.
Anmerkung: Sprünge in Assembler entstehen im seltensten Falle
durch Sprünge im Quellcode, sondern durch if-Abfragen.
Analog gilt dies für Seriennummern berechnen. Das sieht meistens so aus:
CALL XXXX ;ruft Berechnung
der Seriennummer auf und vergleicht
diese mit der Eingegebenen. Wenn richtig, dann Rückgabe-
wert 1, sonst 0
TEST EAX,EAX ;wenn 1
je XXXX ;dann
springe zu "richtige Nummer-weiter im Programm"
RAUS
;sonst Raus
Auch ist hier nur eine Änderung von einem Byte nötig. Sonst
gilt: Hier ist klar, daß die Seriennummer in der mit CALL aufgerufenen
Prozedur generiert wird. Also rein und auslesen. So sieht es in 80% aller
SW-Programme aus und die Programmierer könnten die richtige Seriennummer
in solchen Fällen gleich in die Hilfedatei schreiben.
Viel mehr Mühe macht das Auslesen aus dem RAM auch nicht. Mein
persönlicher Rekord für solch ein Abfrage war 48 SEKUNDEN und
ich bin noch ein (fortgeschrittener) Anfänger. Man sollte zwischen
dem CALL und dem TEST viele Dinge reinprogrammieren, die nichts mit der
Generierung zu tun haben.
Präventionen, die man schnell und einfach programmieren kann:
Man sollte wenigstens ein Minimum an Ahnung haben, wie das Programm, das man geschrieben hat auf "Low-Level" Ebene funktioniert. Wenn man bloss die Entwicklungsumgebungen und RAD Tools sieht, kann man es eigentlich gleich vergessen, Software effizient zu schützen (ausser man ist wirklich clever und ein sehr guter Programmierer).
Als erstes möchte ich sagen, daß jedes Programm das den Quellcode der Sharewareversion beinhaltet auch zu Cracken ist. Das kann ich sagen, da man vor Debugger und Disassembler nichts (wirklich gar nichts) verstecken kann. Wenn man lang genug sucht, wird man auch fündig. Man kann also das Cracken nicht verhindern, sondern nur so lange wie möglich herauszögern und hoffen, daß der Cracker das Interesse verliert. Die folgenden Tips sind meiner Meinung nach nicht unnützlich, um das zu erreichen.
Zuerst eine generelle Warnung. Benutzen sie niemals kommerzielle Programme,
die ihr Programm schützen sollen. Diese sind zumeist sauschlecht und
sowieso alle schon gecrackt. Das gleiche gilt für EXE-Packer, die
die EXE-Datei erst
in den RAM laden und dort entschlüsseln. Damit ist es wie mit
Fernsehwerbung. Während man entpackt holt man sich was zu essen. Deshalb
störts nicht wirklich.
Fangen wir mit den kleineren, allgemeineren Dingen an, die man mit minimalem
Programmieraufwand bewerkstelligen kann.
Zuerst sollte man niemals Funktionen oder Prozeduren aus DLL-Dateien
importieren, die schon am Namen erkennen lassen, was sie bewerkstelligen
sollen. Bekannte Beispiele, wie man Prozeduren nicht nennen sollte sind
z.B. die Firma Ulead, die ihren Prozeduren traditionell z.B. IsFullVersion
nennt. Raten sie mal, was diese Prozedur testet ;-). (Auch IsValidSerial
gehört zu meinen Favoriten)
Analog kann man das für die Namen der Einträge in der Windows-Registry
oder INI-Dateien anwenden. Es gibt ein Tuningtool (Name wird hier nicht
genannt), das liest aus der Windows-Registry einen Wert mit dem Namen IsRegistered
aus.
Wenn dieser Wert 0 ist, startet das Programm als Shareware, ist der
Wert jedoch 1, dann besitzt man die Vollversion.
Ohne zu denken haben auch die Programmierer von Pixel 3D programmiert. Zu erst einmal Glückwunsch. Zuerst dachte ich, daß sie alles richtig gemacht hätten, um mir das Leben schwer zu machen. Dann habe ich mir was neues ausgedacht (habe ich auch noch nie irgendwo gelesen). Ich löschte einfach alle Eintragungen für Pixel 3D in der Windows-Registry und überbrückte die daraufhin auftretenden Fehlermeldungen. Dann hatte ich die Vollversion. Will sagen: Wenn irgendwas passiert, das gar nicht sein dürfte, muß das Programm immer als Sharewareversion starten. Der ehrliche Kunde kann das Programm ja mit seinem Schlüssel erneut registrieren. (Ein gutes Beispiel dafür ist Microangelo).
Was ich für ziemlich scheiße halte, aber durchaus ein adäquates
Mittel gegen Cracker ist, ist das Löschen von wichtigen Dateien, wenn
irgendwas merkwürdiges auftritt. Man sollte um eine Neuinstallation
nicht herumkommen. Ähnliches gilt für einen Systemneustart. Das
sollte man allerdings nur tun, wenn man absolut überzeugt ist, dass
der entsprechende Programmteil
100% funktioniert, da man sonst ehrliche Kunden verärgern könnte.
Wenn sie eine Hilfedatei schreiben, sollten sie nichts erwähnen,
was auch nur halbwegs einem Cracker helfen könnte. Nicht mal
irgendeinen Hinweis auf den Code (10 Ziffern/Buchstaben...). Am schlimmsten
war bisher bei einer Cheatsammlung (Das geht nur bei viel früheren
Versionen, deshalb erwähne ich es hier). In der Hilfedatei stand,
daß der Code in der Form 11111-2222-333 (oder so ähnlich) eingegeben
werden muss. Nicht nur das die Form gegeben war, der Programmierer hat
auch noch einen anderen kapitalen Fehler begangen: Wenn man als Namen 0
eingibt, lautet das Password 00000-0000-000. Es scheint, daß die
Berechnung des Passwords nur auf Multipliktionen beruht und da ein Glied
0 ist, weiß man was da passiert ist. Dies gilt übrigens auch
noch für einige andere Programme. In der Hilfedatei sollte man wenn
überhaupt, dann falsche Informationen über das Passwort geben.
Beispiel: Name des Programms weis ich nicht mehr. "Sie bekommen die
Datei keyfile.dat zugesandt, um das Programm zu registrieren." Hab ich
zuerst auch gedacht, wurde aber stutzig, als im ASM-Code kein solcher String
zu finden war, wo der Programmierer doch auch sonst alle wichtigen Strings
"hardgecodet" hat. Am Ende stellte sich heraus, das keyfile.dat ein Trick
war, und der richtige keyfile anders hies.
Ein anderes Beispiel ist ein CrackMe, das jemand aus unserer Gruppe
(greets Shadow) programmiert hat. Wenn man die Strings durchsucht findet
man shadow.key und xxx.123. Beide Strings sehen aus, wie potentielle Keyfiles,
der richtige keyfile heisst aber ganz anders.
Vermeiden sie auch (wichtige) Strings "hardzucoden". Dies ist immer
der erste Anhaltspunkt, wenn man ein Programm crackt. Viel besser ist es,
wenn man Strings aus ASCII-Zeichen zusammensetzt. Bsp.: char(65)+char(66)...
Besonders tödlich sind deshalb MessageBoxes und Textfelder in
Nag-Screens. Das Spiel kann man jedoch umdrehen und die wichtigen Strings
verbergen und dafür die gleichen Strings (wirklich richtige Strings)
an anderer unwichtigen Stelle mit einer kleinen Abfrage, die nie erfüllt
werden kann in das Programm einbauen, so das der Cracker von einem völlig
falschen
Ansatzpunkt ausgeht. Auch lustig ist, wenn man (echte) Strings einbaut,
die so auch vom Compiler eingebaut werden könnten (z.B. GetWindowText,
ShowWindow, 7ABE1F90). Manche Disassembler schaffen es dann nicht mehr
diese
Strings als Strings vom Programmierer einzuordnen, sondern versuchen
verzweifelt die Strings in den Programmablauf als Befehler einzubauen,
was dazu führt, daß der Disassembler abstürzt. Die Stringstips
gelten nicht für Visual Basic, d a V B
d i e S t r i n g s s o
a b s p e i c h e r t (nämlich mit ASCII 00 zwischen den Zeichen)
und man sie dann nicht mehr findet (in herkömmlichen Disassemblern.
Es gibt auch welche für VB, den hab ich aber noch nicht)
Die imaginäre Anwendung Win-Dummy
Soweit zur allgemeinen Benennung. Der nächste Abschnitt befasst
sich damit, wie man das Ausspionieren der richtigen Registrierungsnummer
erschweren kann.Ich kreiere eine absolut imaginäre Anwendung, die
alle Fehler enthält, die
ein Programmierer machen kann. Nennen wir sie Win-Dummy. Sie verhält
sich so, wie man es von einem Sharewareprogramm gewöhnt ist: Nagscreen,
Zeitlimit,Registrierungscode,Einschränkungen...
Fangen wir mit dem an, was man sieht, wenn das Programm startet. Bei
sehr vielen Sharewareprogrammen startet man das Programm ganz hoffnungsvoll
und erblickt dann *PENG* einen Nag-Screen. Ums mal mit den Worten einer
Jeans-
Werbung auszudrücken: "Bad idea, bad idea". Wenn man mal davon
ausgeht, daß das Programm mit einer Seriennummer/Keyfile... zur Vollversion
aufrüsten kann, dann muss irgendwo eine Abfrage für diesen Nag-Screen
stehen, die man überbrücken kann. (Man identifiziert sie meistens
mit Strings wie "Noch XX Tage Zeit". Viel schwerer zu cracken- aber auch
speicherintensiver- sind BMP-Dateien, die man mit eigenen Routinen reinlädt.
Verwendet man die vordefinierten API Befehle kann man es auch gleich lassen.
Dieser Tip ist jedoch zu schwer zu realisieren für ein Sharewareprogramm.
Das dabei der Cracker den Nagscreen nicht mehr ertragen muss, ist dabei
noch das geringere übel. Viel schlimmer ist die Tatsache, daß
eine Abfrage geschehen muss, ob die Version registriert ist. Das muss man
aus einer Datei auslesen (INI/CFG/DAT/Windows Registry...). Dort ist entweder
etwas wie IsRegistered=0 bzw. IsRegistered=1
oder
der Benutzername und die daraus resultierende Seriennummer
gespeichert:
Um das recht schnell rauszukriegen gibt es zwei Freeware-Tools, die eigentlich für Programmierer gedacht sind. Vielleicht fragen sie sich, worauf ich hinaus will. Ganz einfach, entweder ist der Nag-Screen ziemlich einfach zu überbrücken oder man zeigt dem potentiellen Cracker, wo bzw. wie der richtige Code berechnet wird.
Wenn man schon einen Nagscreen benutzt, dann meistens, um dem User anzuzeigen,
wie lange man das Programm noch testen darf. Mal davon abgesehen, daß
die Zeitabfrage einfach zu überbrücken ist, wenn man die vorgefertigten
Funktionen wie GetSystemDate benutzt, sollte man diese Funktion nicht
benutzen. Der User kann das Systemdatum ja nach Herzenslust verstellen.
Um dies wenigstens einzuschränken, sollte man das Datum des letzten
Programmstarts verschlüsselt speichern und bei irgendwelchen Merkwürdigkeiten
(z.B.aktuelles Datum das Programm beenden.
Eine viel effektivere Anti-Cracker-Methode, um das Datum auszulesen,
ist eine der Dateien System.dat oder Bootlog.txt. Bei jedem Systemstart
werden diese Dateien (normalerweise) aktualisiert und beinhalten so das
neue Datum. Ausserdem kommt da niemals ein Cracker drauf, das auszuprobieren.
(Hab auch noch keinen Programmierer gesehen, der das gemacht hat)
Schlechtes Beispiel: Ich habe vor einigen Tagen eine Anwendung gecrackt,
deren Testphase niemals abläuft, wenn man folgendes tut: Zeit 10 Jahre
vor; Programm installieren; Zeit 10 Jahre zurück und schon hat man
ca. 3600 Tage, um das Programm zu testen. Bis dahin sollte eine neue Version
draussen sein ;-).
Wenn wir den Nagscreen endlich überwunden haben, dann steht in
vielen Programmen, die unregistriert sind (meistens im Fenstertitel) UNREGISTRIERT.
Da bedankt sich jeder Cracker. Wieder ein Ausgangspunkt für einen
Crack mehr.
Wenn man so etwas schon macht, dann sollte man wenigstens nicht innerhalb
der gleichen Prozedur noch den Fenstertitel verändern. So zeigt man
nämlich die Prozedur an, die es zu überbrücken gilt. In
manchen Programmen (ich glaube
z.B. WinRar) genügt es das Ändern des Fenstertitels zu überbrücken
und schon hat man eine registrierte Version. (Einwurf: Gerade fällt
mir ein: Gibt es vielleicht Programme, die den Programmstatus am Fenstertitel
festmachen ?
Wenn ja, dann verdienen die Programmierer ihr Geld nicht !) Das selbe
gilt für den Text, der in der Copyrightsbox steht (Registriert von...).
Wenn wir uns ein wenig in Win-Dummy umsehen, dann bemerken wir, das
es extrem in seinen Funktionen limitiert ist. Das erkennt man teils daran,
das manche Menüs und Buttons "grau" sind und nach Drücken auf
andere Buttons eine
Messagebox erscheint, die mir mitteilt, das diese Funktion nur in der
Vollversion vorhanden ist.
Einwurf: Definieren sie alle Menüs dynamisch, während das
Programm startet.
Bereits definierte Menüs kann man mit einem Ressource-Workshop leicht
verändern (Menüpunkte aktivieren...).
Das "ausgrauen" von Menüs ist prinzipiell schon mal schlecht. Irgendwo im Programm muss der Code stehen, der das macht. Dort steht der Win-API Befehl EnableMenuItem und der Name des Menüs, den man aus dem Programm her kennt. Schwerer zu finden ist ein Menü, dessen Namen man nicht kennt. (Aufpassen auf Hilfedatei) Das komplette nicht-anzeigen von Menüpunkten ist deshalb um einiges sicherer. Was ich von MessageBoxes halte, sagte ich ja weiter oben bereits.
Jetzt wenden wir uns dem Ausspionieren des Registrierungscodes zu. Das erste Problem, das hierbei auftauchen sollte ist: Wo zur Hölle muss ich den Code eingeben ?
Am besten ist es, wenn man eine verstecktes Eingabefenster programmiert,
daß nur auf Tastendruck erscheint. Diese Tastenkombination könnte
etwas ausgefallenes wie [CTRL]+[ALT]+[ENTF] ;-) sein. Besser ist jedoch
wenn man
als Kombination [CTRL]+[D] wählt (Ich gehe nicht weiter darauf
ein, es hat aber was mit dem Debugger zu tun.).
Jetzt kommen zwei meiner Lieblingstricks, die ich bei meinen CrackMes
gerne benutze. Zuerst sollte man die Eingabefelder falsch herum bennenen
(Feld für Name heisst "Hier Code eingeben" und anders herum). Da muss
man erst mal draufkommen. Dies setzt natürlich voraus, daß keine
Einschränkungen für das Textfeld vorhanden sind (max 10 Zeichen/nur
Ziffern...).
Mein zweiter Lieblingstrick ist, daß man zwei Eingabefelder für
Namen und Code programmiert und darunter einen OK-Button setzt. Den Code
checkt man bei jeder Änderung der Textfelder (dann darf natürlich
keine MessageBox kommen, wenn der Code falsch ist.). Wenn man den OK-Button
drückt, ist der Code IMMER falsch und es erscheint IMMER die "Falscher
Code-Box" (natürlich ASCII(65)+ASCII(66)...).
Aber warum ist man auf Eingabefelder beschränkt ? Etwas komplett neues und definitiv extrem schwer zu crackendes Verfahren zur Kalkulation eines Codes ist nicht ein Eingabefeld zu erzeugen, in das man den Code eingibt, sondern eine 10x10-Matrix aus Checkboxes zu erschaffen, bei der jede Kombination markiert/unmarkiert genau einem Namen zuzuordnen ist. Auch andere Eingabefelder (ComboBox/ListBox...) sind dazu zu gebrauchen (Phantasie ist gefragt).
Zur Codeberechnung:
Zuerst muss man Variablen deklarieren. Wenn das geschieht reserviert
das Programm im Speicher je nach Typ der Variablen Platz und dahinter beginnt
der Speicherplatz der nächsten Variablen. Also die Variablen für
Name, Code und richtigen Code so weit wie nur möglich von einander
weg deklarieren. Als schlechtes Beispiel kann ich hier ein Programm von
mir nennen. Ich war bei einem Freund (auch Cracker). Er startet den Debugger,
dann mein Programm und fängt an zu lachen. Dann zeigt er mir, daß
Name, eingegebener und richtiger Code keine 100 Bytes voneinander entfernt
im Speicher liegen.
Man sollte niemals die komplette Registrierungsnummer auf einmal berechnen.
Besser ist es sie in zwei oder mehr Teile zu zerlegen und dann einzeln
mit den entsprechenden Teilen des eingegebenen Codes zu vergleichen. Die
Registrierungsnummer sollte man 1000 mal einlesen (hat auch was mit dem
Debugger zu tun) und die Berechnung des Codes auch 20-30 mal durchlaufen
lassen. Dabei gilt: Je komplexer die mathematischen Operationen sind, die
man benutzt, um den Code zu berechnen, desto weniger wahrscheinlich ist
es, daß der Cracker bemerkt, daß er sich in einer riesigen
Schleife befindet. Man
sollte eh jede Menge Müll und unnötige Mache-Nichts-Funktionen
während der Codeberechnung aufrufen, die den Cracker verwirren. Zumindestens
ein Key-Generator wird dadurch absolut unwahrscheinlich. Ebenfalls sollte
man die Schleifen möglichst gross machen, damit der Cracker nicht
merkt, das er sich in einer Schleife befindet und einfach einen Breakpoint
dahintersetzt.
Lustig ist in diesem Zusammenhang auch die "Fake"-Serial Berechnung.
Dazu bastelt man zur echten Prozedur nochmals eine hinzu, die eine falsche
Nummer ausrechnet. Wenn der Cracker diese im RAM sieht und nicht mitdenkt,
wird er
denken, daß er die richtige Nummer gefunden hat und verzweifelt
an der "Falscher Code"-Meldung.
(Ein bißchen) Schwer zu cracken ist auch eine Codeberechnung, die nicht mit Werten rechnet, sondern mit Zeigern auf Speicheradressen.
Wenn man schon eine MessageBox mit "echten" Strings verwendet, dann sollte man den Code zweimal checken. Einmal mit Box und einmal ohne. ACHTUNG: Nicht zweimal die gleiche Prozedur aufrufen, sondern zwei verschiedene.
Ist die Falsche Code-Meldung erschienen, dann sollte das Programm zwei Sekunden keine Eingabe zulassen. Das verhindert das Rausfinden von Codes durch Brute Force Verfahren. Brute Force heist "brutale Gewalt" und bedeutet, man hat ein kleines Programm, das ganz schnell alle Zeichenkombinationen als Code ausprobiert. Es gibt solche Programme, die können mehrere tausend Codes pro Sekunden prüfen, aber nur wenn das Zielprogramm mitspielt.
Dummheit ist natürlich, wenn man die richtige Seriennummer in die KEY/DAT/INI/CFG... Datei schreibt, statt der eingegebenen. Dann muss man nur einmal die Abfrage überbrücken und schon hat man die richtige Seriennummer für jeden beliebigen Namen (siehe Goldwave 3.24 in V4.02 hat der Programmierer es jedoch bemerkt ;-)). Auch nicht gerade von Intelligenz zeugt die Routine von Hex Workshop 2.54. Wenn man da einmal die Routine überbrückt, erzeugt HW einen gültigen Keyfile. (Habe den Programmierern geschrieben, aber nie eine Antwort erhalten :( ).
Wenn der Code berechnet ist, sollte man alle Variablen, die der Codeberechnung
dienen auf 0 (Integer) und (leer) (String) setzen, damit das durchsuchen
des RAM verhindert wird.
Dinge, die schwer zu programmieren/cracken sind, die ich nicht in meiner kleinen Geschichte hab unterbringen können, oder die ich mir gerade ausgedacht habe (Ob sie funktionieren ist eine andere Sache):
Die folgenden Dinge sind zum Teil schwer zu programmieren oder schwer zu cracken. Manche sind jedoch zu überladen für ein Sharewareprogramm und eignen sich mehr für den Einsatz in kommerziellen Programmen.
1. Wenn man einen Prüfsummencheck durchführt und eine Fehlermeldung ausgibt, ist der meistens einfacher zu cracken, als das eigentliche Programm. Viel lustiger ist es, eine EXE und eine DLL Datei zu programmieren, die sich gegenseitig überprüfen und ohne Fehlermeldung aussteigen, wenn etwas nicht stimmt.
2. Wäre es möglich, den Namen der Datei, in der die Informationen gespeichert sind aus der richtigen Registrierungsnummer zu erstellen und dann aus der Windows-Registry darauf zu verweisen ? Das hätte den Vorteil, das zu Beginn niemand wüsste, wie der Name der Datei ist (nicht mal das Programm selbst).
3. Was ich in meinem nächsten CrackMe mache: Das Eingabefeld hat die gleiche Farbe, wie das Hintergrundfenster und besitzt keinen Rahmen. Dann kann man es nicht mehr erkennen. Das eingegebene Passwort wird überprüft, sobald sich im Eingabefeld etwas ändert.
4. Irgendwo im Programm Strings einbauen, die identisch mit den "Falscher Code"/"Danke" Strings sind, aber eigentlich nichts damit zu tun haben.
5. Möglichst einen Punkt am Ende des Passworts verwenden, da diese im Debugger schwer zu erkennen sind. Man sieht norwalerweise das Passwort so:
OFFSET HEX-CODE DES PASSWORTS
PWD IN ASCII
XXXX:XXXX 00 00 00 00 00 00 00 00
........
XXXX:XXXX 65 66 67 68 69 70 71 2D
ABCDEFG.
XXXX:XXXX 00 00 00 00 00 00 00 00
........
Wer im Freudentaumel nur einen flüchtigen Blick darauf wirft, denkt, das der Punkt hinter G nicht mehr zum Password gehört, sondern nur als Platzhalter für ASCII 00 gilt, wie die anderen Punkte.
6. Wenn man schon "-" benutzt, um das Password zu unterteilen, dann sollte man explizit nach den Strichen fragen, und nicht das gesamte Passwort mit Strichen berechnen. Außerdem ist eine regelmäßige Strichesetzung (XXX-XXX-XXX) einfacher zu cracken, als z.B.X-XXXXX-XXX.
7.Auch noch nirgendwo gelesen. Normalerweise sieht die Abfrage für einen Nag-Screen so aus: C++-Code
int a=0;
a=PasswortVerifizieren();
if (a==1) NagScreen();
wenn man aber schreibt:
int a=0;
int b=0;
CheckPassword(); //Rückgabewert
b muss 1 sein, sonst wurde Prozedur übergangen
if (b==0) then PasswortCheckWurdeUebergangen();
if (a==1) then ShowNag();
(Alternativ ginge auch (sogar besser): if ((a==1)||(b==0))
// für alle nicht C++ler || bedeutet oder)
Prozedur :
CheckPassword():
{
Code, um das Passwort zu verifizieren; wenn falsch a=1;
b=1;
}
Jetzt kann man nicht mehr hergehen, und den gesamten Call übergehen. Natürlich ist es weiterhin möglich, die Bedingung der PassWortWurdeUebergangen Routine zu ändern, aber wer sagt denn, dass man nur mit einer Kontrollvariablen und ohne Prozedurverschachtelungen programmiert. (Bischen Phantasie bitte)
8. Ein Cracker geht immer vom idealen Programmierer aus: Nur Prozeduren, lokale Variablen... Zumindest beim Passwortcheck und anderen solchen Dingen sollte man vollkommen ohne Prozeduren, sondern mit Copy/Paste im Quellcode arbeiten. Das bedeutet, wenn man das Passwort schon zweimal überprüft, dann ohne Prozedur. Beispiel: Wenn man eine Prozedur 1000 mal aufruft, genügt meistens schon eine Änderung von max. 8 Bytes, um den Aufruf zu übergehen. Wird der gleiche Code aber 1000 mal hintereinander aufgerufen, muss man (wenn man Pech hat) 1000*8 Bytes ändern und das macht keiner.
9. Wenn man Delphi oder C++ Builder programmiert und die vorgefertigten Komponenten benutzt (z.B.Label) kann man ruhig Dinge wie "Unregistriert" als Anfangstext verwenden, da diese Strings verschlüsselt in die EXE-Datei kompiliert werden.
10. Die Informationen, ob das Programm registriert ist, sollte man in die Haupt EXE-Datei schreiben. Weis nicht, wie das geht, weis nur, daß es geht. Siehe: Visual Help Pro.
11. Wenn die Registriernummer auch noch von der Hardwarekonfiguration (Intel/AMD oder anderer CPU Hersteller?/ 16/32.. MB RAM?/ Festplatte C: größer 4 GB?) abhängt, ist alles aus. So kann man das Verbreiten von Codes über das Internet verhindern. Nachteil: Kunden müssen bei Änderung der Konfiguration neue Codes beantragen. Nicht so toll finde ich auch die Methode, die die Programmierer von Visual Help Pro gewählt haben. Da hängt der Registrierungscode vom Monat der Registrierung ab.
12. Man sollte prüfen, ob der Name Sonderzeichen enthält, da kein normaler Name so lauten kann: LaZaRuS [hf] - ED!SON - +wAj. - _mammon - ][ce usw. Bei - muss man vorsichtig sein, da es sich um einen Doppelnamen handeln könnte: Karl-Heinz.
13. Absolute Sicherheit kann es nur geben, wenn in der Sharewareversion Programmteil fehlen (DLL-Dateien), die die wichtigen Funktionen enthalten. Beispiel: Audio Grabber 1.40. Die EXE-Datei ist bei SW und Vollversion die gleiche. Nur fehlt in der SW-Version die DLL AudioFull.dll (oder so ähnlich). In der SW Version ist nur die Datei AudioFree.dll (oder so ähnlich) enthalten. Diese SW findet man dann aber auf Warez-Seiten.
14. Man könnte checken, ob Fenster geöffnet sind, in denen folgende Strings vorkommen "W32Dasm", "IDA", "Smart Check", "WinSight". Wenn es solche gibt, dann sieht nach Crack Versuch aus."
15. Es gibt spezielle Codefolgen, die bringen gnadenlos jeden Disassembler zum Absturz. Die kenne ich jedoch nicht, also müssen sie selbst nachforschen, wenn sie dies in ihre Programme implementieren wollen.
16. Man kann feststellen, ob ein Debugger geladen ist. Geht über
einen Interrupt (13?). Darüber weis ich jedoch auch nichts genaues.
Oliver Buschjost (http://software.webset.de/buschjost) benutzt in seinem
Programm MP3 TO EXE 2.0 solch einen Debugger Check (von Marquee) der einen
mit den Worten "You wouldn't see this if there wasn't a debugger running
in the background" oder so ähnlich begrüsst.
Dinge, von deren Wirkung Sharewareprogrammierer so überzeugt sind, das sie sie immer wieder benutzen, obwohl sie den Crack in keinem Fall erschweren
Hier sind Dinge, die ich immer wieder in Sharewareprogrammen sehe. Die Programmierer glauben wohl, das sie unserer "Gilde" die Arbeit damit erschweren. Das stimmt aber in keinem Fall. Statt die folgenden Massnahmen zu implementieren sollte man mehr Zeit auf die oben genannten verwenden.
1. Manche Leute glauben, das es schwer ist Seriennummern rauszukriegen, wenn man keine MessageBox "Wrong Serial" bringt. Sie zeigen stattdessen nur eine, wenn das Programm korrekt registriert wurde. Das ist jedoch genausoviel wert. Irgendwo muss ja etwas stehen wie:
CALL XXXXXX ;; Berechne RegCode und vergleiche
mit eingegebenem
TEST EAX, EAX ;; RegCode korrekt ?
JE 1234 ;; Wenn ja, dann
springe
...
;; Sonst weiter im Programm
1234: ???? ;; Zeige hier MessageBox "Thank you" an
Wenn ich also keine "Falscher Code" Box finde, dann suche ich nach "Thank..." (englische Programme) oder "Danke.." (deutsche Programme). Für was sollten die Phrasen sonst stehen ?
2. Es gibt Programmierer, die glauben ein ellenlanger (30+ Zeichen) RegCode wäre schwerer zu knacken, als ein kurzer (-15). Diese denken jedoch nur an Brute Force Verfahren und nicht an die "wahre Kunst". Wenn die Routine so aussieht.
CALL XXXXXX ;; Berechne RegCode und vergleiche
mit eingegebenem
TEST EAX, EAX ;; RegCode korrekt ?
JE 1234 ;; Wenn ja, dann
springe
und man den Code in irgendeinem Register (oder nahe der Position des eingegebenen Namens) auslesen kann, könnten sie auch einen RegCode aus 100 Zeichen bestehen lassen.
3. Das gleiche gilt für das Verwenden von "-". Es nützt gar
nichts, wenn man den RegCode irgendwo im RAM auslesen kann. Besser ist
sowas:
if (3. Zeichen des Codes "-") then
if (6. Zeichen des Codes "-") then
if (9. Zeichen des Codes "-") then
Beginne Code Berechnung
Visual Basic Programme
Zuerst dachte man VB Programme sind schwerer zu cracken, als "richtige"
Programme. Ich schreibe "richtige" Programme, weil VB keine echten EXE
Dateien erzeugt. Stattdessen ist VB eine Interpretersprache, die Befehle
an die Runtime Module VBRUNXXX.DLL schickt, die die DLL dann ausführt.
Da es mittlerweile aber sehr gute Decompiler für Visual Basic EXEs
gibt, ist auch VB Cracken kein Problem mehr.Wenn ich im Vorgänger
dieses Dokuments noch schrieb, das die Tips nicht für VB Programme
gelten, so muss ich heute sagen, dass die Tips auch voll für VB gelten.
Ein weiterer Ansatz VB zu cracken hat Razzia in einem Tutorial beschrieben.
Mit einer leicht modifizierten VBRUNXXX.DLL erscheint nach einer falschen
RegCode Eingabe nicht die "Falscher Code" MessageBox, sondern eine MessageBox
mit der korrekten Serial. (Ich lache immer noch jedes mal, wenn ich das
sehe).
btw: Das funktioniert auch, wenn der Programmierer keine MessageBox
erscheinen lässt, da nicht die "Falscher Code" Box "missbraucht" wird,
sondern eine (so gut wie ungenutzte) Routine, die irgendwo in der VBRUNXXX.DLL
schlummert.
Soft-Ice (den verbreitetsten Debugger) feststellen:
Diesen Beispiel-Code für C++ habe ich kürzlich gefunden:
//////////////////////////////////////////////////////////////////////
//
// MeltICE - SoftICE '95 version 3 detection
- Made by David Eriksson
// ==================================================================
//
// Disclaimer
// ~~~~~~~~~~
// I take no responsibility for the authenticity
of this information,
// or the results of the use or misuse of the
source code.
//
// SoftICE is a trademark of NuMega Technologies,
Inc.
//
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//////////////////////////////////////////////////////////////////////
//
// See if SoftICE version 3.x for Windows 95
is loaded
//
BOOL IsSoftIce95Loaded()
{
HANDLE hFile;
// "\\.\SICE" without escape stuff
hFile = CreateFile( "\\\\.\\SICE",
GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ
| FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if( hFile != INVALID_HANDLE_VALUE )
{
CloseHandle(hFile);
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
//
// See if SoftICE version 3.x for Windows NT
is loaded
//
BOOL IsSoftIceNTLoaded()
{
HANDLE hFile;
// "\\.\NTICE" without escape stuff
hFile = CreateFile( "\\\\.\\NTICE",
GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ
| FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if( hFile != INVALID_HANDLE_VALUE )
{
CloseHandle(hFile);
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
//
// Example code for calling these functions
//
int main(void)
{
if( IsSoftIce95Loaded() )
printf("SoftICE for Windows 95 is active!\n");
else if( IsSoftIceNTLoaded() )
printf("SoftICE for Windows NT is active!\n");
else
printf("Can't find SoftICE with this method!\n");
return 0;
}
Final words
~~~~~~~~~~~
Hopefully this will make shareware developers
a little bit easier
about the safety of their software. I would appreciate
if I got
credit whenever you use the information provided
here - and maybe a
copy of your software...
(You don't
Good luck with your development!
- David Eriksson ([email protected]), August
12, 1997
Ok, ich würde vorschlagen keine Fehlermeldung auszugeben, wenn SICE festgestellt werden kann. Die folgende Methode ist viel effektiver, wenn es darum geht Registrierungscodes zu schützen (aber nutzlos, wenn es um Date-Checks oder Nag-Screens geht). Man sollte eine Variable (int fake) deklarieren, der man den Wert 1 zuweist, wenn SICE nicht gefunden werden kann. Wird SICE jedoch gefunden, weist man ihr den Wert 2 zu. Dann fügt man irgendwo in der Routine, in der der korrekte Registrierungscode berechnet wird die Zeile
regcode = regcode * fake;
ein. Dann wird eine Registrierungsnummer berechnet, die nur gilt, wenn SICE geladen ist, und der Cracker wird sich doch sehr wundern, warum das Programm nicht registriert ist, wenn er das nächste Mal das Programm startet, ohne dass SICE geladen ist. Wenn er das Programm nach dem "erfolgreichen" Cracken wieder deinstalliert, ohne den Code erneut zu testen und diesen stattdessen sofort auf seine Internet Page lädt ensteht überhaupt kein Schaden für den Shareware Autor, da die Registrierungsnummer für den "normalen" Anwender keine Gültigkeit hat.
Mein "uncrackbares" CrackMe:
Hier ist das Prinzip eines CrackMes, das ich programmiert habe. Es ist
höllisch schwer zu cracken, für einen ehrlichen Anwender dennoch
leicht zu registrieren. Da das Programm zu umfangreich ist, erläutere
ich nur die Funktionsweise.
Glossar:
Breakpoint - Ein Breakpoint ist ein "Lesezeichen" im
Debugger, mit dem man
ein Programm debuggt. Wenn solch ein Lesezeichen erreicht ist, dann
öffnet sich der sonst im Hintergrund laufende Debugger selbstständig
und man kann Änderungen im Programm (im RAM) vornehmen. BP lassen
sich auf Speicheradressen, Windows API-Funktionen, Hardwareschnitt-
stellenaktivität (für Hardware-Dongles)... setzen.
CrackMe - Ein CrackMe ist ein Beispielprogramm,
das von Crackern geschrieben
ist, um andere Cracker zu beschäfigen und vor eine Aufgabe zu stellen,
die von Sharewareprogrammen nicht mehr gefordert werden, oder sich
in einem speziellen Gebiet weiterbilden wollen.
Debugger - Ein Debugger ist ein Programm,
mit dem man ein Programm in seinem
Ablauf beeinflussen kann. Man kann dort Assembleranweisungen ändern
oder den Ram nach Werten durchsuchen. Eigentlich kann man mit einem Debugger
alles im RAM tun, was man will, nur endet das manchmal mit einem Reset.
Disassembler - Ein Programm, das ausführbare Dateien in Assemblerinstruktionen
zer-
legt.
Hardcoden - Das Definieren eines Strings auf
folgende Weise String hallo="Hallo".
Gegenteil weichcoden: String hallo=char(72)+char(97)+char(108)+char(108)
+char(111) (Das muss man halt für die verschiedenen Sprachen anpassen)
KeyGenerator - Kleines Programm, mit dem auf Namen basierende Registrierungscodes
für
Sharewareprogramme erstellen kann. (Hab im Urlaub meinen ersten programmiert:
10 Stunden/25 Seiten kommentierter Assembler Code nur um am Ende festzustellen,
das mein genereller Ansatz für einen KeyGenerator falsch war (hätte
ich nur
vorher was darüber gelesen). Es hätten auch 1 Stunde und 15 Zeilen
kommentierter Code gereicht:(. Ich habs aber trotzdem geschafft :)
Greetings:
Thanx/Greetz and Gratitude to Fravia+, tKC, ED!SON, Sandman, DaVinci,
Eternal Bliss, +wAj, Shadow, Jordan - The Black Wizard, Razzia
The hole document was coded by LaZaRuS [hf]
last changed 13.03.1999
Anmerkungen/Korrekturen/(konstruktive) Kritik/Anfügungen
an [email protected]
Bitte mailt mir. Keine Antwort ist schlimmer, als eine
schlechte. (Ausser ihr wollt mich beleidigen, dann spart euch die Mail)
Wenn irgendein Cracker/Reverser das liest und glaubt
manche Dinge besser zu wissen, bitte ich auch um eine Mail.
Wenn irgendjemand glaubt ich sollte seine Programme (kein
VB oder DOS) mal testen und spezielle Tips geben, dann mailt mir aber vorsicht
ich werde mich natürlich bei dem entsprechenden Programmierer mit
Angabe der ersten Mailadresse rückversichern. Bitte mailt mir auch,
was ich cracken soll, da ich keine Lust habe nach Einschränkungen
zu suchen, die nach 37 Programmstarts im 60. Untermenü entstehen.
Bitte dieses Dokument so weit wie möglich verbreiten. Es ist ausdrücklich gestattet es überall zu veröffentlichen. (Bitte unverändert) Wenn ich es in 6 Monaten irgendwo auf einer WebPage sehe, dann glaube ich, das die Arbeit dieses Dokument zu schreiben sich ausgezahlt hat.