2009-08-18 67 views
4

我想知道如何獲得運行jvm的操作系統。它也必須是「安全的」,所以System.getProperty("os.name")並不是一個真正的選擇,因爲它可以通過-D指令輕鬆繞過。java中操作系統的名稱(不是「os.name」)

「安全」我的意思是不平凡的規避。它適用於桌面應用程序。用戶總是可以反混淆,反編譯,編輯和重新編譯代碼,但這比將-D傳遞給jvm困難得多。我們想要修補不平凡的,不是不可能的(因爲這是不可能的)。

+7

定義「安全」。你想保護自己的誰?如果某人啓動了你的應用程序並且控制了它正在運行的計算機,那麼你的運行可能會很困難。在AS/400的分區的Linux上運行的虛擬機中,在Windows上運行的JVM如何運行?該報告應該如何? – 2009-08-18 12:38:57

+0

安全意味着不受限制。它適用於桌面應用程序。用戶總是可以反混淆,反編譯,編輯和重新編譯代碼,但這比將-D傳遞給jvm困難得多。我們想要修補不平凡的,不是不可能的(因爲這是不可能的)。 – 2009-08-18 12:54:06

+0

我不知道你想解決什麼問題,但我可以向你保證,依靠os.name很可能是不正確的解決方案。你爲什麼不重新使用這個屬性來解決你想要解決的實際問題? – Kevin 2009-08-18 12:57:49

回答

15

首先,不可能保護代碼免受運行時環境的任意處理。但爲了至少很難欺騙你的支票,最好的選擇可能是某種基於文件系統OS fingerprinting

File.listRoots()是你的出發點;在類Unix系統上,它將返回一個包含/ etc,/ usr等特徵目錄的根目錄。在Windows上,它將返回多個結果,但AFAIK操作系統安裝驅動器不一定是C:並且特徵目錄跨不同Windows版本和區域設置 - 注意不要認爲每個人都運行英文版的Vista。

您可以投入大量的工作來識別不同版本的Windows和Linux以及BSD或MacOS--並且在編譯後的代碼一旦移除時,可能會花費很少的工作將其刪除。

-2

你爲什麼不結合以下,並用它來進行插值,方式規避可能是困難的。

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 OpertingSystemInfo' - 現在呢? – Bombe 2009-08-18 12:38:56

1

阿帕奇commons-vfs抽象一些處理,因此您可以只處理OsOsFamily。但是在內部,這仍然使用System.getProperty(..)來獲取值。我不知道任何其他方式讓JVM獲得這些值。

如果有人在改變傳遞給你有更大的問題要處理比他們改變奇數財產的JVM屬性的位置。

您能詳細說明您的安全含義嗎?從誰那裏安全?

8

系統屬性是我知道獲取操作系統信息的唯一方法。即使OperatingSystemMXBean從os.X系統屬性中獲取它的值。

如果有人能與你的應用程序是如何啓動鼓搗,你必須比如果os.name是正確的更大的問題。

不過,如果你擔心惡意代碼設置,而你的應用程序運行的屬性,你可以使用Java安全管理,以確保性能安全防護。

0

除了使用您提到的屬性之外,VM中沒有公共API。

我的希望是,由於Java的應該是安全的,該VM會忽略任何企圖通過命令行覆蓋這些值,但事實並非如此。

你可以嘗試它不允許寫這些值的安全管理器,但我的猜測是,那麼,該值將是乾脆爲空(因爲VM不能改變它,要麼)。

+0

我很確定VM所做的設置不會被任何SecurityManager阻止。 – 2009-08-18 12:51:56

2

你可以通過Runtime類(exec方法)外部CMD像「版本」來獲得操作系統的版本(如果在Windows中)或「UNAME -A」

0

運行你還可以通過檢查環境變量System.getenv(),但用戶可以自由修改這些以及啓動之前。這只是不太容易(至少在Windows上)將變量作爲命令行的一部分修改以啓動應用程序。

8

你爲什麼這麼擔心?如果一個最終用戶笨到可以混淆os。*屬性,爲什麼不讓應用程序爆炸呢?

話雖這麼說,這些工作可能不夠好,你的目的

//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

如果安全是您的首要目標,你可能會想嘗試一些JNI補充。首先,如果您嘗試在Linux或OS X中加載DLL,我敢打賭它會崩潰/不加載。 其次,您可以從該DLL調用操作系統的API,因此您不受限於Java環境提供的內容。

0

我同意jni/jna是一個更好的選擇。只需調用Native.loadLibrary(「myLib」)之類的東西,並在Windows上加載myLib.dll,在linux-myLib.so上。這是最安全的方式,只是不能搞砸它。將所有特定於OS的代碼放入庫中,並將編譯後的版本保存在jar中。

1

您可以使用exec來嘗試運行一些無害的程序,這些程序可能存在於一個操作系統或另一個操作系統上 - 例如windows和「/ bin/ls」的「c:\ windows \ system \ dir.exe」爲*尼克斯 - 並看看他們是否運行成功或炸彈。但是當然有人知道你在做這件事,並試圖破壞它,他們可以用這些名字創建可執行文件。

究竟是什麼,你試圖安全起來?如果有人故意停止啓動你的應用程序,然後因爲你試圖運行不存在的命令而爆炸,那麼適當的迴應就不會是:「如果你的腳受傷了,停止在腳下射擊。」如果你所做的只是運行OS命令,大概用戶可以訪問你的應用以外的人,所以我沒有看到操作系統如何撒謊會危及安全。

+0

安全問題是「複製保護」。在一個媒體(USB棒)上運行該應用程序應該是不平凡的,而不是傳遞它的應用程序。 – 2009-08-18 18:21:25

+1

我建議你重新回答你的問題,詢問你真正想知道的內容。 – 2009-08-18 18:45:00

+1

我只是好奇而已。這可能與回答您的問題無關,但如何瞭解操作系統的幫助?如果有人插入USB,將程序複製到他們的硬盤驅動器,並嘗試運行它們,它們仍處於相同的操作系統下。如果你在USB上編寫你期望的操作系統,併爲不同的操作系統銷售不同的版本,那麼我想你可以防止有人購買Windows版本並在Linux上運行,但這只是盜版候選人的一小部分。我懷疑大多數想要製作非法拷貝的人會爲了同一個操作系統而製作它們。 – Jay 2009-08-18 20:48:30

0

現代Linux系統有一個特殊的文件/proc/version,它提供了內核版本ID。因此,如果該文件存在匹配適合的模式(例如,以Linux這個詞開頭),那麼您已經增加了在Linux計算機上運行的可能性。相反,如果它不存在或不符合該模式,則可以確定您沒有在Linux上運行。