Shi0shishi0

汐鹿生

YARA Rule Creation Crackmeをやってみた

初めに

Twitterを眺めていたら "YARA Rule Creation Crackme" という変わったものが流れてきた. こういうの新人教育用のネタに使えるかもな~と思ったのでとりあえず自分でやってみた.

このCrackmeで紹介されている検体は, Nextron Systemsがインターンの人に向けたトレーニングのために収集したものらしい. 3種類の検体が紹介されており, これらを検出できるYARAルールを作成するものらしい.

www.nextron-systems.com

詳細な説明は省くが, ざっくり言うと, YARAは文字列やバイナリパターンから作成されたルールを用いてファイルをスキャンし, 当該ファイルをルールに基づいて検出, 分類するツールである. YARAルールはYARAによるスキャンで使用されるルールのことである(そのまま) YARAは様々なところで使用されている.

YARA is a tool aimed at (but not limited to) helping malware researchers to identify and classify malware samples. With YARA you can create descriptions of malware families (or whatever you want to describe) based on textual or binary patterns. Each description, a.k.a rule, consists of a set of strings and a boolean expression which determine its logic.

github.com

今回はそのYARAルールを作成する. 問題の説明によると, このチャレンジは1ルール20分以内に作成するのが望ましいらしい. また, ツールは文字列を抽出するツール, バイナリエディタ, yarGen, Google先生, malware(.)oneを使うのが良いらしい.

・We don’t want to to spend more than 20 minutes for a single rule. ・We use string extraction, hex editors and yarGen ・We also use public resources like Google (yes), malware.one

3種類の検体が紹介されているが, 今回はその中の "PLEAD Downloader" のYARAルール作成をやってみた. この検体を選んだ理由は紹介されていたサンプルが多かったから(他の2種はサンプルが1個ずつしかない)

・Try to compare the samples in order to find specific strings that appear in all of them

サンプル4ファイルの情報は以下の通り.

サンプルとして取り上げられているPLEAD Downloaderは株式会社ラックさんのブログで "攻撃手口2 : シェルコードを利用する「PLEAD」ダウンローダ" として紹介されているものと同種だと思われる. このサンプルはDLL内包型の「攻撃手口1」と異なり, 内部に "暗号化されたシェルコード" を保持している点が特徴的である.

www.lac.co.jp

表層解析

yarGenは使ったこと無いので使わずやってみる.

sample1,2,4を表層解析ツール等で見ると, dataセクションに小文字or大文字のアルファベット文字列が大量にハードコードされているのが確認できる. sample3には他の検体のようなハードコードされた文字列は見られない.

動的解析

ざっと眺めて見て気になるところをピックアップする.

書式指定子

sample1をデバッガで実行して, 参照文字列を見ると, 大量のアルファベット文字列と, "1111ddd_dd2222"などの書式指定子のようなものが見える. この書式指定子はMutexを生成するためのものだが, これは特徴的なのでYARAルールに使えそう.

52                   PUSH EDX                                              ; /<d>
8B85 B0FCFFFF        MOV EAX,DWORD PTR SS:[EBP-350]                        ; |
25 FFFF0000          AND EAX,0FFFF                                         ; |
50                   PUSH EAX                                              ; |<d>
8B8D AEFCFFFF        MOV ECX,DWORD PTR SS:[EBP-352]                        ; |
81E1 FFFF0000        AND ECX,0FFFF                                         ; |
51                   PUSH ECX                                              ; |<d>
8B95 AAFCFFFF        MOV EDX,DWORD PTR SS:[EBP-356]                        ; |
81E2 FFFF0000        AND EDX,0FFFF                                         ; |
52                   PUSH EDX                                              ; |<d>
8B85 A8FCFFFF        MOV EAX,DWORD PTR SS:[EBP-358]                        ; |
25 FFFF0000          AND EAX,0FFFF                                         ; |
50                   PUSH EAX                                              ; |<d>
68 785C4000          PUSH sample1.00405C78                                 ; |format = "1111ddd_dd2222"
8D8D C4FDFFFF        LEA ECX,DWORD PTR SS:[EBP-23C]                        ; |
51                   PUSH ECX                                              ; |s
8B3D A0304000        MOV EDI,DWORD PTR DS:[<&MSVCRT.sprintf>]              ; |msvcrt.sprintf
FFD7                 CALL EDI                                              ; ¥sprintf
83C4 1C              ADD ESP,1C
8D95 C4FDFFFF        LEA EDX,DWORD PTR SS:[EBP-23C]
52                   PUSH EDX                                              ; /MutexName = "111120180621_11012222"
53                   PUSH EBX                                              ; |InitialOwner
53                   PUSH EBX                                              ; |pSecurity
FF15 58304000        CALL DWORD PTR DS:[<&KERNEL32.CreateMutexA>]          ; ¥CreateMutexA

DialogBoxParam API

実行していくとDialogBoxParamAを呼んでいるところがある. このWindowsAPI経由でコードを実行している.

53                   PUSH EBX                                              ; /lParam
68 E01F4000          PUSH sample1.00401FE0                                 ; |DlgProc = sample1.00401FE0
53                   PUSH EBX                                              ; |hOwner
6A 64                PUSH 64                                               ; |pTemplate = 64
8B55 08              MOV EDX,DWORD PTR SS:[EBP+8]                          ; |
52                   PUSH EDX                                              ; |hInst
FF15 F0304000        CALL DWORD PTR DS:[<&USER32.DialogBoxParamA>]         ; ¥DialogBoxParamA

XOR処理とRC4暗号

8A02                 MOV AL,BYTE PTR DS:[EDX]
8A4A 01              MOV CL,BYTE PTR DS:[EDX+1]
42                   INC EDX
42                   INC EDX
FEC8                 DEC AL
F6D0                 NOT AL
C0E1 04              SHL CL,4
24 0F                AND AL,0F
FEC9                 DEC CL
32C1                 XOR AL,CL
88042F               MOV BYTE PTR DS:[EDI+EBP],AL
47                   INC EDI
3BFE                 CMP EDI,ESI
72 E4                JB SHORT sample1.00401974

処理対象の文字列の n番目 と n+1番目 に対して, DEC, NOT, SHL, AND命令で処理を行ない, 最終的に2つの値をXORする. ESIの値がループカウンタになっていて, 処理するデータのサイズは0xD94. このXOR処理のコードはそのままYARAルールに使えるかも.

その後, XOR処理で生成したデータと復号鍵, 鍵のサイズ(0x20)を指定して, RC4暗号でデータを復号する.

RC4Key : 4EqMMLqCSfjE6US9lz7XkjM5athMnejf
Hex    : 3445714D4D4C714353666A45365553396C7A37586B6A4D356174684D6E656A66
6A 20                PUSH 20
50                   PUSH EAX
E8 9CF6FFFF          CALL sample1.00401040

復号されたデータはシェルコードで, これがVirtualAllocで確保されたメモリに展開, 実行される. これ以降も, 復号されたシェルコード内で更にコードや通信先情報の復号処理が行われたりするが, YARAのルールには向かない部分(メモリ上にのみ展開されるコード)なので省略する.

ざっくり説明すると以上のような感じの挙動になっている.

他のsampleとの比較

YARAルールを作る時は1検体を解析し, その後, 当該検体に見られた特徴が他の検体に見られるかを確認するのが良い気がする(当たり前のことだが...) 他の複数検体にも見られる特徴であれば, それをYARAルールに用いる.

各サンプルについて, ハードコードされた書式指定子とXOR処理のコードを列挙してみたら以下のようになった. Sample3は暗号化されたデータの格納方法が他の検体と異なっている + XOR処理が無く, いきなりRC4で復号する形になっている.

また, XOR処理は各検体で酷似しているが, 使用するレジスタの差がある. 1Byteの差はワイルドカードで対応するので良いと思う.

<Sample1>

68 785C4000    PUSH sample1.00405C78                           ; |format = "1111ddd_dd2222"
68 685C4000    PUSH sample1.00405C68                           ;  ASCII "d-d-d"
68 485C4000    PUSH sample1.00405C48                           ;  ASCII "d:d:d"

8A02           /MOV AL,BYTE PTR DS:[EDX]
8A4A 01        |MOV CL,BYTE PTR DS:[EDX+1]
42             |INC EDX
42             |INC EDX
FEC8           |DEC AL
F6D0           |NOT AL
C0E1 04        |SHL CL,4
24 0F          |AND AL,0F
FEC9           |DEC CL
32C1           |XOR AL,CL
88042F         |MOV BYTE PTR DS:[EDI+EBP],AL
47             |INC EDI
3BFE           |CMP EDI,ESI
72 E4          ¥JB SHORT sample1.00401974


<Sample2>

68 70604000          PUSH sample2.00406070                     ; |format = "1111ddd_dd2222"
68 60604000          PUSH sample2.00406060                     ;  ASCII "d-d-d"
68 40604000          PUSH sample2.00406040                     ;  ASCII "d:d:d"

8A02               /MOV AL,BYTE PTR DS:[EDX]
8A4A 01            |MOV CL,BYTE PTR DS:[EDX+1]
42                 |INC EDX
42                 |INC EDX
FEC8               |DEC AL
F6D0               |NOT AL
C0E1 04            |SHL CL,4
24 0F              |AND AL,0F
FEC9               |DEC CL
32C1               |XOR AL,CL
88042F             |MOV BYTE PTR DS:[EDI+EBP],AL
47                 |INC EDI
3BFE               |CMP EDI,ESI
72 E4              ¥JB SHORT sample2.00401894


<Sample3>

68 98B04000    PUSH sample3.0040B098                          ;  ASCII "1....ddd_dd...2"
68 88B04000    PUSH sample3.0040B088                          ;  ASCII "d-d-d"
68 68B04000    PUSH sample3.0040B068                          ;  ASCII "d:d:d"


<Sample4>

68 F8C54000            PUSH sample4.0040C5F8                  ;  ASCII "x....ddd_dd...x"
68 E8C54000            PUSH sample4.0040C5E8                  ;  ASCII "d-d-d"
68 C8C54000            PUSH sample4.0040C5C8                  ;  ASCII "d:d:d"

8A03                   /MOV AL,BYTE PTR DS:[EBX]
8A4B 01                |MOV CL,BYTE PTR DS:[EBX+1]
43                     |INC EBX
43                     |INC EBX
FEC8                   |DEC AL
F6D0                   |NOT AL
C0E1 04                |SHL CL,4
24 0F                  |AND AL,0F
FEC9                   |DEC CL
32C1                   |XOR AL,CL
88043A                 |MOV BYTE PTR DS:[EDX+EDI],AL
42                     |INC EDX
3BD6                   |CMP EDX,ESI
72 E4                  ¥JB SHORT sample4.00401550

ちなみに, VirusTotalの検索結果画面からsample1~4のコンパイル日時を見てみると, Sample3だけが他の3検体よりも1年ぐらい古い.

sample3は他の検体と異なる時期に作られており, この検体だけ他とアセンブリコードの雰囲気も違う. 勝手な想像だが, sample3は他の検体と異なる時期の攻撃に用いられたものなんじゃないかと思う.

sample1
Compilation Timestamp 2018-03-14 01:11:49

sample2
Compilation Timestamp 2018-03-07 07:44:44

sample3
Compilation Timestamp 2017-03-29 07:06:51

sample4
Compilation Timestamp 2018-03-15 13:08:38

Yaraルール作成

sample1〜4を拾うためには, 以下のようなYARAルールを作れれば良い気がする. 2個目の方は3は拾えないけど他は拾える. また, ファイルサイズの範囲指定を入れるのも良いかもと思った.

rule PLEAD_Downloader_FormatStrings
{
    meta:
        sample1 = "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d"
        sample2 = "bc2c8cc9896cdd5816509f43cb5dca7433198251d754a997a70db7e8ed5cca40"
        sample3 = "2ddb2030ab3373b9438102b541aa4623b7dfee972850dcef05742ecbe8982e22"
        sample4 = "a26df4f62ada084a596bf0f603691bc9c02024be98abec4a9872f0ff0085f940"
    strings:
        $a1 = "d:d:d" ascii fullword
        $a2 = "d-d-d" ascii fullword
        $a3 = "1111ddd_dd2222" ascii fullword
        $a4 = "1....ddd_dd...2" ascii fullword
        $a5 = "x....ddd_dd...x" ascii fullword
    condition:
        uint16(0) == 0x5a4d and (2 of them)
}

rule PLEAD_Downloader_XorRoutine
{
    meta:
        sample1 = "eec3f761f7eabe9ed569f39e896be24c9bbb8861b15dbde1b3d539505cd9dd8d"
        sample2 = "bc2c8cc9896cdd5816509f43cb5dca7433198251d754a997a70db7e8ed5cca40"
        sample4 = "a26df4f62ada084a596bf0f603691bc9c02024be98abec4a9872f0ff0085f940"
    strings:
        $a1 = { 8A ?? 8A ?? 01 ?? ?? FE C8 F6 D0 C0 E1 04 24 0F FE C9 32 C1 88 04 ?? ?? 3B ?? 72 E4 }
    condition:
        uint16(0) == 0x5a4d and $a1
}

終わりに

模範解答を見ると, "Scanning..." 等の文字列もYARAルールに使用していた. 正解は1つ!じゃない!!とのことなので.

Remember, there is no single correct solution to this task. Your rules may be better than mine. If that’s the case, please share them with me 😄.

入手したIoCからYARAルールを素早く作成できれば、VirusTotalのHuntingとかが捗ると思う. サンプルが増えればよりよいYARAルールが作れることもあると思う.

今回のYARAルールの作成は20分以内で終わらなかった気がするので, もっと精進したい.