Secure Honey

SSH honeypot written in C

Creating An Antidote For Android Simplelocker Ransomware

Tuesday 17th June 2014 10:09

In yesterday's blog post (How To Dissect Android Simplelocker Ransomware) we dissected the new Android Simplelocker ransomware.

In this blog post we'll be creating an antidote for the ransomware to decrypt any files it encrypts.

The process of creating the antidote is actually very simple because the ransomware comes with a built-in decrypt method and cipher password. This means we're able to create our own Java class and copy the decryption code from the ransomware into our antidote class.

So let's jump right in and start creating our antidote for Simplelocker!

NB: if you haven't already read the previous post (How To Dissect Android Simplelocker Ransomware) it might be worth having a quick read through that now, since I'll be referencing Java classes that were analysed in that post.

First, we want to examine the AesCrypt class, which is shown in full below:

package org.simplelocker;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.MessageDigest;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesCrypt
{
  private final Cipher cipher;
  private final SecretKeySpec key;
  private AlgorithmParameterSpec spec;

  public AesCrypt(String paramString)
    throws Exception
  {
    MessageDigest localMessageDigest = MessageDigest.getInstance("SHA-256");
    localMessageDigest.update(paramString.getBytes("UTF-8"));
    byte[] arrayOfByte = new byte[32];
    System.arraycopy(localMessageDigest.digest(), 0, arrayOfByte, 0, arrayOfByte.length);
    this.cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
    this.key = new SecretKeySpec(arrayOfByte, "AES");
    this.spec = getIV();
  }

  public void decrypt(String paramString1, String paramString2)
    throws Exception
  {
    FileInputStream localFileInputStream = new FileInputStream(paramString1);
    FileOutputStream localFileOutputStream = new FileOutputStream(paramString2);
    this.cipher.init(2, this.key, this.spec);
    CipherInputStream localCipherInputStream = new CipherInputStream(localFileInputStream, this.cipher);
    byte[] arrayOfByte = new byte[8];
    while (true)
    {
      int i = localCipherInputStream.read(arrayOfByte);
      if (i == -1)
      {
        localFileOutputStream.flush();
        localFileOutputStream.close();
        localCipherInputStream.close();
        return;
      }
      localFileOutputStream.write(arrayOfByte, 0, i);
    }
  }

  public void encrypt(String paramString1, String paramString2)
    throws Exception
  {
    FileInputStream localFileInputStream = new FileInputStream(paramString1);
    FileOutputStream localFileOutputStream = new FileOutputStream(paramString2);
    this.cipher.init(1, this.key, this.spec);
    CipherOutputStream localCipherOutputStream = new CipherOutputStream(localFileOutputStream, this.cipher);
    byte[] arrayOfByte = new byte[8];
    while (true)
    {
      int i = localFileInputStream.read(arrayOfByte);
      if (i == -1)
      {
        localCipherOutputStream.flush();
        localCipherOutputStream.close();
        localFileInputStream.close();
        return;
      }
      localCipherOutputStream.write(arrayOfByte, 0, i);
    }
  }

  public AlgorithmParameterSpec getIV()
  {
    return new IvParameterSpec(new byte[16]);
  }
}

We can see that the decrypt() method is clearly provided within this class. We also already know the decryption password (as set in the Constants class), so all we need to is call this method on any files ending in .enc.

Let's create a new Java class called SimplelockerAntidote with a method called getEncryptedFiles() which will scan the current directory for all files ending with .enc:

public static String[] getEncryptedFiles() {

		File dir = new File(System.getProperty("user.dir"));

		Collection<String> files  =new ArrayList<String>();

		if(dir.isDirectory()){
			File[] listFiles = dir.listFiles();

			for(File file : listFiles){
				String filename = file.getName();
				if(
					file.isFile() 
					&& (filename.lastIndexOf(".") >= 0)
					&& (filename.substring(filename.lastIndexOf(".")).toLowerCase().equals(".enc"))
				) {
					files.add(file.getName());
				}
			}
		}
		
		return files.toArray(new String[]{});
	}

This method returns an array of String files names (of all files ending in .enc in the current directory) which we can then feed into the decrypt() method. Line 3 sets the current directory (where the Java program is running). Line 10 iterates over all files in the directory. Finally, line 15 checks if the current file ends in .enc where line 17 adds it to the return array if it matches.

Next, create a main method which calls getEncryptedFiles() and sets the decryption password:

	public static void main(String[] args) throws Exception{

		// set default cipher password
		String cipher_password = "jndlasf074hr";

		// overwrite cipher password if set by first argument
		if(args.length == 1)
		{
			cipher_password = args[0];
		}

		// create new SimplelockerAntidote object
		SimplelockerAntidote sa = new SimplelockerAntidote(cipher_password);

		// get array of filenames to decrypt from current directory
		String[] files = sa.getEncryptedFiles();

		// iterate through files in the array
		for (int i = 0; i < files.length; i++) {

			// set input and output filenames
			// and remove the .enc file extension
			String inputFilename = files[i];			
			String outputFilename = inputFilename.substring(0,inputFilename.length()-4);

			System.out.println("Decrypting "+outputFilename);

			// call decrypt on the current file
			sa.decrypt(inputFilename,outputFilename);
		}

		System.out.println("Decryption complete.");

	}

Now all we need to do is copy-and-paste the constructor method from AesCrypt along with AlgorithmParameterSpec getIV(), encrypt() and decrypt().

This completes the antidote. The full Java class file is shown below:

// Simplelocker antidote, written by Simon Bell, SecureHoney.net

import javax.crypto.*;
import javax.crypto.interfaces.*;
import javax.crypto.spec.*;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.security.interfaces.*;
import java.security.spec.*;
import javax.xml.bind.DatatypeConverter;
import java.util.ArrayList;
import java.util.Collection;

public class SimplelockerAntidote {

	private final Cipher cipher;
	private final SecretKeySpec key;
	private AlgorithmParameterSpec spec;

	public SimplelockerAntidote(String password) throws Exception {

		MessageDigest digest = MessageDigest.getInstance("SHA-256");
		digest.update(password.getBytes("UTF-8"));
		byte[] keyBytes = new byte[32];
		System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

		cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		key = new SecretKeySpec(keyBytes, "AES");
		spec = getIV();
	}

	public AlgorithmParameterSpec getIV() {
		return new IvParameterSpec(new byte[16]);
	}

	public void encrypt(String paramString1, String paramString2) throws Exception {
		FileInputStream localFileInputStream = new FileInputStream(paramString1);
		FileOutputStream localFileOutputStream = new FileOutputStream(paramString2);
		this.cipher.init(1, this.key, this.spec);
		CipherOutputStream localCipherOutputStream = new CipherOutputStream(localFileOutputStream, this.cipher);
		byte[] arrayOfByte = new byte[8];
		while (true) {
			int i = localFileInputStream.read(arrayOfByte);
			if (i == -1) {
				localCipherOutputStream.flush();
				localCipherOutputStream.close();
				localFileInputStream.close();
				return;
			}
			localCipherOutputStream.write(arrayOfByte, 0, i);
		}
	}

	public void decrypt(String paramString1, String paramString2) throws Exception {
		FileInputStream localFileInputStream = new FileInputStream(paramString1);
		FileOutputStream localFileOutputStream = new FileOutputStream(paramString2);
		this.cipher.init(2, this.key, this.spec);
		CipherInputStream localCipherInputStream = new CipherInputStream(localFileInputStream, this.cipher);
		byte[] arrayOfByte = new byte[8];
		while (true) {
			int i = localCipherInputStream.read(arrayOfByte);
			if (i == -1) {
				localFileOutputStream.flush();
				localFileOutputStream.close();
				localCipherInputStream.close();
				return;
			}
			localFileOutputStream.write(arrayOfByte, 0, i);
		}
	} 

	public static String[] getEncryptedFiles() {

		File dir = new File(System.getProperty("user.dir"));

		Collection<String> files  =new ArrayList<String>();

		if(dir.isDirectory()){
			File[] listFiles = dir.listFiles();

			for(File file : listFiles){
				String filename = file.getName();
				if(
					file.isFile() 
					&& (filename.lastIndexOf(".") >= 0)
					&& (filename.substring(filename.lastIndexOf(".")).toLowerCase().equals(".enc"))
				) {
					files.add(file.getName());
				}
			}
		}
		
		return files.toArray(new String[]{});
	}

	public static void main(String[] args) throws Exception{

		// set default cipher password
		String cipher_password = "jndlasf074hr";

		// overwrite cipher password if set by first argument
		if(args.length == 1)
		{
			cipher_password = args[0];
		}

		// create new SimplelockerAntidote object
		SimplelockerAntidote sa = new SimplelockerAntidote(cipher_password);

		// get array of filenames to decrypt from current directory
		String[] files = sa.getEncryptedFiles();

		// iterate through files in the array
		for (int i = 0; i < files.length; i++) {

			// set input and output filenames
			// and remove the .enc file extension
			String inputFilename = files[i];			
			String outputFilename = inputFilename.substring(0,inputFilename.length()-4);

			System.out.println("Decrypting "+outputFilename);

			// call decrypt on the current file
			sa.decrypt(inputFilename,outputFilename);
		}

		System.out.println("Decryption complete.");

	}
}

Once compiled, this Java program will scan the current directory for all files ending in .enc and attempt to decrypt them using the pre-set password.

It's also possible to override the default cipher password by calling the program as follows:

java SimplelockerAntidote <cipher-password>

The complete Java program can be downloaded here: SimplelockerAntidote.java.

It would be fairly straightforward from here to convert this Java program into an Android app. This app could then search for all .enc files on the SD card and attempt to decrypt them - thus providing a direct Android antidote app.

The antidote for this ransomware was incredibly easy to create because the ransomware came with both the decryption method and the decryption password. Therefore producing an antidote was more of a copy-and-paste job than anything.

It's also worth noting that while this antidote doesn't detect the decryption password automatically, it could be possible to do so. However, future versions of the ransomware will probably not reveal the decryption password so easily and will likely receive it from the C&C server.

Since the Simplelocker ransomware is a proof-of-concept, the antidote provided here is simply a solution to this proof-of-concept. Future versions of advanced smartphone ransomware will likely prove significantly harder to reverse engineer.

Image credit: "Chemistry" by Paul, flickr.com/photos/howzey/4955405374.

Comments

Roshin

Tue, 17 Jun 2014 12:45:00 +0100

you're awesome!

GK

Tue, 17 Jun 2014 12:49:35 +0100

Small type: \"with both the decryption method and the decryption password.\", should be encryption method I assume. Awesome write-up, thanks alot! :)

Hello

Tue, 17 Jun 2014 18:20:52 +0100

I guess it should be Android Simplocker Ransomware.

Cii3er

Wed, 18 Jun 2014 21:45:13 +0100

Very good Job. (Y)

Alex

Fri, 20 Jun 2014 13:37:53 +0100

Ctrl+C, Ctrl+V from source decompiled code.

TomTerrific

Tue, 07 Apr 2015 14:32:34 +0100

As an IT professional, we're constantly looking for solutions that would protect customer from CryptoWall etc. Since this was published in June 2014 and the ransomware world never sleeps, what has evolved since then in viable solutions and protection. Thanks

Simon

Sat, 11 Apr 2015 17:57:51 +0100

Hi Tom

As far as I'm aware, in terms of Android ransomware, the only real threat was Koler (See Android ransomware demanding $300 from porn site visitors and Android ransomware 'Koler' turns into a worm, spreads via SMS). Also known as FBI Ransomware, the Trojan was disguised as a BaDoink streaming app and would lock the users screen and demand a ransom of $300 to unlock the device.

Thanks
Simon

Add Comment

Name

Email (won't be displayed)

Website (optional)

Comments

Live Stats (see full stats)

Attempted logins

date range # attempts
today0
yesterday0
past 7 days18,521
past 30 days77,915
all time3,816,386

Top 5 passwords

password # attempts
12345613,178
-6,277
admin6,214
password4,980
6666663,687

Top 5 usernames

username # attempts
root3,679,111
admin71,556
oracle2,873
bin2,223
test2,146

Stats represent data collected from SSH login attempts on multiple honeypots. Parts of some stats may be filtered to maintain anonymity.

Updated: Fri, 29 May 2015 06:02:21 +0100

Live Password Cloud

admin123 asdfgh zaqxsw abc123 welcome123 asdf P@$$w0rd sysadmin manager zxcvbnm zaqxswcdevfr 123654 idc123 1314520 linux admin woaini qqpp windows guest master a123456 qazwsxedc _ POIUYT P@ssw0rd zhang cisco test123 qwe 225588 123456a qazwsx adminpp 1111 123qweasd asdfghjkl 666666 147258369 1q2w3e4r 123456789 1qaz2wsx3edc admin1 11111111 a1b2c3d4 Pass123 q1w2e3r4 456789 123qwe 102030 Aa123456 qwer1234 789789 asdfg 11223344 !2#4%6 aaa123 monitor 1q2w3e4r5t6y zxcvbn qwer 1234567890 system zaqxswcde qwert 000000 a1b2c3d4e5 sqlpp 159357 0000 qazwsx123 f**kyou 123123 !@#$%^ 54321 123 12345 P@ssw0rd1 qweasd pass toor a1s2d3f4 zxcv q1w2e3r4t5 1qazxsw2 redhat idcidc nagios user zaq12wsx p0o9i8u7 admin@123 sql 1122334455 qwerty 123321 sapp p@ssword server root123 Passw0rd huawei 1qaz2wsx 123123123 qwe123 support dragon 888888 root 1234%^ 23456 123abc password 1 12344321 5201314 super superman qwaszx 77777777 cisco123 huawei123 111111 88888888 secret - qaz !QAZ2wsx zaq1xsw2 admin123!@# changeme 1q2w3e 12qwaszx passwd 12345678 china iloveyou sa890pp oracle qazxsw q1w2e3 lanyue raspberry 159753 qwerty123456 rootpass power q123456 !QAZ@WSX caonima 12345qwert 1234 7890pp 1qaz@WSX default 654321 963852741 111 changeme123 z1x2c3v4 987654321 147258 qwertyuiop 1a2s3d4f 1q2w3e4r5t 112233 Admin123456 idc2008 abcd1234 qwerty123 password123 welcome 147852369 password1 test mnbvcxz abc1234 1234qwer 123456 Huawei@123 letmein public administrator