Pregunta

Me gustaría saber cómo controlar el tipo de sistema operativo en el que se ejecuta la jvm.También tiene que ser "seguro", por lo que System.getProperty("os.name") En realidad no es una opción porque se puede eludir trivialmente con la directiva -D.

Por "seguro" me refiero a algo no trivial de eludir.Es para una aplicación de escritorio.El usuario siempre puede desofuscar, descompilar, editar y recompilar el código, pero eso es mucho más difícil que pasar -D a la jvm.Queremos que los retoques no sean triviales, ni imposibles (ya que eso no se puede hacer).

¿Fue útil?

Solución

En primer lugar, es imposible proteger el código para que no sea manipulado arbitrariamente por su entorno de ejecución.Pero para que sea al menos difícil engañar a su cheque, la mejor opción es probablemente algún tipo de sistema de archivos basado huellas dactilares del sistema operativo.

Archivo.listRoots() es tu punto de partida;en un sistema tipo Unix devolverá una única raíz que contiene directorios característicos como /etc, /usr, etc.En Windows, devolverá varios resultados, pero AFAIK la unidad de instalación del sistema operativo no es necesariamente C:y los directorios característicos difieren según las versiones y configuraciones regionales de Windows; tenga cuidado de no asumir que todos ejecutan una versión en inglés de Vista.

Podría invertir mucho trabajo en reconocer diferentes versiones de Windows y Linux, así como BSD o MacOS, y probablemente tomaría mucho menos trabajo eliminar la verificación del código compilado una vez que esté disponible.

Otros consejos

Las propiedades del sistema son la única forma que conozco para obtener información del sistema operativo. Incluso el OperatingSystemMXBean toma sus valores de las propiedades del sistema os.X.

Si alguien puede jugar con cómo se pone en marcha su aplicación, tiene problemas más grandes que si os.name es correcta.

Sin embargo, si usted está preocupado acerca de la configuración de este inmueble, mientras se ejecuta la aplicación, puede utilizar el Administrador de seguridad de Java para asegurarse de que las propiedades son guardadas de manera segura el código malicioso.

¿Por qué te preocupa esto? Si un usuario final es tan tonto como para meterse con OS. * Propiedades por qué no dejar la aplicación explotar?

Una vez dicho esto, estos pueden funcionar lo suficientemente bien para sus propósitos

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

Puede ejecutar a través de la clase en tiempo de ejecución (método exec) un cmd externos como "ver" para obtener la versión del sistema operativo (si está en Windows) o "uname -a"

Commons-VFS abstrae algunos de los procesamientos por lo que sólo puede hacer frente a Os y OsFamily . Sin embargo internamente esto sigue utilizando System.getProperty (..) para obtener los valores. No sé de ninguna otra forma de la JVM para obtener estos valores.

Si alguien está en una posición para cambiar las propiedades pasaron a la JVM que tienes problemas más importantes que atender que ellos cambiando la propiedad extraño.

Se puede elaborar en lo que entendemos por seguro. Asegure de quién?

Se puede usar exec para tratar de ejecutar algunos programas inofensivos que se puede esperar de existir en un sistema operativo u otro - como "c: \ windows \ system \ dir.exe" para las ventanas y "/ bin / ls" para el * nix - y ver si se ejecutan satisfactoriamente o una bomba a cabo. Pero, por supuesto, es que alguien sepa que estás haciendo eso y está tratando de debilitarlo, podrían crear ejecutables con esos nombres.

¿Qué es exactamente lo que usted está tratando de ser seguro desde? Si alguien deliberadamente tornillos hasta el lanzamiento de su aplicación y entonces explota porque usted está intentando ejecutar comandos no existentes, no sería la respuesta apropiada, "Si te duelen los pies, dejar de disparar en el pie." Si todo lo que estamos haciendo es ejecutar comandos del sistema operativo, presumiblemente, el usuario puede acceder a los que están fuera de su aplicación, por lo que no veo cómo mentir sobre el sistema operativo compromete la seguridad.

No hay una API pública en la máquina virtual que no sea el uso de las propiedades que usted ha mencionado.

Mi esperanza era que, dado que Java se supone que es segura, que la máquina virtual ignoraría cualquier intento de sobrescribir estos valores desde la línea de comandos, pero ese no es el caso.

Usted puede tratar de un SecurityManager, que no permite escribir estos valores, pero mi conjetura es que entonces, el valor será simplemente vacío (ya que la máquina virtual no puede cambiarlo, tampoco).

También puede examinar las variables de entorno a través de System.getenv (), pero el usuario es libre de modificar estos también antes del arranque. Es que no es tan fácil (al menos en Windows) para modificar las variables como parte de la línea de comandos para iniciar la aplicación.

Si la seguridad es su objetivo principal, es posible que desee para tratar de añadir en algunos JNI. En primer lugar, si se intenta cargar un archivo DLL en Linux o en Mac OS X, apuesto a que se colgará / no carga. En segundo lugar, a partir de ese DLL puede llamar a la API del sistema operativo', por lo que no se limitan a lo que está ofreciendo el entorno Java.

Estoy de acuerdo que JNI / JNA es una mejor alternativa. Sólo tiene que llamar algo así como Native.loadLibrary ( "MYLIB"), y en las ventanas que se carga myLib.dll, en Linux - myLib.so. Es la forma más segura, uno simplemente no puede meterse con él. Poner todo el código específico del sistema operativo en las bibliotecas y mantener versiones compiladas en su frasco.

Los sistemas modernos de Linux tienen un /proc/version archivo especial, que da el identificador de versión del kernel. Así que si ese archivo está presente un coincide con un patrón adecuado (por ejemplo, a partir de la palabra Linux), que ha aumentado la probabilidad de que se está ejecutando en un equipo Linux. Por el contrario, si está ausente o no coincide con el patrón, puede estar seguro de que no está ejecutando en Linux.

¿Por qué no combinar el siguiente y lo utilizan para interpolar, de esa manera elusión puede ser difícil.

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));
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top