CTFするぞ

CTF以外のことも書くよ

【Forensics 250】matroska - InterKosenCTF 作問writeup

はじめに

この記事ではInterKosenCTFで出題した問題の解説を書きます。 他の問題のwriteupについては下記リンクから参照してください。

ptr-yudai.hatenablog.com

概要

Description: I just tried to watch a movie.
OS: Windows 10 x64 (RS4)
File: matroska.tar.gz

Windows 10 x64のメモリダンプが渡されます. ファイルサイズが大きいのは申し訳ないですがどうしようもないんです. 私はメモリダンプの問題はvolatilityで解く人です. Slackでも連絡しましたが,この問題をvolatilityで解く場合はstandaloneでない最新のものを使わないと対応するプロファイルが無くてすらすら解けません.

解法

Windows 10のRS4を調べるとビルド番号は17134であることが分かります. volatilityではプロファイルはWin10x64_17134にあたるので,これを使います. まずはpstreeを見てみましょう.

$ vol.py -f memdump.raw --profile=Win10x64_17134 pstree
Volatility Foundation Volatility Framework 2.6.1
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0xffffe00e553b7080:winlogon.exe                      516    432      6      0 2018-12-25 03:09:58 UTC+0000
. 0xffffe00e55794580:fontdrvhost.ex                   664    516      6      0 2018-12-25 03:09:58 UTC+0000
. 0xffffe00e5703d580:userinit.exe                    3364    516      0 ------ 2018-12-25 03:10:12 UTC+0000
.. 0xffffe00e5703f580:explorer.exe                   3452   3364     88      0 2018-12-25 03:10:13 UTC+0000
... 0xffffe00e577fe580:VBoxTray.exe                  6036   3452     14      0 2018-12-25 03:10:43 UTC+0000
... 0xffffe00e5701f080:DumpIt.exe                    2080   3452      2      0 2018-12-25 03:11:30 UTC+0000
.... 0xffffe00e578a8080:conhost.exe                  2260   2080      5      0 2018-12-25 03:11:30 UTC+0000
... 0xffffe00e57376580:MSASCuiL.exe                  5988   3452      6      0 2018-12-25 03:10:41 UTC+0000
... 0xffffe00e576d1580:vlc.exe                       5700   3452      0 ------ 2018-12-25 03:11:00 UTC+0000
.... 0xffffe00e574fe3c0:svchost.exe                  4940   5700      2      0 2018-12-25 03:11:10 UTC+0000
..... 0xffffe00e5618a580:conhost.exe                 3368   4940      6      0 2018-12-25 03:11:10 UTC+0000
. 0xffffe00e568ed580:dwm.exe                          884    516     14      0 2018-12-25 03:09:59 UTC+0000
 0xffffe00e552ce580:csrss.exe                         452    432     12      0 2018-12-25 03:09:57 UTC+0000
 0xffffe00e551c1580:csrss.exe                         372    364     11      0 2018-12-25 03:09:57 UTC+0000
 0xffffe00e5539e080:wininit.exe                       440    364      5      0 2018-12-25 03:09:57 UTC+0000
[省略]

問題文的にvlc.exeあたりを見てみると,vlcからsvchost.exeが呼び出されています. ちょっと前までvolatilityはまだWin10に全然に対応しておらず,こういったコマンドが動かない場合がありました. その際はyarascanとかを使ってcookieという値を取り出す必要があったのですが,最近のはwin10cookieなるコマンドも用意されており,だいたい使えます. また,プロセスがEPROCESS構造体などをいじって隠蔽されている場合はpsxviewを使うと見つかります.

さて,PIDが4940のsvchost.exeにロードされたdll一覧を見てみましょう.

$ vol.py -f memdump.raw --profile=Win10x64_17134 dlllist -p 4940
Volatility Foundation Volatility Framework 2.6.1
************************************************************************
svchost.exe pid:   4940
Command line : C:\Windows\svchost.exe


Base                             Size          LoadCount LoadTime                       Path
------------------ ------------------ ------------------ ------------------------------ ----
0x0000000000880000            0x17000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\svchost.exe
0x00007ffa8f6e0000           0x1e1000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\SYSTEM32\ntdll.dll
0x0000000077410000            0x52000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\System32\wow64.dll
0x0000000077380000            0x78000                0x6 2018-12-25 03:11:10 UTC+0000   C:\Windows\System32\wow64win.dll
0x0000000077400000             0xa000                0x6 2018-12-25 03:11:10 UTC+0000   C:\Windows\System32\wow64cpu.dll
0x0000000000880000            0x17000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\svchost.exe
0x0000000077470000           0x190000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\SYSTEM32\ntdll.dll
0x0000000074420000            0xe0000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\System32\KERNEL32.DLL
0x0000000074550000           0x1e3000             0xffff 2018-12-25 03:11:10 UTC+0000   C:\Windows\System32\KERNELBASE.dll
0x0000000076790000           0x18d000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\USER32.dll
0x00000000748f0000            0x17000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\win32u.dll
0x00000000764f0000            0x22000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\GDI32.dll
0x0000000075030000           0x164000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\gdi32full.dll
0x0000000077060000            0x7d000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\msvcp_win.dll
0x0000000076670000           0x11e000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\ucrtbase.dll
0x0000000077030000            0x26000                0x6 2018-12-25 03:11:11 UTC+0000   C:\Windows\System32\IMM32.DLL
0x0000000073b80000            0x16000                0x6 2018-12-25 03:11:12 UTC+0000   C:\Windows\user32.dll
0x0000000073b00000            0x7c000                0x6 2018-12-25 03:11:12 UTC+0000   C:\Windows\system32\uxtheme.dll
0x0000000076a20000            0xbf000             0xffff 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\msvcrt.dll
0x0000000076c10000           0x25c000             0xffff 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\combase.dll
0x0000000076e70000            0xc0000             0xffff 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\RPCRT4.dll
0x0000000073d30000            0x20000                0x6 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\SspiCli.dll
0x0000000073d20000             0xa000             0xffff 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\CRYPTBASE.dll
0x0000000074350000            0x58000             0xffff 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\bcryptPrimitives.dll
0x0000000073d50000            0x44000                0x6 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\sechost.dll
0x0000000076520000           0x144000                0x6 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\MSCTF.dll
0x0000000077100000            0x96000                0x6 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\OLEAUT32.dll
0x00000000748e0000             0xf000             0xffff 2018-12-25 03:11:12 UTC+0000   C:\Windows\System32\kernel.appcore.dll
0x0000000073a80000            0x7e000                0x6 2018-12-25 03:11:13 UTC+0000   C:\Windows\SYSTEM32\TextInputFramework.dll
0x0000000073820000           0x25d000             0xffff 2018-12-25 03:11:13 UTC+0000   C:\Windows\SYSTEM32\CoreUIComponents.dll
0x0000000076f90000            0x89000             0xffff 2018-12-25 03:11:13 UTC+0000   C:\Windows\System32\SHCORE.dll
0x00000000772a0000            0x78000             0xffff 2018-12-25 03:11:13 UTC+0000   C:\Windows\System32\advapi32.dll
0x0000000073790000            0x8b000             0xffff 2018-12-25 03:11:13 UTC+0000   C:\Windows\SYSTEM32\CoreMessaging.dll
0x0000000073760000            0x29000             0xffff 2018-12-25 03:11:13 UTC+0000   C:\Windows\SYSTEM32\ntmarta.dll
0x0000000073680000            0xd6000             0xffff 2018-12-25 03:11:13 UTC+0000   C:\Windows\SYSTEM32\wintypes.dll
0x0000000076920000            0xfc000                0x6 2018-12-25 03:11:16 UTC+0000   C:\Windows\System32\ole32.dll

svchost.exeもuser32.dllも明らかにおかしな場所に存在します. svchost.exeとuser32.dllをdlldumpで抽出して解析してみましょう.

$ vol.py -f memdump.raw --profile=Win10x64_17134 dlldump --base=0x0000000000880000 -D dump
$ vol.py -f memdump.raw --profile=Win10x64_17134 dlldump --base=0x0000000073b80000 -D dump

ちなみにdllがunlinkされていてダンプできない場合はoffsetを調べて指定してやれば良いです.

svchost.exeをidaで解析してみましょう. Windowsのバイナリは書いた関数がidaで一番上に表示されるのですが,必ずそうなるものなんでしょうか.

f:id:ptr-yudai:20190121151621p:plain
svchost.exeの関数

こんな感じで特にひねりもない単純な関数があります. user32.dllの__GetWindowLong関数を呼び出しているようです. ちなみにGetWindowLongという関数なら本物のuser32.dllにも存在します.

ではuser32.dllの__GetWindowLongをidaで見ましょう. すごく最適化されているのですが,読むと次のような処理をしています.

for(i = 0; i < strlen(text); i++) {
    text[i] ^= 0xFF ^ i;
}
MessageBoxA(NULL, text, "Information", MB_OK | MB_ICONINFORMATION);
for(i = 0; i < strlen(text); i++) {
    text[i] ^= 0xFF ^ (strlen(text) - i);
}
MessageBoxA(NULL, "Hacked by ptr-yudai", "Information", MB_OK | MB_ICONINFORMATION);

textはグローバル変数なのでidaから中身が見えるのですが,ここで注意しなくてはならないことがあります. 普通のリバージングならtextの中身を上から処理していけばフラグが分かるのですが,このバイナリはメモリダンプから取り出したもので,かつこの関数はsvchost.exeから一度呼び出されています. したがって,textの中身は関数を呼び出した後の状態になっているので,フラグを入手するには逆から戻さなければなりません. ということでフラグを表示した後の処理をデコードするとフラグが出てきます.

with open("text.dmp", "rb") as f:
    text = f.read()

flag = ""
for (i, c) in enumerate(text):
    flag += chr(ord(c) ^ 0xFF ^ (len(text) - i))

print(flag)

ちなみにグローバル変数textの中身は次のIDCで取り出せます.

auto file, fname, address, size, i;
address = Text;
size = 0x31;
fname = "/tmp/text.dmp";
file = fopen(fname, "wb");
for(i = address; i < address + size; i++) {
    fput(Byte(i), file);
}
fclose(file);

背景

一応フラグはこれで入手できるのですが,ここまで読んでなんでvlcからsvchostが実行されてるの?と思うかもしれません. 実はCVE-2018-11529が使われており,ビデオ開いたことで攻撃コードが実行されています. 問題のタイトルはこのビデオの形式であるmkv(matroska)から取りました. Exploitコードは公開した問題にあります.

svchost.exeとuser32.dllがどこからやってきたかについては......聞かないでください......

あとがき

イデアとしてはCVEを使いたいというのと,コード実行後のメモリの状態を逆に戻す作業をやって欲しいというのでこの問題を作りました. CTFではWin7のメモリダンプがよく出題されて,Win10を見かけないので出してみたのですが,まだ対応していない解析ツールもあるのでWin7にしておくべきでした. Win10を出すにしても,OSのバージョンだけでなくビルド番号とかも問題に書いておくべきだったと反省しています.