2009-08-18 3 views
4

Ich würde gerne wissen, wie man an die Art des Betriebssystems, auf dem der jvm läuft, gelangt. Es muss auch "sicher" sein, also ist System.getProperty("os.name") nicht wirklich eine Option, weil es mit der -D-Direktive trivial umgangen werden kann.Name des Betriebssystems in Java (nicht "os.name")

Mit "sicher" meine ich nontrivial zu umgehen. Es ist für eine Desktop-Anwendung. Der Benutzer konnte den Code immer entschlüsseln, dekompilieren, bearbeiten und neu kompilieren, aber das ist wesentlich schwieriger als die Übergabe von -D an den jvm. Wir wollen das Basteln nicht-trivial machen, nicht unmöglich (da das nicht möglich ist).

+7

Definieren Sie "sicher". Vor wem willst du dich schützen? Wenn jemand Ihre Anwendung startet und die Kontrolle über den Computer hat, auf dem er läuft, haben Sie wahrscheinlich kein Glück. Was ist mit einer JVM, die unter Windows in einer virtuellen Maschine läuft, die unter Linux in einer Partition eines AS/400 läuft? Was sollte das melden? –

+0

Sicher bedeutet, nicht zu umgehen. Es ist für eine Desktop-Anwendung. Der Benutzer konnte den Code immer entschlüsseln, dekompilieren, bearbeiten und neu kompilieren, aber das ist wesentlich schwieriger als die Übergabe von -D an den jvm. Wir wollen das Basteln nicht-trivial machen, nicht unmöglich (da das nicht möglich ist). –

+0

Ich weiß nicht, welches Problem Sie lösen möchten, aber ich kann Ihnen versichern, dass die Verwendung von os.name höchstwahrscheinlich die falsche Lösung ist. Warum schreiben Sie nicht das eigentliche Problem, das Sie mit dieser Eigenschaft lösen wollen? – Kevin

Antwort

15

Erstens ist es unmöglich, Code vor willkürlicher Manipulation durch seine Laufzeitumgebung zu schützen. Aber um es zumindest schwer zu machen, Ihren Scheck zu täuschen, ist die beste Wette wahrscheinlich eine Art Dateisystem basierend auf OS fingerprinting.

File.listRoots() ist Ihr Ausgangspunkt; Auf einem Unix-ähnlichen System gibt es eine einzelne Wurzel zurück, die charakteristische Verzeichnisse wie/etc,/usr usw. enthält. Unter Windows gibt es mehrere Ergebnisse zurück, aber AFAIK das Betriebssysteminstallationslaufwerk ist nicht unbedingt C: und die charakteristischen Verzeichnisse unterscheiden sich übergreifend Windows-Versionen und Ländereinstellungen - seien Sie vorsichtig, dass Sie nicht davon ausgehen, dass jeder eine englische Version von Vista ausführt.

Sie könnten eine Menge Arbeit in die Erkennung verschiedener Versionen von Windows und Linux sowie BSD oder MacOS investieren - und es würde wahrscheinlich viel weniger Arbeit kosten, den Check aus dem kompilierten Code zu entfernen, sobald er da draußen ist.

-2

Warum kombinieren Sie das Folgende nicht und verwenden es zum Interpolieren, so kann das Umgehen schwierig sein.

public class OpertingSystemInfo 
{ 
    public static void main(String[] args) 
    { 
     String nameOS = "os.name";   
     String versionOS = "os.version";   
     String architectureOS = "os.arch"; 
    System.out.println("\n The information about OS"); 
     System.out.println("\nName of the OS: " + 
System.getProperty(nameOS)); 
     System.out.println("Version of the OS: " + 
System.getProperty(versionOS)); 
     System.out.println("Architecture of THe OS: " + 
System.getProperty(architectureOS)); 
    } 
} 
+6

'java -Dos.name = foo -Dos.version = foo -Dos.arch = foo OperatingSystemInfo' - und jetzt? – Bombe

1

Apache commons-vfs abstrahiert einen Teil der Verarbeitung, so dass Sie nur mit Os und OsFamily umgehen können. Intern wird jedoch weiterhin System.getProperty (..) verwendet, um die Werte zu erhalten. Ich kenne keine andere Möglichkeit für die JVM, diese Werte zu erhalten.

Wenn jemand in der Lage ist, die an die JVM übergebenen Eigenschaften zu ändern, haben Sie größere Probleme zu bewältigen, als sie die ungerade Eigenschaft ändern.

Können Sie näher erläutern, was Sie mit Sicherheit meinen. Sicher von wem?

8

Die Systemeigenschaften sind die einzige Möglichkeit, Informationen zum Betriebssystem zu erhalten. Sogar der OperatingSystemMXBean übernimmt seine Werte aus den os.X-Systemeigenschaften.

Wenn jemand basteln kann, wie Ihre Anwendung gestartet wird, haben Sie größere Probleme als wenn os.name korrekt ist.

Wenn Sie jedoch besorgt sind, dass bösartiger Code während der Ausführung der Anwendung diese Eigenschaft festlegt, können Sie mithilfe von Java Security Manager sicherstellen, dass die Eigenschaften sicher verwaltet werden.

0

Es gibt keine öffentliche API in der VM außer den genannten Eigenschaften.

Meine Hoffnung war, dass, da Java sicher sein soll, die VM alle Versuche ignorieren würde, diese Werte von der Befehlszeile zu überschreiben, aber das ist nicht der Fall.

Sie könnten einen SecurityManager versuchen, der es nicht erlaubt, diese Werte zu schreiben, aber ich nehme an, dass der Wert dann einfach leer ist (da die VM ihn auch nicht ändern kann).

+0

Ich bin mir ziemlich sicher, dass die Einstellungen der VM von keinem SecurityManager verhindert werden. –

0

Sie können auch Umwelt untersuchen Variablen durch die Runtime-Klasse (exec-Methode) ein externes cmd wie „ver“ erhält die Version von OS (wenn in Windows) oder „uname -a“ durchlaufen System.getenv(), aber der Benutzer kann diese auch vor dem Start ändern. Es ist einfach nicht so einfach (zumindest unter Windows), die Variablen als Teil der Befehlszeile zu ändern, um Ihre Anwendung zu starten.

8

Warum machen Sie sich Sorgen darüber? Wenn ein Endbenutzer dumm genug ist, sich mit den Betriebssystemen zu messen. * Warum lässt sich die App nicht explodieren?

Davon abgesehen, arbeiten diese können gut genug für Ihre Zwecke

//can be defeated by adding com.apple.eawt.Application to the classpath 
public boolean isMac() { 
    try { 
     Class.forName("com.apple.eawt.Application"); 
     return true; 
    } catch(Exception e) { 
     return false; 
    } 
} 

//can be defeated by creating a cmd.exe in PATH 
public boolean isWin() { 
    try{ 
     Runtime.getRuntime().exec(new String[]{"cmd.exe","/C","dir"}).waitFor(); 
     return true; 
    } catch (Exception e) { 
     return false; 
    } 
} 

public boolean isLinux() { 
    if(isMac()) return false; 
    try{ 
     Runtime.getRuntime().exec( new String[]{"sh","-c","ls"}).waitFor(); 
     return true; 
    } catch (Exception e) { 
     return false; 
    } 
} 
0

Wenn Sicherheit Ihr primäres Ziel ist es, Sie können versuchen, in irgendeiner JNI hinzuzufügen. Erstens, wenn Sie versuchen, eine DLL in Linux oder OS X zu laden, ich wette, es wird abstürzen/nicht laden. Zweitens, von dieser DLL können Sie die OS-API aufrufen, so dass Sie nicht darauf beschränkt sind, was die Java-Umgebung bietet.

0

Ich stimme zu, dass jni/jna eine bessere Alternative ist. Rufen Sie einfach etwas wie Native.loadLibrary ("myLib") auf, und unter Windows wird myLib.dll auf linux - myLib.so geladen. Es ist der sicherste Weg, man kann sich einfach nicht damit anlegen. Setzen Sie den gesamten osspezifischen Code in Bibliotheken und behalten Sie kompilierte Versionen in Ihrem Jar bei.

1

Sie könnten exec verwenden, um einige harmlose Programme zu starten, die Sie auf dem einen oder anderen Betriebssystem erwarten können - wie "c: \ windows \ system \ dir.exe" für Windows und "/ bin/ls" für * nix - und sehen, ob sie erfolgreich laufen oder bombardieren. Aber natürlich weiß jemand, dass Sie das tun und versucht, es zu untergraben, sie könnten ausführbare Dateien mit diesen Namen erstellen.

Worum genau möchten Sie sich schützen? Wenn jemand absichtlich den Start Ihrer App vermasselt und dann explodiert, weil Sie versuchen, nicht vorhandene Befehle auszuführen, wäre die entsprechende Antwort nicht: "Wenn Ihre Füße schmerzen, hören Sie auf, sich in den Fuß zu schießen." Wenn Sie nur OS-Befehle ausführen, kann der Benutzer vermutlich auf Benutzer außerhalb der App zugreifen. Daher kann ich nicht erkennen, wie die Sicherheit des Betriebssystems beeinträchtigt wird.

+0

Das Sicherheitsproblem ist "Kopierschutz". Es sollte nicht sinnvoll sein, die Anwendung auf einem Medium (USB-Stick) auszuführen, außer dem, auf dem sie ausgeliefert wird. –

+1

Ich schlage vor, dass Sie Ihre Frage umschreiben, um nach dem zu fragen, was Sie wirklich wissen möchten. –

+1

Ich bin jetzt nur neugierig. Dies ist wahrscheinlich nicht relevant für die Beantwortung Ihrer Frage, aber wie hilft das Wissen über das Betriebssystem? Wenn jemand den USB einsteckt, das Programm auf seine Festplatte kopiert und versucht, es auszuführen, befinden sie sich immer noch unter demselben Betriebssystem. Wenn Sie auf dem USB-Code kodieren, welches Betriebssystem Sie erwarten und verschiedene Versionen für verschiedene Betriebssysteme verkaufen, dann könnten Sie vermutlich verhindern, dass jemand die Windows-Version kauft und unter Linux läuft, aber das wäre eine winzige Untergruppe von Pirateriekandidaten. Ich vermute, dass die meisten Leute, die illegale Kopien machen wollen, sie für das gleiche Betriebssystem herstellen würden. – Jay

0

Moderne Linux-Systeme haben eine spezielle Datei /proc/version, die die Kernel-Version ID gibt. Wenn diese Datei vorhanden ist und mit einem passenden Muster übereinstimmt (zum Beispiel beginnend mit dem Wort Linux), haben Sie die Wahrscheinlichkeit erhöht, dass Sie auf einem Linux-Computer ausgeführt werden. Wenn es abwesend ist oder nicht mit diesem Muster übereinstimmt, können Sie sicher sein, dass Sie nicht unter Linux laufen.