今日表示しない

トップへ戻る

トップへ戻る

脅威インテリジェンス

脅威インテリジェンス

脅威インテリジェンス

QRKimsuky

QRKimsuky

QRKimsuky

エンキホワイトハット

エンキホワイトハット

コンテンツ

コンテンツ

コンテンツ

概要

  • DOCSWAP悪質なアプリの最新の流布経路と新しいバージョンのAPKファイルを多数確保して分析した。

  • 悪質なアプリは内部で暗号化されたAPKファイルを復号し、C&Cサーバーと通信してRAT機能を実行する悪質なサービスを登録する。

  • 攻撃者は新しいネイティブ復号関数を追加し、囮(デコイ)の動作も多様化した。

  • C&Cサーバーの共有、ハングルのアノテーションなど、Kimsukyによる攻撃と推定される手がかりが多数発見された。

1. 概要

去る2025年9月、ENKI Whitehat脅威研究チームはフィッシングサイトを通じて流布されている悪性モバイルアプリを発見した。攻撃者はQRコードと通知ウィンドウを利用して、被害者がモバイル環境に悪性アプリをインストールおよび実行するように誘導した。

分析の結果、確保した悪性アプリは2025年3月にS2Wで「DOCSWAP」と命名された悪性アプリの最新バージョンであり、既存の悪性アプリと動作は同様だが、内部のAPK復号化プロセスが異なる。また、分析の過程で、北朝鮮が背後にいる攻撃グループであるKimsukyとの関連性も多数確認された。

さらに、APKファイルのメタデータとインフラの類似性に基づき、追加の悪性アプリ3個と攻撃者のC&Cサーバー7台を確保した。この過程で、攻撃者は悪性アプリごとに様々なテーマのおとり用動作を追加し、被害者が疑念を抱かないように設計していた。

2. 攻撃分析

공격 개요도

caption - 攻撃概要図

2.1. 不正アプリの配布経路

不正アプリの配布は、27.102.137[.]181 において配送業者を騙ったQRコードによって行われたことを確認した。調査中に発見された4つの不正アプリのうち2つが配送業者を騙っていたが、過去のESTSecurityのレポート事例では、配送業者を騙ったスミッシング(SMSフィッシング)によって被害者に不正アプリ配布URLが送信されていた。このため、過去の事例と同様に、初期のアクセス段階においてスミッシングまたはフィッシングメールが利用されたと推測される。確認されたURLは以下の通りである。

  • hxxps://27.102.137[.]181/store/tracking.php?id=[Base64エンコードされたメールアドレス]

  • hxxps://27.102.137[.]181/store/delivery.html

모바일 접속 유도 QR코드

caption - モバイルアクセス誘導QRコード

PC環境からURLにアクセスすると、「セキュリティ上の理由により、PCからは確認できません。」という文章を表示し、QRコードを介してスマートフォンでアクセスするように誘導する。分析当時、QRコードにリンクされたパスがサーバー上に存在しなかったため、正常にはアクセスできなかった。QRコードのURLは以下の通りである。

  • hxxps://delivery.cjlogistics[.]kro[.]kr/loing/tracking.php?id=dGVzdEBuYXZlci5jb20=

User-AgentをAndroid環境の値に設定してURLにアクセスすると、攻撃者が設計した配布プロセスが明らかになる。tracking.php ファイル自体に、リクエストのUser-Agentに応じて異なるサイトをロードする機能が含まれていると思われる。配布プロセスで確認された画面は以下の通りである。

가짜 보안 검사 화면

caption - 偽のセキュリティ検査画面

보안 앱 설치 버튼

caption - セキュリティアプリインストールボタン

「セキュリティアプリをインストールする(보안앱 설치하기)」ボタンをクリックすると、Base64でエンコードされたURLにアクセスし、APKをダウンロードする。デコードされたURLは以下の通りである。

  • hxxps://27.102.137[.]181/store/SecDelivery.APK

보안 앱 설치 루틴

caption - セキュリティアプリインストールルーチン

APKのダウンロードと同時に、downcat.phpにアクセス時刻とアプリのURLパスを含むPOSTリクエストを送信してログを記録する。同ルーチンにおいて、「ボタンクリック時にログを記録(버튼 클릭시 로그 남기기)」という韓国語のコメントと、「ログ送信失敗(로그 전송 실패)」という韓国語のエラーメッセージが確認された。

로그 전송 루틴

caption - ログ送信ルーチン

2.2. 不正アプリ分析

2.2.1. SecDelivery.apk

보안배송확인 악성 앱 아이콘

caption - セキュリティ配送確認の不正アプリのアイコン

SecDelivery.apkは、内部に暗号化されたAPKファイルを復号・ロードした後、不正なRATサービスを生成するAPKファイルである。APK署名の有効開始日時は2025年5月20日であり、攻撃者が不正アプリを制作し、テストまたは攻撃に使用した時期もこれに近いと推測される。APK署名情報は以下の表の通りである。

| **DN** | C=US, ST=bitapp, L=bitapp, O=bitapp, OU=bitapp, CN=bitapp |
| --- | --- |
| MD5 | 7d00a43872dcdd1174d3713e6bbf01ba |
| 有効開始時間 | Tue May 20 18:41:34 KST 2025

| **DN** | C=US, ST=bitapp, L=bitapp, O=bitapp, OU=bitapp, CN=bitapp |
| --- | --- |
| MD5 | 7d00a43872dcdd1174d3713e6bbf01ba |
| 有効開始時間 | Tue May 20 18:41:34 KST 2025

| **DN** | C=US, ST=bitapp, L=bitapp, O=bitapp, OU=bitapp, CN=bitapp |
| --- | --- |
| MD5 | 7d00a43872dcdd1174d3713e6bbf01ba |
| 有効開始時間 | Tue May 20 18:41:34 KST 2025

caption - APK署名情報

2.2.2. リソースの復号 & サービスの生成

AndroidManifest.xmlファイルにおいて、SplashActivityがMAIN activityとして設定されている。アプリ起動時にSplashActivityによってAPK内部に暗号化されたリソースがロードされ、不正行為に必要な各種権限を取得したのち、不正サービスを登録する。

AndoridManifest.xml MAIN activity

caption - AndroidManifest.xml MAIN activity

暗号化されたAPKファイルは、リソース領域のsecurity.datファイルとして保存されている。以前の「DOCSWAP」の事例では、内部APKの復号の際にJavaコード上でXORを実行していたが、今回の事例では攻撃者が追加したネイティブライブラリを利用している。

loadPluginAPKメソッドは、暗号化されたAPKファイルであるsecurity.datファイルを、内部ストレージにsecurity.dat_copyファイルとして保存した後、native-libライブラリのdecryptFile関数を利用して復号する。

내부 APK 로드 루틴

caption - 内部APKロードルーチン

decryptFile関数は、リソース領域のlibnative-lib.soファイルを抽出して直接確認できる。decryptFile関数内で、xorDecrypt関数が直接的な復号を担当する。4バイトのkeyを利用したXOR復号のみを実行していた以前の事例とは異なり、若干のビット演算が追加されている。

xorDecrypt関数のアルゴリズムは以下の通りである。

  1. バイトデータのビット反転

  2. 5ビットのROL(左循環シフト)適用

  3. 4バイトのkeyでXOR

내부 APK 복호화 루틴

caption - 内部APK復号ルーチン

XORに使用される4バイトのキーは以下の通りである。

  • 541161FE (hex)

データのロード後は、必要な権限が確保されているか確認する。必要な権限がすべて取得された状態であれば、直ちに新しくロードしたAPKファイルのMainServiceを「com.delivery.security.MainService」サービスとして登録する。AndroidManifest.xmlに登録されているアプリの権限は以下の通りである。

    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
    <uses-permission android:name="android.permission.SET_WALLPAPER"/>
    <uses-permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"

    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
    <uses-permission android:name="android.permission.SET_WALLPAPER"/>
    <uses-permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"

    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
    <uses-permission android:name="android.permission.SET_WALLPAPER"/>
    <uses-permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"

サービス登録と同時に、既存のアプリはAuthActivityを実行する。AuthActivityはOTP認証画面を装っており、配送番号を用いた本人確認が行われる。配送番号はAPK内部に「742938128549」としてハードコードされており、初期アクセスの際に不正アプリ配布URLとともに渡されていたものと推測される。配送番号を入力すると、((int) (Math.random() * 900000.0d)) + 100000で計算された6桁の認証番号の通知が表示される。

가짜 인증 화면

caption - 偽の認証画面

発行された認証番号を入力すると、MainActivityを実行する。MainActivityでは、WebViewの設定が行われ、公式の配送情報照会サイトへの接続が実行される。

공식 사이트 리다이렉션 루틴

caption - 公式サイトへのリダイレクトルーチン

2.2.3. 内部APK & 不正サービス

復号されたAPKファイルには、SecDelivery.apkとは異なる署名が使用されていた。APK署名の有効開始日時が2025年4月22日と記録されており、SecDelivery.apkの開発前から攻撃に使用されていた不正APKであることがわかる。APK署名情報は以下の表の通りである。

| **DN** | C=US, O=Android, CN=Android Debug |
| --- | --- |
| MD5 | afb708faf1a66892a6e6cae9e63c6c2b |
| 有効開始時間 | Tue Apr 22 15:57:54 KST 2025

| **DN** | C=US, O=Android, CN=Android Debug |
| --- | --- |
| MD5 | afb708faf1a66892a6e6cae9e63c6c2b |
| 有効開始時間 | Tue Apr 22 15:57:54 KST 2025

| **DN** | C=US, O=Android, CN=Android Debug |
| --- | --- |
| MD5 | afb708faf1a66892a6e6cae9e63c6c2b |
| 有効開始時間 | Tue Apr 22 15:57:54 KST 2025

caption - APK署名情報

復号されたsecurity.datに含まれるMainServiceは、あらかじめSplashActivityによってサービス登録されており、繰り返し動作する。また、以下のインテントフィルタが設定されており、再起動後も自動的にMainServiceを実行する。

  • android.intent.action.BOOT_COMPLETED

  • android.intent.action.ACTION_POWER_CONNECTED

  • android.intent.action.ACTION_POWER_DISCONNECTED

MainServiceはC&Cサーバーに接続し、インフォスティーラー(情報窃取ツール)およびRATとして機能する。RATが実行するコマンドは合計57個あり、各コマンドに応じた動作は付録の「コマンド一覧」として添付する。

初期のC&Cサーバーは、配布サーバーと同じIPである 27.102.137[.]181:50005 に設定されており、サーバーと通信する際は「長さ | Null | Gzip圧縮されたペイロード」の形式でデータを送受信する。

데이터 전송 루틴

caption - データ送信ルーチン

データ受信時には、「長さ | Null | コマンド」という構造でコマンドを分離し、これをパースして適切な動作を実行する。コマンドのパース時には、区切り文字として「10249」という文字列を使用する。

  • “10256” | “10249” | “arg1” | “10249” | “arg2” → StartAudioRecord(arg1 , arg2 )

명령어 파싱 루틴

caption - コマンド解析ルーチン

このほか、アクセシビリティサービスを通じたキーロギング(キー入力履歴の記録)のロジックも実行される。キーロガーは、アクセシビリティイベント発生時に、イベントが発生したアプリのアイコン、パッケージ名、イベントテキスト、発生時刻を記録する。アプリのアイコンファイルはPNGファイルに圧縮され、Base64でエンコードされてキーログに含まれる。

앱 아이콘 저장 루틴

caption - アプリアイコンの保存ルーチン

デフォルト設定では、作成したキーログを内部ストレージのfileパス配下にある「/Security/download_[日-月-年].dat」に保存する。コマンドによってisOnelineKeylogger変数にTrueが設定された場合、記録されたキーログを先にサーバーへ送信してからローカルに保存する。

실시간 키로깅 및 키로그 저장 루틴

caption - リアルタイムキーロギングおよびキーログ保存ルーチン

3. 追加情報

3.1. 追加の悪意のあるAPKファイル

分析の過程において、同様の挙動を実行するAPKファイルがさら3個発見された。このうち2個は、分析されたファイルと同じ27.102.137[.]181をC&Cサーバーとして使用し、残りの1個は、分析されたファイルと同じAPK署名を使用していた。追加で確保した3個のAPKファイルはどれも、内部に暗号化されたapkファイルを復号して悪質なサービス登録に利用し、それぞれ異なるタイプのアプリに偽装されていた。追加の悪意のあるAPKファイルの詳細は、以下の表の通りである。

| 悪意のあるアプリのタイプ | XORキー (Hex) | C&Cサーバー |
| --- | --- | --- |
| オークション配送情報認証 | 541161FE | 27.102.137[.]181 |
| VPN | 201925EA | 27.102.137[.]181 |
| P2B Airdrop認証 | 541161FE | 27.102.137[.]180

| 悪意のあるアプリのタイプ | XORキー (Hex) | C&Cサーバー |
| --- | --- | --- |
| オークション配送情報認証 | 541161FE | 27.102.137[.]181 |
| VPN | 201925EA | 27.102.137[.]181 |
| P2B Airdrop認証 | 541161FE | 27.102.137[.]180

| 悪意のあるアプリのタイプ | XORキー (Hex) | C&Cサーバー |
| --- | --- | --- |
| オークション配送情報認証 | 541161FE | 27.102.137[.]181 |
| VPN | 201925EA | 27.102.137[.]181 |
| P2B Airdrop認証 | 541161FE | 27.102.137[.]180

caption - 悪意のあるAPKファイルの詳細情報

APK署名および内部APKファイルのハッシュ情報は、以下の表の通りである。

| 悪意のあるアプリのタイプ | 署名 MD5 | 内部APKファイル MD5 |
| --- | --- | --- |
| オークション配送情報認証 | 45a2140271ab7dfd73cbcf312c910926 | 858588b7c5331c948fb3e84d9b4ddbb7 |
| VPN | 45a2140271ab7dfd73cbcf312c910926 | 03a117c6cb86859623720e75f839260a |
| P2B Airdrop認証 | 7d00a43872dcdd1174d3713e6bbf01ba | 2a7dab4c0f6507bc5fd826f9a336d50c

| 悪意のあるアプリのタイプ | 署名 MD5 | 内部APKファイル MD5 |
| --- | --- | --- |
| オークション配送情報認証 | 45a2140271ab7dfd73cbcf312c910926 | 858588b7c5331c948fb3e84d9b4ddbb7 |
| VPN | 45a2140271ab7dfd73cbcf312c910926 | 03a117c6cb86859623720e75f839260a |
| P2B Airdrop認証 | 7d00a43872dcdd1174d3713e6bbf01ba | 2a7dab4c0f6507bc5fd826f9a336d50c

| 悪意のあるアプリのタイプ | 署名 MD5 | 内部APKファイル MD5 |
| --- | --- | --- |
| オークション配送情報認証 | 45a2140271ab7dfd73cbcf312c910926 | 858588b7c5331c948fb3e84d9b4ddbb7 |
| VPN | 45a2140271ab7dfd73cbcf312c910926 | 03a117c6cb86859623720e75f839260a |
| P2B Airdrop認証 | 7d00a43872dcdd1174d3713e6bbf01ba | 2a7dab4c0f6507bc5fd826f9a336d50c

caption - 悪意のあるAPK署名および内部APKファイルのハッシュ情報

追加の悪意のあるAPKファイルのうち、27.102.137[.]181をC&Cサーバーとして使用した2つのファイルは同じAPK署名を使用しており、その詳細は以下の表の通りである。

| **DN** | C=KR, ST=log, L=log, O=log, OU=log, CN=log |
| --- | --- |
| MD5 | 45a2140271ab7dfd73cbcf312c910926 |
| 有効開始時間 | Thu Aug 14 00:38:45 KST 2025

| **DN** | C=KR, ST=log, L=log, O=log, OU=log, CN=log |
| --- | --- |
| MD5 | 45a2140271ab7dfd73cbcf312c910926 |
| 有効開始時間 | Thu Aug 14 00:38:45 KST 2025

| **DN** | C=KR, ST=log, L=log, O=log, OU=log, CN=log |
| --- | --- |
| MD5 | 45a2140271ab7dfd73cbcf312c910926 |
| 有効開始時間 | Thu Aug 14 00:38:45 KST 2025

caption - APK署名の詳細情報

オークション偽装アプリは、ユーザーが実行した際に公式サイにリダイレクトさせ、P2B Airdrop偽装アプリは、分析された悪意のあるアプリと類似した認証ロジックが存在する。この時に入力するウォレットアドレスの「0x」を除いた文字列の長さが42の場合に検証を通過し、認証番号の生成ロジックは ((int) (Math.random() * 900000.0d)) + 100000 で、分析された悪意のあるアプリと同様である。認証画面のUIもまた、分析された悪意のあるアプリと非常によく似ている。

추가 APK 가짜 인증 화면

caption - 追加APKの偽の認証画面

VPN偽装アプリのパッケージ名は「com.bycomsolutions.bycomvpn」であり、ファイル構成やメタデータ、コードルーチンなどが同じパッケージ名の公式アプリと非常に類似している。これは、攻撃者が公式APKに悪意のある行為を追加してリパッケージし、悪質な行為として利用しようとしたことを示している。

악성 앱의 UIActivity onCreate  메소드

caption - 悪意のあるアプリのUIActivity onCreateメソッド

공식 앱의 UIActivity onCreate 메소드

caption - 公式アプリのUIActivity onCreateメソッド

3.2. 追加のC&Cサーバー

マルウェアの配布およびC&Cサーバーとして使用された27.102.137[.]181と同じJARM値を持ち、httpポートが稼働しているダウ技術(Daou Technology)所属のIPを調査した結果、攻撃者が使用した追加のインフラを確認することができた。ここには、Airdrop認証偽装アプリのC&Cサーバーとして使用された27.102.137[.]180が含まれている。JARMと検索されたC&Cサーバーは以下の表の通りである。

| JARM | IP |
| --- | --- |
| 2ad2ad16d2ad2ad00042d42d00000061256d32ed7779c14686ad100544dc8d  | 27.102.137[.]93-n27.102.137[.]106-n27.102.137[.]214-n27.102.138[.]163-n27.102.137[.]179-n27.102.137[.]180-n27.102.138[.]181
| JARM | IP |
| --- | --- |
| 2ad2ad16d2ad2ad00042d42d00000061256d32ed7779c14686ad100544dc8d  | 27.102.137[.]93-n27.102.137[.]106-n27.102.137[.]214-n27.102.138[.]163-n27.102.137[.]179-n27.102.137[.]180-n27.102.138[.]181
| JARM | IP |
| --- | --- |
| 2ad2ad16d2ad2ad00042d42d00000061256d32ed7779c14686ad100544dc8d  | 27.102.137[.]93-n27.102.137[.]106-n27.102.137[.]214-n27.102.138[.]163-n27.102.137[.]179-n27.102.137[.]180-n27.102.138[.]181

caption - JARMハッシュが同一のIP

確認されたC&Cサーバーのうち、27.102.137[.]106でオークション偽装アプリを配布するフィッシングサイトが発見された。CJの事例と同じく、被害者がコンピュータでリンクにアクセスすると、モバイルでのみアクセス可能であるという通知を表示して、モバイルでのアクセスを誘導する。本稿の事例のように、QRコードを利用してモバイルアクセスを誘導することはしなかった。URLは以下の通りである。

  • hxxp://27.102.137[.]106/tracking.php?id=[メールアドレス base64エンコード]

  • hxxp://27.102.137[.]106/mobile.html

모바일 접속 유도 알림

caption - モバイルアクセスの誘導の通知

本稿の事例と同じく、User-Agentを使ってアクセスを迂回した際、APKのインストール案内メッセージが表示される。Androidは基本的に、公式アプリストア以外からダウンロードされた「提供元不明のアプリ」のインストールをブロックし、セキュリティ警告を表示する。攻撃者はこれを認識した上で、正式に配布された安全なアプリであるとして被害者をだまし、警告を無視してインストールするように誘導する。

악성 APK 설치 시 안내 문구

caption - 悪意のあるAPKのインストール時の案内メッセージ

警告ウィンドウの確認ボタンをクリックすると、分析されたCJの悪意のあるアプリと同じく、同じサーバーのdowncat.phpにログを送信する。その後、同じC&Cサーバーからauction_8.7.01.APKをダウンロードするが、当該コードの処理において「APKダウンロード開始」という韓国語のコメント(注釈)が確認された。

로그 전송 및 악성 앱 다운로드 루틴

caption - ログ送信および悪意のあるアプリダウンロードのルーチン

3.2.1 NAVERフィッシングサイト

27.102.137[.]180を除くすべての追加C&Cサーバーで、プロキシサーバー形式のNAVERフィッシングサイトが確認された。wreplyパラメータに被害者のメールアドレス、mパラメータにプロシURLが渡される。この時、プロキシを介して表示するサイトURLをURLエンコードした後にROT13処理を行ってから送信する必要があり、これによってプロキシサイトが正常に読み込まれる。例となるURLと、表示されるログイン画面は以下の通りである。

  • hxxp://27.102.137[.]181/users2/?wreply=qwer@naver.com&m=uggcf%3N%2S%2Savq.anire.pbz%2Savqybtva.ybtva

네이버 로그인 피싱 화면

caption - NAVERログインのフィッシング画面

ログイン情報を入力した際、入力されたメールアドレスで新規ディレクトリを作成し、そのディレクトリに被害者情報が保存される。

저장된 피해자 정보

caption - 保存された被害者情報

3.2.2. Kakaoフィッシングサイト

27.102.137[.]180と27.102.138[.]181においては、/login のパスでKakaoフィッシングサイトが確認された。

카카오 로그인 피싱 화면

caption - Kakaoログインのフィッシング画面

NAVERフィッシング同様、プロキシ形式でサイトをロードするが、パスワード入力時に入力された値を傍受し、pass.phpにPOST送信して流出させるルーチンが確認された。

비밀번호 유출 루틴

caption - パスワード流出のルーチン


4. APTグループとの関連性

4.1. Million OK !!!! フィッシングキャンペーンと攻撃インフラの共有

先述の、悪性アプリが配布された 27.102.137[.]181、27.102.137[.]106 と Kimsuky の Naver フィッシングサイトインフラとの間の接続点が確認された。参考にした外部資料のリンクは以下の通りである。

確認されたフィッシングサイトは、Kimsuky の以前の Naver フィッシング事例と同じ形式の引数を使用しているが、プロキシサイトの URL を ROT13 暗号化するロジックが追加された。過去の同キャンペーンのフィッシングサイト URL と現在のフィッシングサイト URL は以下の表の通りである。

| 過去の Naver フィッシング URL | 現在の Naver フィッシング URL |
| --- | --- |
| http://158.247.202[.]109/invoice/?wreply=&m=https%3a%2f%2fnid.naver[.]com%2fnidlogin[.]login | http://27.102.137[.]181/users2/?wreply=qwer@naver.com&m=uggcf%3N%2S%2Savq.anire.pbz%2Savqybtva.ybtva |
| 過去の Naver フィッシング URL | 現在の Naver フィッシング URL |
| --- | --- |
| http://158.247.202[.]109/invoice/?wreply=&m=https%3a%2f%2fnid.naver[.]com%2fnidlogin[.]login | http://27.102.137[.]181/users2/?wreply=qwer@naver.com&m=uggcf%3N%2S%2Savq.anire.pbz%2Savqybtva.ybtva |
| 過去の Naver フィッシング URL | 現在の Naver フィッシング URL |
| --- | --- |
| http://158.247.202[.]109/invoice/?wreply=&m=https%3a%2f%2fnid.naver[.]com%2fnidlogin[.]login | http://27.102.137[.]181/users2/?wreply=qwer@naver.com&m=uggcf%3N%2S%2Savq.anire.pbz%2Savqybtva.ybtva |

caption - 過去、現在の Naver フィッシング URL の比較

フィッシングサイトの UI は、過去の Naver フィッシング事例と同じである。

동일한 로그인 피싱 화면

caption - 同一のログインフィッシング画面

C&C サーバーのルートディレクトリにアクセスした際、Kimsuky フィッシングインフラの特徴である「Million OK !!!!」という文言も確認された。

루트 디렉토리 “Million OK !!!!” 문자열

caption - ルートディレクトリの「Million OK !!!!」文字列

4.2. html コード内の韓国語コメント

発見された APK 配布ウェブサイトの html コードから、韓国語のコメントとエラー構文を確認できる。該当のコメント群はログ生成および APK ダウンロードルーチンに含まれており、攻撃者が作成した可能性が極めて高い。これは、韓国語を使用できる攻撃者が作成したコードであることを示している。

CJ 악성 앱 유포 사이트의 한글 주석

caption - CJ 悪性アプリ配布サイトの韓国語コメント

옥션 악성 앱 유포 사이트의 한글 주석

caption - Auction 悪性アプリ配布サイトの韓国語コメント

5. 対応策

5.1. リンク先アドレスの再確認など注意が必要

本文の事例ではマルウェアの配布方法は確認できませんでしたが、攻撃者はショートメッセージまたは電子メールを通じて被害者に悪性アプリのダウンロードリンクを送信したものと推定されます。モバイルでURLにアクセスすると、すぐに悪性モバイルアプリのダウンロードが行われますが、モバイル以外のデバイスでURLにアクセスした場合はQRコードを表示し、モバイルでURLにアクセスするよう誘導します。

QR코드 인식 시 나타나는 악성 링크

caption - QRコード認識時に表示される悪質なリンク

リンクをクリックするだけで悪性アプリが実行されるわけではありませんが、攻撃者は巧妙に作り込まれたフィッシングサイトなどを通じて、被害者が悪性アプリを実行したり、個人情報を入力したりするように設計しています。したがって、被害を予防するためには、見知らぬ人から送られてきたリンクはなるべくクリックせず、知人から送られてきたリンクであっても普段と異なる内容であったり不審な点がある場合は、クリックする前にまず連絡して確認するプロセスを経る必要があります。

5.2. アプリ使用時の最小権限の原則の適用

Androidアプリがシステム機能にアクセスするためには、ユーザーが該当するランタイム権限を許可する必要があります。一般的に、悪性アプリは起動と同時にファイルアクセス、電話、メッセージなど、さまざまな権限を要求します。

악성 앱 요청 권한

caption - 悪性アプリが要求する権限

本文の事例の場合、ファイルアクセスおよび電話の権限は「安全配送通知」というアプリの目的から大きく外れています。また、正常なアプリは一般的に、ユーザーが特定の権限を拒否しても、その権限を必要とする機能を実行する際、権限を再要求するように設計されているため、一時的な権限の拒否がアプリの機能に問題を引き起こすことはありません。したがって、ユーザーはアプリ利用時に最小権限の原則を適用し、それらの権限がアプリの機能に必須であるかどうかを保守的に判断する習慣を身につける必要があります。


6. おわりに

本稿では、過去に「DOCSWAP」と命名された悪意のあるアプリキャンペーンの新しいAPKファイルと、その配布経路を分析した。最初の配布プロセスは確認されていないが、攻撃者は悪意のあるAPKの配布リンクをスミッシング(SMSフィッシング)で配布したと推定され、QRコードを利用して被害者がスマートフォンに悪意のあるアプリをダウンロードして実行するように誘導した。

実行された悪意のあるアプリは、過去の事例と類似したRAT(Remote Access Trojan)サービスを実行するが、内部のAPKファイルの復号に新しいネイティブ関数を使用し、多様な囮(デコイ)動作を追加するなど、進化した形態を示した。

さらに、「DOCSWAP」の悪意のあるアプリとKimsukyとの関連性も明確になった。C&Cサーバーで確認された「Million OK!!!」という文字列だけでなく、最近のKimsukyフィッシング攻撃と類似した形式のプロキシサーバー、被害者情報の保存形態までが、提示された関連性の確実な根拠となっている。さらに、悪意のあるアプリの配布サイトで確認されたハングルのコメントやエラーメッセージは、攻撃者が北朝鮮を背景に持つ攻撃グループと関連していることを示している。

今日、スマートフォンは財産やプライバシーなどの機密性の高い個人情報を満載した、移動する金庫となった。個人の生活に最も密着しているモバイルおよびウェアラブル環境を侵害し、貴重な個人情報を奪取しようとする攻撃も持続的に行われている。すでにスマートフォンが最も身近な友人であり最高の秘書となった現代社会の個人は、同様の攻撃や犯行の手口をあらかじめ知っておき、予防しようとする努力が必要である。

7. 付録

부록 A. MITRE ATT&CK

| Tactic | Techniques |
| --- | --- |
| Initial Access | T1660: Phishing |
| Persistence | T1541: Foreground Persistence-nT1624.001: Event Triggered Execution: Broadcast Receivers |
| Defense Evasion | T1575: Native API-nT1630.002: Indicator Removal on Host: File Deletion-nT1655: Masquerading |
| Discovery | T1418: Software Discovery-nT1420: File and Directory Discovery-nT1426: System Information Discovery-nT1430: Location Tracking |
| Collection | T1417.001: Input Capture:Keylogging-nT1429: Audio Capture-nT1512: Video Capture-nT1616: Call Control-nT1636.002: Protected User Data: Call Log-nT1636.003: Protected User Data: Contact List-nT1636.004: Protected User Data: SMS Messages |
| Command and Control | T1437: Application Layer Protocol |
| Exfiltration | T1646: Exfiltration Over C2 Channel

| Tactic | Techniques |
| --- | --- |
| Initial Access | T1660: Phishing |
| Persistence | T1541: Foreground Persistence-nT1624.001: Event Triggered Execution: Broadcast Receivers |
| Defense Evasion | T1575: Native API-nT1630.002: Indicator Removal on Host: File Deletion-nT1655: Masquerading |
| Discovery | T1418: Software Discovery-nT1420: File and Directory Discovery-nT1426: System Information Discovery-nT1430: Location Tracking |
| Collection | T1417.001: Input Capture:Keylogging-nT1429: Audio Capture-nT1512: Video Capture-nT1616: Call Control-nT1636.002: Protected User Data: Call Log-nT1636.003: Protected User Data: Contact List-nT1636.004: Protected User Data: SMS Messages |
| Command and Control | T1437: Application Layer Protocol |
| Exfiltration | T1646: Exfiltration Over C2 Channel

| Tactic | Techniques |
| --- | --- |
| Initial Access | T1660: Phishing |
| Persistence | T1541: Foreground Persistence-nT1624.001: Event Triggered Execution: Broadcast Receivers |
| Defense Evasion | T1575: Native API-nT1630.002: Indicator Removal on Host: File Deletion-nT1655: Masquerading |
| Discovery | T1418: Software Discovery-nT1420: File and Directory Discovery-nT1426: System Information Discovery-nT1430: Location Tracking |
| Collection | T1417.001: Input Capture:Keylogging-nT1429: Audio Capture-nT1512: Video Capture-nT1616: Call Control-nT1636.002: Protected User Data: Call Log-nT1636.003: Protected User Data: Contact List-nT1636.004: Protected User Data: SMS Messages |
| Command and Control | T1437: Application Layer Protocol |
| Exfiltration | T1646: Exfiltration Over C2 Channel

caption - MITRE ATT&CK

부록 B. IOCs

MD5

  • 36677d732da69b7a81a46f9a06c36260 - SecDelivery.APK

  • 3a2a9f205c79ee45a84e3d862884fd72 - auction_8.7.01.APK

  • 27ea7ef88724c51bbe3ad42853bbc204 - vpn APK

  • 86da5e00a9c73c9cb0855805cbc38c4a - airdrop.apk

  • 2b99603cd8e69f82c064856d6ff63996- decrypted CJ security.dat

  • 858588b7c5331c948fb3e84d9b4ddbb7- decrypted auction security.dat

  • 03a117c6cb86859623720e75f839260a - decrypted vpn search.db

  • 2a7dab4c0f6507bc5fd826f9a336d50c - decrypted airdrop security.dat

  • 436287ad0ea3a9e94cd4574d54d0dec5 - mobile.html

  • c90ee7d3b1226f73044e7ae635493d31 - delivery.html

  • 506e136336ca9d7246caf8c9011fe97e - login.html

C&C

  • 27.102.137[.]106

  • 27.102.137[.]181

  • 27.102.137[.]93

  • 27.102.137[.]214

  • 27.102.138[.]163

  • 27.102.137[.]180

  • 27.102.138[.]181

부록 C. 명령 목록

| 명령 | 동작 |
| --- | --- |
| 10254 | 오디오 녹음 중지 |
| 10255 | 배경 화면 전송 |
| 10256 | 오디오 녹음 시작 |
| 10257 | 카메라 정보 전송 |
| 10258 | 카메라 녹화 시작 |
| 10259 | 카메라 녹화 종료 |
| 10260 | 각종 플래그와 변수 설정 |
| 10261 | 파일 탐색기 정보 전송 |
| 10262 | 비디오, 이미지 썸네일 전송 |
| 10263 | f1207X 플래그 false 디컴파일 불가 메소드 호출 |
| 10264 | f1207X 플래그 true |
| 10265 | 파일 정보 수집 (경로, 길이) |
| 10266 | 파일을 청크로 나누어 업로드 |
| 10267 | 텍스트 파일 업로드 |
| 10268 | 파일 다운로드 |
| 10269 | 위치 수집 서비스 시작 정보 전송 |
| 10270 | 위치 수집 서비스 종료 |
| 10271 | 통화 기록 전송 |
| 10272 | 등록된 계정 정보 전송 |
| 10273 | 연락처 정보 전송 |
| 10274 | 디컴파일 불가 |
| 10275 | 설치된 어플리케이션 정보 전송 |
| 10276 | 지정된 패키지 실행 |
| 10278 | 메세지 전송 |
| 10279 | 전화 연결 |
| 10281 | C&C 서버 재연결 |
| 10282 | 소켓 연결 정리 |
| 10283 | 원격 명령 실행 |
| 10284 | 파일 쓰기 |
| 10285 | 파일/디렉토리 생성 |
| 10286 | 파일 이름 변경 |
| 10287 | 파일 삭제 |
| 10288 | 디렉토리 삭제 |
| 10289 | 배경 화면 설정 |
| 10290 | 파일 이동/복사 |
| 10291 | 오디오 재생 |
| 10292 | 오디오 재생 중지 |
| 10293 | zip 압축 |
| 10294 | zip 압축 해제 |
| 10295 | 정보 전송 |
| 10296 | 오디오/무선 설정 |
| 10297 | 로그 파일 목록 전송 |
| 10298 | 로그 전송 |
| 10299 | 로그 삭제 |
| 10300 | 실시간 로깅 활성화 |
| 10301 | 실시간 로깅 비활성화 |
| 10302 | 새로운 C&C 서버 설정 |
| 10303 | 특정 전화번호와의 최신 통화 기록 삭제 |
| 10304 | 연락처 삭제 |
| 10305 | 연락처 추가 |
| 10306 | 데이터 삭제 / 화면 잠금 / 비밀번호 변경 권한 상승 필요 |
| 10307 | 파일 열기 |
| 10308 | 패키지 정보 전송 |
| 10309 | OK 메세지 전송 |
| 10310 | 전송된 메세지 출력 |
| 10311 | 진동 중지 |
| 10312 | 진동 시작

| 명령 | 동작 |
| --- | --- |
| 10254 | 오디오 녹음 중지 |
| 10255 | 배경 화면 전송 |
| 10256 | 오디오 녹음 시작 |
| 10257 | 카메라 정보 전송 |
| 10258 | 카메라 녹화 시작 |
| 10259 | 카메라 녹화 종료 |
| 10260 | 각종 플래그와 변수 설정 |
| 10261 | 파일 탐색기 정보 전송 |
| 10262 | 비디오, 이미지 썸네일 전송 |
| 10263 | f1207X 플래그 false 디컴파일 불가 메소드 호출 |
| 10264 | f1207X 플래그 true |
| 10265 | 파일 정보 수집 (경로, 길이) |
| 10266 | 파일을 청크로 나누어 업로드 |
| 10267 | 텍스트 파일 업로드 |
| 10268 | 파일 다운로드 |
| 10269 | 위치 수집 서비스 시작 정보 전송 |
| 10270 | 위치 수집 서비스 종료 |
| 10271 | 통화 기록 전송 |
| 10272 | 등록된 계정 정보 전송 |
| 10273 | 연락처 정보 전송 |
| 10274 | 디컴파일 불가 |
| 10275 | 설치된 어플리케이션 정보 전송 |
| 10276 | 지정된 패키지 실행 |
| 10278 | 메세지 전송 |
| 10279 | 전화 연결 |
| 10281 | C&C 서버 재연결 |
| 10282 | 소켓 연결 정리 |
| 10283 | 원격 명령 실행 |
| 10284 | 파일 쓰기 |
| 10285 | 파일/디렉토리 생성 |
| 10286 | 파일 이름 변경 |
| 10287 | 파일 삭제 |
| 10288 | 디렉토리 삭제 |
| 10289 | 배경 화면 설정 |
| 10290 | 파일 이동/복사 |
| 10291 | 오디오 재생 |
| 10292 | 오디오 재생 중지 |
| 10293 | zip 압축 |
| 10294 | zip 압축 해제 |
| 10295 | 정보 전송 |
| 10296 | 오디오/무선 설정 |
| 10297 | 로그 파일 목록 전송 |
| 10298 | 로그 전송 |
| 10299 | 로그 삭제 |
| 10300 | 실시간 로깅 활성화 |
| 10301 | 실시간 로깅 비활성화 |
| 10302 | 새로운 C&C 서버 설정 |
| 10303 | 특정 전화번호와의 최신 통화 기록 삭제 |
| 10304 | 연락처 삭제 |
| 10305 | 연락처 추가 |
| 10306 | 데이터 삭제 / 화면 잠금 / 비밀번호 변경 권한 상승 필요 |
| 10307 | 파일 열기 |
| 10308 | 패키지 정보 전송 |
| 10309 | OK 메세지 전송 |
| 10310 | 전송된 메세지 출력 |
| 10311 | 진동 중지 |
| 10312 | 진동 시작

| 명령 | 동작 |
| --- | --- |
| 10254 | 오디오 녹음 중지 |
| 10255 | 배경 화면 전송 |
| 10256 | 오디오 녹음 시작 |
| 10257 | 카메라 정보 전송 |
| 10258 | 카메라 녹화 시작 |
| 10259 | 카메라 녹화 종료 |
| 10260 | 각종 플래그와 변수 설정 |
| 10261 | 파일 탐색기 정보 전송 |
| 10262 | 비디오, 이미지 썸네일 전송 |
| 10263 | f1207X 플래그 false 디컴파일 불가 메소드 호출 |
| 10264 | f1207X 플래그 true |
| 10265 | 파일 정보 수집 (경로, 길이) |
| 10266 | 파일을 청크로 나누어 업로드 |
| 10267 | 텍스트 파일 업로드 |
| 10268 | 파일 다운로드 |
| 10269 | 위치 수집 서비스 시작 정보 전송 |
| 10270 | 위치 수집 서비스 종료 |
| 10271 | 통화 기록 전송 |
| 10272 | 등록된 계정 정보 전송 |
| 10273 | 연락처 정보 전송 |
| 10274 | 디컴파일 불가 |
| 10275 | 설치된 어플리케이션 정보 전송 |
| 10276 | 지정된 패키지 실행 |
| 10278 | 메세지 전송 |
| 10279 | 전화 연결 |
| 10281 | C&C 서버 재연결 |
| 10282 | 소켓 연결 정리 |
| 10283 | 원격 명령 실행 |
| 10284 | 파일 쓰기 |
| 10285 | 파일/디렉토리 생성 |
| 10286 | 파일 이름 변경 |
| 10287 | 파일 삭제 |
| 10288 | 디렉토리 삭제 |
| 10289 | 배경 화면 설정 |
| 10290 | 파일 이동/복사 |
| 10291 | 오디오 재생 |
| 10292 | 오디오 재생 중지 |
| 10293 | zip 압축 |
| 10294 | zip 압축 해제 |
| 10295 | 정보 전송 |
| 10296 | 오디오/무선 설정 |
| 10297 | 로그 파일 목록 전송 |
| 10298 | 로그 전송 |
| 10299 | 로그 삭제 |
| 10300 | 실시간 로깅 활성화 |
| 10301 | 실시간 로깅 비활성화 |
| 10302 | 새로운 C&C 서버 설정 |
| 10303 | 특정 전화번호와의 최신 통화 기록 삭제 |
| 10304 | 연락처 삭제 |
| 10305 | 연락처 추가 |
| 10306 | 데이터 삭제 / 화면 잠금 / 비밀번호 변경 권한 상승 필요 |
| 10307 | 파일 열기 |
| 10308 | 패키지 정보 전송 |
| 10309 | OK 메세지 전송 |
| 10310 | 전송된 메세지 출력 |
| 10311 | 진동 중지 |
| 10312 | 진동 시작

caption - 명령 목록

부록 D. Scripts

APK 복호화 스크립트

import argparse
from typing import List

def rol8(x, r):
    r &= 7
    return ((x << r) | (x >> (8 - r))) & 0xFF

def parse_key_hex(s):
    s = s.strip()
    hexstr = "".join(s)
    bs = [int(hexstr[i:i+2], 16) for i in range(0, 8, 2)]
    return bs

def xor_decrypt_stream(fin, fout, key_bytes):
    data = fin.read()
    out = bytearray(len(data))
    for i, c in enumerate(data):
        c8 = c & 0xFF
        t = rol8((~c8) & 0xFF, 5)
        out[i] = key_bytes[i & 3] ^ t
    fout.write(out)

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("infile", help="input file")
    ap.add_argument("outfile", help="output file")
    ap.add_argument("key_hex", help='4-byte key in hex (e.g. "12345678")')
    args = ap.parse_args()

    key = parse_key_hex(args.key_hex)
    with open(args.infile, "rb") as fin, open(args.outfile, "wb") as fout:
        xor_decrypt_stream(fin, fout, key)

if __name__ == "__main__":
    main()
import argparse
from typing import List

def rol8(x, r):
    r &= 7
    return ((x << r) | (x >> (8 - r))) & 0xFF

def parse_key_hex(s):
    s = s.strip()
    hexstr = "".join(s)
    bs = [int(hexstr[i:i+2], 16) for i in range(0, 8, 2)]
    return bs

def xor_decrypt_stream(fin, fout, key_bytes):
    data = fin.read()
    out = bytearray(len(data))
    for i, c in enumerate(data):
        c8 = c & 0xFF
        t = rol8((~c8) & 0xFF, 5)
        out[i] = key_bytes[i & 3] ^ t
    fout.write(out)

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("infile", help="input file")
    ap.add_argument("outfile", help="output file")
    ap.add_argument("key_hex", help='4-byte key in hex (e.g. "12345678")')
    args = ap.parse_args()

    key = parse_key_hex(args.key_hex)
    with open(args.infile, "rb") as fin, open(args.outfile, "wb") as fout:
        xor_decrypt_stream(fin, fout, key)

if __name__ == "__main__":
    main()
import argparse
from typing import List

def rol8(x, r):
    r &= 7
    return ((x << r) | (x >> (8 - r))) & 0xFF

def parse_key_hex(s):
    s = s.strip()
    hexstr = "".join(s)
    bs = [int(hexstr[i:i+2], 16) for i in range(0, 8, 2)]
    return bs

def xor_decrypt_stream(fin, fout, key_bytes):
    data = fin.read()
    out = bytearray(len(data))
    for i, c in enumerate(data):
        c8 = c & 0xFF
        t = rol8((~c8) & 0xFF, 5)
        out[i] = key_bytes[i & 3] ^ t
    fout.write(out)

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("infile", help="input file")
    ap.add_argument("outfile", help="output file")
    ap.add_argument("key_hex", help='4-byte key in hex (e.g. "12345678")')
    args = ap.parse_args()

    key = parse_key_hex(args.key_hex)
    with open(args.infile, "rb") as fin, open(args.outfile, "wb") as fout:
        xor_decrypt_stream(fin, fout, key)

if __name__ == "__main__":
    main()

エンキホワイトハット

エンキホワイトハット

ENKI ホワイトハット
ENKI ホワイトハット

オフェンシブセキュリティの専門企業として、攻撃者の視点から次元の異なるセキュリティを提示します。

オフェンシブセキュリティの専門企業として、攻撃者の視点から次元の異なるセキュリティを提示します。

隙のないセキュリティ設計の始まり、NO.1ホワイトハッカーのノウハウから

インシデント発生前、
今すぐ備えましょう

隙のないセキュリティ設計の始まり、
No.1ホワイトハッカーのノウハウから

インシデント発生前、
今すぐ備えましょう

隙のないセキュリティ設計の始まり、
No.1ホワイトハッカーのノウハウから

インシデント発生前、
今すぐ備えましょう

購読する

コンテンツが役に立ったら?
エンキーレターを購読しましょう!

Copyright © 2025. ENKI WhiteHat Co., Ltd. All rights reserved.

Copyright © 2025. ENKI WhiteHat Co., Ltd. All rights reserved.

Copyright © 2025. ENKI WhiteHat Co., Ltd. All rights reserved.