はじめに
2019年11月3日〜4日にかけて品川のところの高専でMAIR忍者チャレンジが開催されたので参加しました。 マルウェアに感染したシステムのエビデンスから、感染源や被害範囲、マルウェアの挙動などを解析して、対策などをレポートにまとめるという感じのコンテストです。 本物のマルウェアを使うので面白かったです。 私はひたすら全部のファイルの処理を読んでまとめただけでIRやyaraは他の方がやってくれたので、私の調べた限りのマルウェアの挙動をメインに書こうと思います。
IDBなどはここに置いておきます:
マルウェアの概要
渡されるファイルのうち私が調べたのは以下の6つです。
C:\windows\syswow64\drivers\svchost.exe
C:\windows\syswow64\drivers\wmiex.exe
C:\windows\temp\svchost.exe
C:\windows\temp\taskmgr.exe
C:\windows\temp\YqejbPXw.exe
C:\windows\temp\svchost.mlz
このうちdrivers\svchost.exe, installed.exe, dl.exeはハッシュ値が同じなので、とりあえずsvchostだけ読みました。 私たちの班が解析したところ(他の班もだいたい同じでしたが)こんな感じでした。
目的:
- 仮想通貨Moneroのマイニング
やること:
- サービスとかいろいろ登録して継続的に活動
- mimikatzでパスワードを抜いたりバックドアユーザー作ったり
- MS17-010で感染拡大
情報漏洩:
- コンピュータの情報とか以外には特になし?
- 外部からコマンドが実行できるので流出している可能性はあるが、マルウェアの機能としては無い気がする
drivers\svchost.exe
これは感染して最初に実行されるファイルです。(正確にはC:\installed.exe
が実行される。)
自身のパスをC:\windows\syswow64\drivers\svchost.exe
(32ビットならC:\windows\system32\svchost.exe
)に変更してサービスや自動起動などに登録します。
他にも実行ファイルを生成したり移動したり、ファイアウォールの設定を変更したりと最初の一歩を担います。
感染経路によって名前が異なるようですが、とりあえずdl.exeを作っている処理は見つからなかったのでSMB経由でC:\instaled.exe
が作られ、それが起動後に移動されたと判断しました。
(後から聞いた話ではあのエビデンスは複数のマシンから集めたものらしいので、dl.exeは別のマシンっぽいです。)
それからsvchost.mlzなるファイルを復号しているのですが、win32api特有の謎crypt関数を使っておりwindowsを持っていなかったので無事解析できませんでした。
解析しながらまとめていたノート:
drivers\taskmgr.exe
これはdrivers\svchost.exeから呼ばれるスレッド内で生成および起動されます。また、drivers\svchost.exeの別スレッドではmutexを使ってtaskmgrの存在を確認し、死んでいたらフラグを立てて起動用スレッドで復活させます。taskmgr.exeはsvchost.exeの存在を確認し、死亡していたら復活させます。(svchostのスレッド自身もsvchostを監視している。) あとファイルマッピングを作っているなどはありましたが、それ以上の重要そうな処理は見つかりませんでした。
解析しながらまとめていたノート:
drivers\wmiex.exe
いまいち存在意義が分からないプロセスです。WebServersというタスクで自身を自動起動するのですが、コンピュータの情報を送るくらいしかやってなくね?という感じです。 svchostにまとめても良かったんじゃないかな?
解析しながらまとめていたノート:
temp\svchost.exe
svchost.exeから起動されるファイルです。Python製なのでデコンパイルするととても読みやすいです。 pyinstxtractorで展開するとiiという名前のpycっぽいものが出てきたのですが、ヘッダが欠けていたので適当に埋めてuncompyleに投げるとpythonコードが生成されました。
with open("2_svchost.exe.malware_extracted/ii", "rb") as f: buf = f.read() buf = b'\x03\xf3\x0d\x0a\x00\x00\x00\x00' + buf with open("ii.pyc", "wb") as f: f.write(buf)
これでコードが出てくるのですが、変数名をごちゃごちゃしていたり最初のmimikatzのコードが邪魔なので整形して出力しました。
variables = {} output = "" with open("main.py", "r") as f: for line in f: line = line.rstrip('\n') for key in variables: if key in line: line = line.replace(key, variables[key]) if ' = ' in line: x = line.split(" = ") name = x[0] value = ' = '.join(x[1:]) if 'pnQmOE' in name: variables[name] = value else: if name != 'mkatz': output += line + "\n" else: output += line + "\n" with open("output.py", "w") as f: f.write(output)
これでただのpythonコードになるので困ることなく読めます。 やっていることは、IPアドレスをipconfigやnetstatの結果から集め、またmimikatzでユーザー、パスワードとドメインを取得し、その情報を使って外部のSMBへログイン試行をしたりEternalBlueを回したりしています。 くっそ汚いコードだったので書き直したいなぁと思いながら読んでいました。 (難読化されたmimikatzの部分はチームメンバーが読んでくれました。) exploitも特定のアカウントを作る目的に改造されているものの、基本的にはインターネッツに転がっているPoCの使い回しでした。
解析しながらまとめていたノート:
シェルコード
EternalBlueのシェルコードが付いているわけですが、これは意味不明でした。 だいたいEternalBlueのテンプレ通りなのですが、攻撃者が付加した部分は読む必要があります。 ですが、知らない構造体がいっぱい出てきて理解不能だったので解析を断念しておやすみなさいしました。 シェルコードは文脈を追わないと平気で関数呼び出し前に設定されたレジスタとかを使うから読めない。
YqejbPXw.exe
これはtemp\svchost.exeが作っているっぽいのですが、RemComSvcなるサービスを登録します。 実際にはパイプを作っておしまいというやる気のないサービスですが、PSEXECか何かで使われているんだと思います。 ちゃんと読む時間がなかったのでよく分かってないです。
解析しながらまとめていたノート:
感染源
ディスクダンプすら無いのに感染源特定するの厳しくないですか。
とりあえずSMBでしかinstalled.exe
が作られていなかったのでSMBからやってきたと判断しました。
被害範囲
SMBが入っているやつは全部感染しているでしょう。 とりあえずpython製のsvchostにハードコーディングされていたIPやユーザーリストなどは要注意です。 この辺はチームメンバーがうまいことまとめてくれました。
感想
疲れましたが楽しかったです。 結構頑張って解析したつもりだったのですが、他にも深くまで解析していたチームもいてかなり焦りました。 東京の人強すぎでは。
恒久フリーパス的なものを貰ったので今後も開催されたら是非参加したいです。 運営やスタッフ、スピーカーのみなさん、ありがとうございました。