14

Along the lines of "This tape will self-destruct in five seconds. Good luck, Jim"...

Would it be possible for an application to delete itself (or it's executable wrapper form) once a preset time of use or other condition has been reached?

Alternatively, what other approaches could be used to make the application useless?

The aim here is to have a beta expire, inviting users to get a more up-to-date version.

James P.
  • 19,313
  • 27
  • 97
  • 155
  • 2
    sure it's possible. Assuming that you have deployed your app in a jar, you can get the classpath via system properties, find the jar, and delete it (assuming Java is running with enough privileges) and the OS permits you to delete a jar while its in use. – ControlAltDel Apr 11 '12 at 14:34
  • 1
    Another way to do this is to store the initial date of usage in the file system or in the system registry. – ControlAltDel Apr 11 '12 at 14:35
  • 1
    There are several questions on stackoverflow about how to make a demo/trial/evaluation version. – mbatchkarov Apr 11 '12 at 14:37
  • 2
    _Alternatively, what other approaches could be used to make the application useless?_ You said it is a beta, when there is the first release the beta is useless for serious users anyway ... – PeterMmm Apr 11 '12 at 14:39
  • 4
    Please consider that making your app simply stop working isn't brilliant in terms of usability. Most users will be a bit confused. Your app should launch anyway and just show something along the lines of "Dude, get the latest release already, kthxbai.". – pcalcao Apr 11 '12 at 14:44
  • 1
    I just tried doing this in Windows 7, with no luck :P Created a jar, jar gets the file... but can't deleted while running. (Not even with windows) – Reg Apr 11 '12 at 14:46
  • 1
    *""This tape will self-destruct in five seconds. Good luck, Jim"..."* This security will be broken in three seconds. Good luck catching us... – Andrew Thompson Apr 11 '12 at 15:10
  • @pcalcao I will consider the approach. – James P. Apr 11 '12 at 15:31
  • @AndrewThompson This is more a question of convenience than security. As you hint and from my experience in anticheating, I am only too well aware of how limited any form of protection is when it comes to software :) . – James P. Apr 11 '12 at 15:34

4 Answers4

8

It is possible. To get around the lock on the JAR file, your application may need to spawn a background process that waits until the JVM has exited before deleting stuff.

However, this isn't bomb-proof. Someone could install the application and then make the installed files and directories read-only so that your application can't delete itself. The user (or their administrator) via the OS'es access control system has the final say on what files are created and deleted.

Dennis Meng
  • 5,109
  • 14
  • 33
  • 36
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • You're right. This would also defeat any overwriting or modifications as suggested by @PeterMmm. How about requiring access to the internet? It would separate some of the control logic. – James P. Apr 11 '12 at 15:54
  • That can be defeated by disabling the relevant code in the application. Obfuscation will not prevent that ... only make it take longer. – Stephen C Apr 11 '12 at 22:45
  • 4
    Putting a timebomb of any kind into your application is a disservice to your potential future customers. Persuade them to upgrade by offering them a good product rather than by crippling your existing one. – Stephen C Apr 11 '12 at 22:49
  • Or have the application upgrade automatically :) ? – James P. Apr 23 '12 at 13:24
  • 1
    @JamesPoulson - self upgrading applications can be good, or bad depending on the nature of the application and the users. For instance, if my database server decided to self upgrade and (accidentally) damaged my data in the process, I would be VERY, VERY annoyed. I personally would not consider implementing automatic self-upgrades for anything. It is simply too risky ... too likely to hurt or annoy customers or potential customers. – Stephen C Sep 20 '12 at 03:31
5

If you control where testers download your application, you could use an automated build system (e.g. Jenkins) that you could create a new beta versions every night that has a hard-coded expiry date:

private static final Date EXPIRY_DATE = <90 days in the future from build date>;

the above date is automatically inserted by the build process

if (EXPIRY_DATE.before(new Date()) {
    System.out.println("Get a new beta version, please");
    System.exit(1);
}

Mix that with signed and sealed jars, to put obstacles in the way of decompiling the bytecode and providing an alternative implementation that doesn't include that code, you can hand out a time-expiring beta of the code.

The automated build system could be configured to automatically upload the beta version to the server hosting the download version.

beny23
  • 34,390
  • 5
  • 82
  • 85
  • 1
    Thanks for the mention of Jenkins. Do you know if this be worked around by changing the system date? – James P. Apr 11 '12 at 15:49
  • 1
    It could be yes, but no security measure is absolutely crack-proof. For example if you were to check the time against a web service, that could be circumvented by intercepting the service call, etc. and I think determined crackers will get around anything. Still, I don't think a normal user would want to change the system time as it would probably interfere with other tools (e.g calendars). – beny23 Apr 11 '12 at 22:09
  • 1
    No need to be a cracker here, just change system time. – atamanroman Jun 10 '14 at 15:53
  • Actually changing system time can raise hell all over your system. 667 of 666 would not recommend. – Tomáš Zato Jan 04 '16 at 14:45
1

Since Windows locks the JAR file while it is running, you cannot delete it from your own Java code hence you need a Batch file:

private static void selfDestructWindowsJARFile() throws Exception
{
    String resourceName = "self-destruct.bat";
    File scriptFile = File.createTempFile(FilenameUtils.getBaseName(resourceName), "." + FilenameUtils.getExtension(resourceName));

    try (FileWriter fileWriter = new FileWriter(scriptFile);
         PrintWriter printWriter = new PrintWriter(fileWriter))
    {
        printWriter.println("taskkill /F /IM \"java.exe\"");
        printWriter.println("DEL /F \"" + ProgramDirectoryUtilities.getCurrentJARFilePath() + "\"");
        printWriter.println("start /b \"\" cmd /c del \"%~f0\"&exit /b");
    }

    Desktop.getDesktop().open(scriptFile);
}

public static void selfDestructJARFile() throws Exception
{
    if (SystemUtils.IS_OS_WINDOWS)
    {
        selfDestructWindowsJARFile();
    } else
    {
        // Unix does not lock the JAR file so we can just delete it
        File directoryFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath();
        Files.delete(directoryFilePath.toPath());
    }

    System.exit(0);
}

ProgramDirectoryUtilities class:

public class ProgramDirectoryUtilities
{
    private static String getJarName()
    {
        return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
                .getCodeSource()
                .getLocation()
                .getPath())
                .getName();
    }

    public static boolean isRunningFromJAR()
    {
        String jarName = getJarName();
        return jarName.contains(".jar");
    }

    public static String getProgramDirectory()
    {
        if (isRunningFromJAR())
        {
            return getCurrentJARDirectory();
        } else
        {
            return getCurrentProjectDirectory();
        }
    }

    private static String getCurrentProjectDirectory()
    {
        return new File("").getAbsolutePath();
    }

    public static String getCurrentJARDirectory()
    {
        try
        {
            return getCurrentJARFilePath().getParent();
        } catch (URISyntaxException exception)
        {
            exception.printStackTrace();
        }

        throw new IllegalStateException("Unexpected null JAR path");
    }

    public static File getCurrentJARFilePath() throws URISyntaxException
    {
        return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
    }
}

Solution inspired by this question.


Here is a better method for Windows:

private static void selfDestructWindowsJARFile() throws Exception
{
    String currentJARFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath().toString();
    Runtime runtime = Runtime.getRuntime();
    runtime.exec("cmd /c ping localhost -n 2 > nul && del \"" + currentJARFilePath + "\"");
}

Here is the original answer.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
-1

it is pretty possible i guess. maybe you can delete the jar like this and make sure the application vanishes given that you have the rights.

File jar = new File(".\\app.jar");
jar.deleteOnExit();
System.exit(0);

also using something like Nullsoft Scriptable Install System which enables you to write your own installed/uninstaller should help.

atamanroman
  • 11,607
  • 7
  • 57
  • 81
Anurag Ramdasan
  • 4,189
  • 4
  • 31
  • 53