《 ELFマルウェアワークショップの方々へ 》
AVTOKYO-2015でELFマルウェアワークショップ「Swimming in the Sea of ELF」を開催しました。来てくれた皆さんに有難う御座いました。丁度最近Linuxランサムウェアが流行ったので、ワークショップ上でunix shellでリバーシングが必要な理由を説明しました。ワークショップで説明したr2をセットアップした後、下記のリバーシングメモを参考に練習が出来ると思います。
=> >English version is here and here
目次
(1)感染のバックグラウンド
(2)どんなソースコードを使用しているのか
(3)何処から何処まで暗号化されているのか
(4)復号機能のリバーシング
(5)なぜPolarSSLのソースコードが沢山使われたのか
(6)ずっと最初から「PolarSSL」を使われたのか
(7)結論
《 感染のバックグラウンド 》
感染されたサイトは例えば↓(下のサイトにはwordpressのファイルアップロード脆弱性がある)
検索のキーワードは「README_FOR_DECRYPT.txt」でdorkで検索したら出てくる。
感染されたサイトからの「README_FOR_DECRYPT.txt」のメッセージを確認すると、こんな感じ↓
(※クリックで拡大)
《 どんなソースコードを使用しているのか 》
実はどんな物なのか「Linux/Encoder.1」ランサムウェアのELF x86-64とx86-32のバイナリサンプルを調査した。
リバーシングしたら中身は単純すぎで、本当にがっかりした。もしかしたら素人が作ったんじゃないのかと思うほど。
ソースコードのセットは↓
↑全部C言語で、マルウェア全体に使っているシステムコールのコードはソースコードに入ってる、目的は分かり易い。恐らくランサムウェアのメインコードは「main.c」だと思う。
メモ:秀丸のgrepでソースコードはさくっと検索が出きるよw
《 何処から何処まで暗号化されているのか 》
調査した結果上で、マルウェアで暗号化されているファイル/DIRじゃ「OK」と「禁止」ルールがある↓
0x002F1FC /root/.ssh (exclusion)_ / 暗号禁止 0x002F207 /usr/bin (exclusion)_ / 暗号禁止 0x002F210 /etc/ssh (exclusion)_ / 暗号禁止 0x002F219 /home 0x002F21F /root 0x002F225 /var/lib/mysql 0x002F234 /var/www 0x002F23D /etc/nginx 0x002F248 /etc/apache2 0x002F255 /var/log
メモ:最初段階の暗号化されているターゲット↓
メモ:その次は下記の暗号化除外↓(別途サンプルx86-32 ELF種類)
下記のファイル拡張子の全ては暗号化されている↓
0x002F25E .php 0x002F263 .html 0x002F269 .tar 0x002F26E .gz 0x002F272 .sql 0x002F277 .js 0x002F27B .css 0x002F280 .pdf 0x002F285 .tgz 0x002F28A .war 0x002F28F .jar 0x002F294 .java 0x002F29A .class 0x002F2A1 .ruby 0x002F2A7 .rar 0x002F2AC .zip 0x002F2B1 .db 0x002F2B5 .7z 0x002F2B9 .doc 0x002F2BE .xls 0x002F2C3 .properties 0x002F2CF .xml 0x002F2D4 .jpg 0x002F2D9 .jpeg 0x002F2DF .png 0x002F2E4 .gif 0x002F2E9 .mov 0x002F2EE .avi 0x002F2F3 .wmv 0x002F2F8 .mp3 0x002F2FD .mp4 0x002F302 .wma 0x002F307 .aac 0x002F30C .wav 0x002F311 .pem 0x002F316 .pub 0x002F31B .docx 0x002F321 .apk 0x002F326 .exe 0x002F32B .dll 0x002F330 .tpl 0x002F335 .psd 0x002F33A .asp 0x002F33F .phtml 0x002F346 .aspx 0x002F34C .csv 0x002F36B .git 0x002F370 .svn
それとgrep/regexで下記の単語が入っているファイルも↓
0x002F351 public_html 0x002F35D webapp 0x002F364 backup
《 復号機能のリバーシング 》
【重要】暗号化されているファイルは「.encrypted」という拡張子名が追加される。
コードを見た限りでは本物のファイルが「unlink」で削除されていただけww(未だ確認出来てないですが恐らくext4だとリストアが出来るかと思われる…)。
decrypter(復号関数)は2つがあり、decrypt_all()とdecrypt_file()なので、
decrypt_all()の*SNIP*リバースデータはこんな感じ↓
[ xrefs: 0x004014f1 0x00401502 0x00401523 0x004014a5 0x004014b6 0x0040098e 0x00400ad3 ]
【重要】上記のリバーシング情報の大して、いくつかのポイント↓
1. その関数を動かす為に引数(arguement)が必ず必要、引数無しだとこのランサムウェアの動かす意味が無い。
例えばこのコマンドラインみたいに⇒ ./ランサムウェアファイル名 [crypt|decrypt] [キー]
x86-32のサンプルには引数のスイッチ機能が下記のように見えます↓
2. リバースコードを見たらLinuxサーバ全体に"/"DIRからのdecrypt(復号)が可能。
3. decrypt_all()は結局最後にdecrypt_file()を実行する。
decrypt_file()の関数について下記のアドレスで見れる、準備はこんな感じ↓
[ addr: 0x00400617 xref: 0x00400a4f xcall: setChmod() ]
【重要】ヒント:"Decrypting file: %s"のstringを探してください(とても分かりやすい)
この辺は面白い、ランサムウェアなのに、システムコール使うよりもstdio.hが使われているww
開いたファイルのデータはfread_unlockedで(void *data, size_t size, size_t count, FILE *stream)読み込みされる
次のリバーシングコードでマルウェアに暗号化されたファイルのdecrypt(復号)仕方の説明。
【重要】まず、このランサムウェアの復号機能の仕組みは、RSAプライベートキー(犯罪者が持っている)とパブリックキー(被害者が持っている)を使い、バイナリに書いた暗号化されているAESキーを取り戻す。そして、そのAESキーを使ってマルウェアに暗号化されているファイルの取り戻すことも出来る。
そのAESキーはプライベートキーで暗号化されている(バイナリの中で)↓
0x002FF58 -----BEGIN ENCRYPTED PRIVATE KEY----- 0x002FF80 9292758453063D803DD603D5E777D7888ED1D5BF35786190FA2F23EBC0848AEADDA92CA6C3D80B32C4D109BE0F36D6AE7130B9CED7ACDF54CFC7555AC14EEBAB93A89813FBF3C4F8066D2D800F7C38A81AE31942917403FF4946B0A83D3D3E05EE57C6F5F5606FB5D4BC6CD34EE0801A5E94BB77B07507233A0BC7BAC8F90F79 0x0030088 24BF6185468786FDD303083D25E64EFC66CA472BC44D253102F8B4A9D3BFA75091386C0077937FE33FA3252D28855837AE1B484A8A9A45F7EE8C0C634F99E8CDDF79C5CE07EE72C7F123142198164234CABB724CF78B8173B9F880FC86322407AF1FEDFDDE2BEB674CA15F3E81A1521E071513A1E85B5DFA031F21ECAE91A34D 0x0030190 C36D0EB7FCD285223CFB5AABA5BDA3D82C01CAD19EA484A87EA4377637E75500FCB2005C5C7DD6EC4AC023CDA285D796C3D9E75E1EFC42488BB4F1D13AC30A57 0x0030218 C000DF51A7C77AE8D7C7370C1FF55B69E211C2B9E5DB1ED0BF61D0D9899620F4910E4168387E3C30AA1E00C339A795088452DD96A9A5EA5D9DCA68DA636032AF 0x00302A0 C1ACF567564274FB07A0BBAD5D26E2983C94D22288ACD763FD8E5600ED4A702DF84198A5F06C2E72236AE490C93F07F83CC559CD27BC2D1CA488811730BB5725 0x0030328 4959CBF6F8FEF750AEE6977C155579C7D8AAEA56749EA28623272E4F7D0592AF7C1F1313CAC9471B5C523BFE592F517B407A1BD76C164B93DA2D32A383E58357 0x00303B0 9AE7FBC99546432DF71896FC239EADAEF38D18D2B2F0E2DD275AA977E2BF4411F5A3B2A5D33605AEBBCCBA7FEB9F2D2FA74206CEC169D74BF5A8C50D6F48EA08 (などなど…)メモ:「などなど…」の所にRSAコマンドのアウトプットがそのままで全て書いてある。ようはAESキーを暗号化された時のアウトプットがバイナリにパース(PARSE)されていたと分かった。恐らくそれぞれのLinuxランサムウェアのバイナリを作った時にビルダーを使ったよう。
AESの種類はCBC(下記のリバーシングのコードと確認が出来る↓)
[ xref: 0x0400836 xcall: aes_decrypt() ]
そして、decrypt_file()関数をリバーシングしたらこんな感じで↓(もっと大きい画像はこちら)
[ xref: 0x00400a4f xcall: setChmod() ]
※このパラグラフが英語で説明した方が分かりやすいと思うので【こちらを】ご覧下さい。
《 なぜPolarSSLのソースコードが沢山使われたのか 》
本ランサムウェアをリバーシングしたら沢山のPolarSSLソースコードの関数を発見した。何故PolarSSLが使われたのか下記に説明する↓
AES復号機能の中にはmbedtls_aes_setkey_dec と mbedtls_aes_crypt_cbc のコードが使われ、両方はPolarSSL「mbedtls/pk.h」からかぱくってきたソースコードだと分かった。その関数の中でAESキーの長さとAESのCBC暗号種類を使ったのも分かった。AESビットの長さは、asmでコールの仕方を見たら何も設定されてないので標準のままで、128ビットだね。AES暗号・復号機能のために便利なオープンソース(polarSSL)からぱくってきたんだと思われる←PolarSSLを悪用する理由(1)
尚、暗号化されたファイルの復号機能の中で取り戻したファイルのデータもstdio.hでのfwrite_unlockedの書き込まれた。これでランサムウェアに暗号化されたファイル復号機能の説明は終わり。次はRSAで暗号化されているAESキーを復号する方法の説明。
RSA復号機能(AESキーのクラック機能)のasmコードを読むと、順序はこんな感じで↓(参考コードはこちらへ)
0x400753でprivate_decrypt()の関数があり、その関数の中で分析を続けて行くとmbedtls_pk_decrypt()関数がある。mbedtls_pk_decrypt()関数の目的はバイナリで暗号化されたAESキーを復号する事。そして、そのAESキーを使うと暗号化されていたファイルをリストアする事が出来る。
mbedtls_pk_decryptコード自体もPolarSSLのソースコードであり、もともとSSLの上で暗号化されていたメッセージを復号する事がこの回数の目的。仕様書に確認するとmbedtls_pk_decryptは「RSA default padding type PKCS#1 v1.5」に対応している、という意味ではmbedtls_pk_decryptはRSA暗号の復号化が出来る←PolarSSLを悪用する理由(2)
上記の説明に当たり、AESキーの復号機能をリバーシングすると下記のように見える↓
[ xref: 0x0400753 xcall: private_decrypt() ]
※このパラグラフが英語で説明した方が分かりやすいと思うので【こちらを】ご覧下さい。
《 ずっと最初から「PolarSSL」を使われたのか 》
詰まり…PolarSSLの前は何のcryptoライブラリーを使用していたのか?何故最近になって「PolarSSL」が使われるようになったのか?
実は「Linux.Encoder.1」の前のLinuxランサムウェアのバーションがあったので、当時「PolarSSL」は使われず、「OpenSSL」だった。証拠は下記の2件↓
RSAプライベートキーの暗号化の機能のリバーシング↓
AESキーの暗号化機能のリバーシング↓
※最初から使われたAESキーの長さは128ビット。
cryptoライブラリーが変わった原因は恐らくPolarSSLの方がバグのない、かつ新しいコードが入っているからかと思われる。
《 結論 》
APIみたいな使い方で引数が必要 arg1=暗号|復号 arg2=RSA、感染されたサーバに残したスクリプトを確認が出来たら使い方が直ぐに分かると思われる。暗号機能がほぼPolarSSLからのコード。読み込みと書き込みはstdio.hの関数で作られた。システム周りのコマンドも結構そのままで実行される(unlink,chmod,など)…ブロックも行けそう。journaldに対応しているシステムではリストアが可能かと。いくつかの攻撃元アドレスと確認したので作者は東ヨーロッパの人っぽいね。
#Linux #ELF マルウェアワークショップ(@avtokyo )に来てくれたの方々の練習が出来るように「ELF Linuxランサムウェア復号機能解析」のリバーシングメモを書きましたので、この記事の参考に練習して下さいね!
https://t.co/z8UDClV9SU
— ☩MalwareMustDie (@MalwareMustDie) 2015, 11月 21
メモ以上
reversing by @unixfreaxjp - founder & team leader of MalwareMustDie
0 件のコメント:
コメントを投稿