Laufzeitbegrenzung

Moin,
hat jemand von Euch eine clevere Idee, wie man ein Java-Programm auf einen Demo-/Testzeitraum auf z.B. 30 Tage begrenzen kann?
Damit meine ich jetzt keine einfache Datumsabfrage, sondern es soll schon etwas verschleiert werden. Timestamp verschlüsseln und in einer Variablen speichern, die nicht unbedingt Timestamp heißt und sich zwischen weiteren sinnlosen Variablen tarnt war meine erste Idee. Ich denke aber, dass das nicht so recht funktioniert, auch wenn ich die Abfrage per Obfuscator verschleiere. Oder doch?

Naja läuft es nur auf einem bestimmten OS?
Obfuscator wirst du auf jeden Fall machen müssen.
Dann würd ich diese Überprüfung ob die Zeit abgelaufen ist sehr oft ins Programm einbauen, so das es nahezu unmöglich ist alle Stellen zu finden und zu entfernen, nach Möglichkeit auch mehrere Klassen dafür nehmen (die ruhig das Gleiche tun können).
Du könntest zb versuchen ob du in eine Jar Datei eine pseudo Class Datei packen kannst mit Timestamp, bei dem solltest du aber den Installationszeitpunkt UND den letzten Start nehmen. Den letzten Start damit du Uhr zurückstellen erkennen kannst, beachten musst du aber die Sommer/Winterzeit damit das keine Probleme gibt.
Du könntest natürlich diese Datumsangaben auch in einer Einstellungsdatei speichern die du bestimmt hast und dort einfach als irgendein String tarnen.

Könnte man nicht das Installationsdatum teilen und verschlüsselt in einem längeren String verbergen und diesen dann mit einer beliebigen serialVersionUID serialisieren?
Serialisierte Dateien sind ziemlich schlecht lesbar. Bräuchte man sich nur noch etwas für die Deserialisierung einfallen zu lassen. Der Code wäre ja beim Decompilieren sichtbar, fehlt nur noch eine Lösung für die nicht nachvollziehbare Entschlüsselung.

Kann auch sein, dass ich nur dumm rumsinniere…

Ich hänge mich mal an diese alte Frage an, da ich momentan vor der gleichen Aufgabe stehe. Ich sehe das Problem nicht darin, das Installationsdatum zu verschlüsseln und geschickt zu verstecken (den Tip mit der Serialisierung finde ich sehr gut), das Problem ist nur, dass irgendwo im Code die Entscheidung getroffen werden muss, dass der Testzeitraum abgelaufen ist und dann die weitere Ausführung des Programms oder der Zugriff auf einzelne Programmfunktionen blockiert werden muss
if (tage > testzeitraum){ … . Wenn jemand die Laufzeitbegrenzung aufheben möchte, muss er ja im Prinzip nur diese eine Stelle im Code ausfindig machen und dann die Bedingung auf false setzen oder einfach entfernen. Dann ist es doch eigentlich egal, wie raffiniert das Installationsdatum versteckt wurde, oder? Obfuskation ist da ja schonmal ein Erschwernis, aber das Schlüsselwort if bleibt dabei lesbar, so dass mit etwas Mühe die relevante Stelle vielleicht gar nicht so schwer aufzuspüren ist. Letzendlich kann man durch simples trial-and-error ja alle if-Anweisungen probeweise auf false setzen und würde dann irgendwann auf die entscheidende Stelle treffen. Das erfordert nur Geduld und keine weitere Intelligenz. Oder hättet Ihr eine Idee, wie man dieses erschweren könnte?
Das würde mich sehr interessieren, da ich bisher keinen pfiffigen Einfall dazu habe …

[QUOTE=HerrKaiser]Ich hänge mich mal an diese alte Frage an, da ich momentan vor der gleichen Aufgabe stehe. Ich sehe das Problem nicht darin, das Installationsdatum zu verschlüsseln und geschickt zu verstecken (den Tip mit der Serialisierung finde ich sehr gut), das Problem ist nur, dass irgendwo im Code die Entscheidung getroffen werden muss, dass der Testzeitraum abgelaufen ist und dann die weitere Ausführung des Programms oder der Zugriff auf einzelne Programmfunktionen blockiert werden muss
if (tage > testzeitraum){ … . Wenn jemand die Laufzeitbegrenzung aufheben möchte, muss er ja im Prinzip nur diese eine Stelle im Code ausfindig machen und dann die Bedingung auf false setzen oder einfach entfernen. Dann ist es doch eigentlich egal, wie raffiniert das Installationsdatum versteckt wurde, oder? Obfuskation ist da ja schonmal ein Erschwernis, aber das Schlüsselwort if bleibt dabei lesbar, so dass mit etwas Mühe die relevante Stelle vielleicht gar nicht so schwer aufzuspüren ist. Letzendlich kann man durch simples trial-and-error ja alle if-Anweisungen probeweise auf false setzen und würde dann irgendwann auf die entscheidende Stelle treffen. Das erfordert nur Geduld und keine weitere Intelligenz. Oder hättet Ihr eine Idee, wie man dieses erschweren könnte?
Das würde mich sehr interessieren, da ich bisher keinen pfiffigen Einfall dazu habe …[/QUOTE]

Also durch einen Kollegen neben mir kann ich dir eins sagen, egal was du baust, wenn einer mitm Decompiler ran geht ist nichts sicher. Du kannst es ihm schwer machen mit Obfuscation/nativem Code. Aber wenn er Lust/Langeweile (oder Hass auf dich ;)) hat schafft er es.
Auch wenn er wie mein Kollege sich fast 1 Jahr dran setzt um das zu knacken

Mal abgesehen davon, dass ein Programm wahrscheinlich sehr viele if’s hat: Verwende einfach zwei if’s / switch’s die das prüfen (s. @EagleEye ): Alle Kombinationen dann auszuprobieren dürfte den Nutze wahrscheinlich übersteigen.
LG

nee nicht probieren, Code Stück für Stück zerlegen :wink:
Mein Kollege hat sich von nem anderen die Firmware von einem Gerät auslesen lassen und hat sie komplett zerlegt um die Verschlüsselung zu knacken, am Ende konnte er das alles in Java/PHP nachbauen

server verbindung ist wohl das einzig sinnvolle dann

Wenn man schon ein 6 Jahre altes Thema ausgräbt, dann kann man auch mal einen Blick in die Zukunft werfen.

Gehe ich mal davon aus, dass sich Microsoft mit Windows 8 und Trusted Computing durchsetzt, dann kann man dies nutzen.

Das sollte dann ausreichend gewappnet sein, dass niemand mehr etwas an deinem Binary rumpfuschen kann.

TPM, TCG als Stichworte

Das hat dann den Vorteil, dass eine einfache Datumsabfrage reicht.

Es besteht auch die große Chance, dass damit Regeln, Programm kann nur 30 Tage lang verwendet werden, definiert werden können.

Ist aber noch ein wenig Zukunftsmusik dabei.

Das sind schonmal gute Hinweise, die meinen Ehrgeiz bremsen, eine (unmögliche) sichere Lösung zu finden. Aber eine Variante, an der der Hobbyprogrammierer scheitert, würde vermutlich schon reichen. @SpaceFiller : mit deinem Hinweis auf Switch hast du meine Überlegungen jetzt in die Richtung gelenkt, dass man ja nicht nur mit if verzwiegen kann. Switch ist vielleicht nicht ganz so naheliegend - andererseits auch nicht so häufig im Code und daher auch schneller abgecheckt. Vielleicht bringt man die Verzweigung auch in einen Try-Catch-Block unter, wäre das nicht vielleicht originell? Oder wüsstet Ihr noch andere Methoden einer Verzweigung, ohne dass man if oder switch verwenden müsste (d. h., wie man eine if-Anweisung praktisch nachbauen könnte)?

TC als Heilmittel zu verwenden halte ich für eine falsche Haltung. Ich sehe es eher als Gefahr an.

Am Besten sollte man ein Datum vom Server holen.

Naja ist ja nicht so als könnte man auch diese Dinge faken :wink:

Ich denke du solltest abwägen was für einen Aufwand du betreiben willst für welchen Nutzen.

MD5 Checksummen sind schwieriger faken. Denn dafür müsste man die Standardbibliothek faken.

Also ich würde einfach einen Timestamp aus dem Internet holen und vergleichen (http://commons.apache.org/proper/commons-net/examples/ntp/NTPClient.java)

Weil: da hast du am wenigsten Aufwand - und für 99% aller Kunden reicht das völlig aus.

Wenn jemand dein Programm disassembliert, dann wird er jede Sperre die du dir ausdenkst ohnehin umgehen.

Nochmals gute Hinweise, vielen Dank. An die Möglichkeit der Verwendung der Checksumme als Kriterium hatte ich noch nicht gedacht. Das ist noch einmal eine gute Anregung!
Ich habe aber vielleicht noch nicht verständlich genug dargestellt, dass meine Fragestellung weniger darauf abzielt, welches Prüfkriterium man verwendet, wie man es auswertet und wie man es versteckt. Mir geht es mehr um den “virtuellen Schalter” im Code, an dem je nach Prüfbedingungen Programmfunktionen freigegeben oder gesperrt werden. Meiner Ansicht nach ist die Sperre an dieser Stelle am leichtesten zu knacken, ganz egal, wie raffiniert das Prüfkriterium gewählt und versteckt wurde. Der Hinweis auf die mehrfache Verwendung von ifs an unterschiedlichen Stellen im Code ist gut, das erhöht sicherlich den Aufwand beträchtlich. Noch raffinierter wäre es, ganz ohne ifs und switches auszukommen. Da grübele ich derzeit noch ein wenig, ob man das hinbekommen könnte (denn wie gesagt, die Schlüsselwörter werden ja nicht obfuskiert, so dass anhand dieser die entscheidenden Stellen im Code vermutlich leicht aufzuspüren sind).

Mit etwas Aufwand kannst du den “virtuellen Schalter” auch verstecken. Einfach den Krempel in eine Klasse packen und diese Kompilieren. Die Methodennamen am besten “per Hand obfuskieren”, so dass man nicht erkennt was machen. Die .class File dann mit einem möglichst unscheinbaren Code/String “verschlüsseln” und als unscheinbare Datei speichern und mitliefern. Zur Laufzeit dann die Datei entschlüsseln, mit einem URLClassLoader laden und den darin enthaltenen Code einfach aufrufen.
Ist wohl relativ viel Aufwand. Aber zuerst wird der Bösewicht wohl versuchen die “IF”-Bedingung zu finden. Und die findet er dann erstmal nicht.

Persönlich würde ich auch die Servergestütze Prüfung bevorzugen. Gibt verschiedene Techniken einen Client mehr oder weniger eindeutig zu identifizieren. Und wenn du über den Server nicht nur das OK-/Nicht-OK zurück lieferst, sondern eine .class-File mit essentiell wichtigem Inhalt (diese aber nur im Speicher hlaten und nicht auf die Platte schreiben), dann ist das schon einigermaßen sicher.

Und dann hat man gleich die Zusatzkosten für einen Server und den Traffic den die Clients verursachen, ganz abgesehen von dem Ärger den man hat wenn der Server mal abraucht und die Clients ihre Software nicht mehr verwenden können. EA hat das mit dem Onlinezwang ja schön vorgemacht.

Gruß

Man darf hier nicht vergessen dass es eine 30 Tage Testversion sein soll… Die Einschränkung ließe sich ja aufheben wenn man das Programm käuflich erwirbt.

Der Anwendungskontext bringt es mit sich, dass die meisten Rechner nicht mit dem Internet verbunden sein werden, so dass sich die Serverlösungen nicht anbieten, aber das ist vermutlich mein Weg:

[QUOTE=tuxedo]Einfach den Krempel in eine Klasse packen und diese Kompilieren. Die Methodennamen am besten „per Hand obfuskieren“, so dass man nicht erkennt was machen. Die .class File dann mit einem möglichst unscheinbaren Code/String „verschlüsseln“ und als unscheinbare Datei speichern und mitliefern. Zur Laufzeit dann die Datei entschlüsseln, mit einem URLClassLoader laden und den darin enthaltenen Code einfach aufrufen.
Ist wohl relativ viel Aufwand. Aber zuerst wird der Bösewicht wohl versuchen die „IF“-Bedingung zu finden. Und die findet er dann erstmal nicht.
[/QUOTE]

Dann werde ich im Code noch ein paar Nebelkerzen werfen, damit der Bösewicht nicht gleich auf die Idee kommt, statt nach Ifs nach dem Classloader und dem Verschlüsselungsalgorithmus zu suchen, das dürfte dann wirklich reichen. Hab mit Classloadern bisher noch keine Erfahrung, werde mich da mal etwas weiterbilden …

1000 Dank für die Anregungen!
(Die Byte-Welt hat den Test auf würdigen JFO-Ersatz aus dem Stand heraus bestanden!! :slight_smile: )