2000P's Blog

最初のページ

nsa explodingcanホール分析とデバッグ

著者 winterton 時間 2020-03-22
all

NSAが漏洩したファイルの中で、私達はwindows/exploiceディレクトリのExplodingcanホールでファイルを利用することに気づきました。このExplodingcanツールはWindows 2003 IIS 6.0上のWEBDAVホール(CVE-2017-7269)の利用を分析した。

NSAリークされたツールパッケージのExplodingcanツールパス:

今回NSAが漏洩したツールバッグの中のExplodingcan-2.0.2.fbファイルの内容:

オペレーティングシステム:Windows Server 2003 R 2 x 86 EN Enterprise

IISサーバ:IIS 6.0バージョン、WebDav拡張を開始しました。

WebClientサービスを開始しました。以下の図です。

WebDAV

HTTP 1.1プロトコルに基づく通信プロトコル。HTTP 1.1を拡張して、GET、POST、HEADなどのいくつかのHTTP標準方法以外に、WebServerに直接読み、書き、ファイルロック、アンロック、ファイルのバージョン制御をサポートします。

PROFIND

メソッドは、指定されたディレクトリの内容を返すために使用します。IISがディレクトリ閲覧権限を開放すると、サイトが指定したディレクトリの下のファイルリストに戻ります。

バグ提出報告からSstragePathFromaUrl関数に問題が発生したことが分かった。WinDBGを使ってプロセスw 3 wp.exeに添付します。w 3 wp.exeプロセスに追加できない場合があります。付加プロセスリストからw 3 wp.exeが見えないため、ネット上で完全に信頼できない説明によると、20分以内に新しい要求がサーバに到着した場合や他の一定の条件が満たされた場合など、システムはw 3 wp.exeプロセスを回収します。そのため、デバッグプログラムを追加するためには、毎回新しい要求が必要です。

ここでu SstragePathFromaUrlを入力し、シンボルサーバから対応符号をダウンロードします。この関数はhttpext.dllにあることが分かります。その対応経路はc:\windows\system 32\inetsrv\httpext.dllにあります。(入力lmfで知ります)。

今から動的デバッグバグプログラムを開始します。前からhttpext!SstragePathFroomUrlにブレークポイントを追加し、WinDBGのコマンドラインにbp httpextを入力します。IDA f 5の逆コンパイルコードとWinDBGデバッグのコマンド、情報などを使って照合します。

WinDBG入力kbはスタックを調べて遡ります。

このPOCが使用すべきものはWEBDAVにおけるpropfind方法であり、呼び出しスタックにおけるDAVPropFindに対応することが、脆弱性公告によって明らかにされた。Executeメンバー関数に入ると、長いことが分かり、このHrCheck StteHeader関数を分析したところ、HrCheckIfHeaderを直接呼び出して、HrCheckIfHeader関数を分析した。

ここでまず一つのことをします。HrCheckIfHeaderにコマンドbp MultiByteToWideCharを入力します。その関数のプロトタイプは以下のように参照できます。

関数の入り口にdd espを入力し、lpMultiByteStrとlpWideCharStrの2つのパラメータを確認します。それぞれ赤い線を引く位置に対応します。

この時はまだ変換されていません。入力ptはこの関数の返却先で対応内容を確認します。

その後、展示された内容はすべて図の右下のunicodeバージョンの文字列の内容です。

HrCheckIfHeaderのwhile(2)サイクル外のIFITER::PszNext Token((int)&v 20,0)を引き続き観察してみると、その帰り先は以下のIf:後からの内容です。

上の図に示す<後、wcslenを用いてhttp全体の開始長さを計算します。最初の場所のSstragePathFroomUrlを呼び出し、POCの内容は1に戻ります。

その後、スコットランド・フロマを呼び出します。この関数は0を返します。for(i=IFITER::PszNext Token((int)&v 20,2);i=IFFER:PszNextToken((int)&v 20,v 19)は、最初の文字で0 x 3 c(<のasciiコード)です。HrValidTokenExpression(a 1,v 17,v 8,0)、非0およびv 22変数を0 x 30にしてlabel_27に移行するとv 26=1になり、v 19=3になって次のサイクルに入ります。サイクル中のIFITER:PszNext Tokenが空に戻ります。

したがって、上の図の関数の処理に入ると、2番目のパラメータの変化が見られます。この関数の具体的な論理は分析されず、ここで2番目の段落の<の内容が戻ることを知っているだけでいいです。

しかし、ここのSstragePathFromaUrlの呼び出しは直接0に戻りますので、一回だけ入ります。私たちの外層からのSstragePathFroomUrlの呼び出しをここに分析した。

(1)解析完了プログラムでの脆弱性のある関数の呼び出しフレームの後、SStorragePathFromarlの最初の関数ScripAndCheckHttpPrfixを分析する必要があります。

プログラムは、ScripAndCheckHttpPrefix(これらの関数の呼び出し方式はすべてfastcalであり、前の2つのパラメータはいずれもecx、edxによって伝えられていることに注意して)で呼び出されます。httpext!CEcbBaseImpl<IEcb>:CchUrlefixWはunicodeバージョンのhttp:/の文字数を返して、http:/とPOCのIf:<を開始とする>を比較することによって、最後の文字列となります。

次に一致を満たすなら、httpextを呼び出します。CEcbBaseImpl<IEcb>:CchGetServerNameW、次にhttp:/後の最初の文字から始まる内容がhttpヘッダのhostフィールドと一致するかどうかを比較します。一致すれば直接0に戻り、この内部関数についてはここで分析しておきます。

(2)SstragePathFroomUrlに戻ると、戻りに対応するstrポインタがhost後の最初の/に修正され、ここが/のasciiコードと一致するかどうかを先に判断します。次に、urlのunicodeバージョンの文字数をすぐに得ます。以前の分析によると、ここで初めて得たのは0 x 97です。

(3)IEcbBase:ScreqMapUrlToPathExにより、仮想ディレクトリから真の経路への変換が完了する。戻るとパラメータは以下のようになります。

(4)HrCheckIfHeaderがSStorragePathFromaUrlを呼び出したとき、一連のqmemcpyの呼び出しに入りました。つまり、ここのecx制御長です。esiはこの物理経路において、ediはあるスタック内の位置を指します。

この関数の最後のところのqmemcpy(&v 35[v 22],v 29,2*v 28+2);0 x 4 cのダブルワードのコピーが完成します。IDAによって、ここのコピーアドレスはv 35で決定されており、v 35は伝達パラメータa 3から発生していることが分かる。これを観察したいです。a 3はどこから来たのですか?これはHrCheckIfHeaderにおけるstr変数に対応する。Push dword ptr[ebp-21 ch]を通じて伝達を完了しました。

その対応する位置は0 xfff 90 c(ebp-328 h)の位置に0 xfff 804(ebp-430 h)が格納されており、両者はいずれもスタック内のアドレス空間であり、IDAによるローカル変数v 28は104 h(260)の長さしかない。POCによると、今回のQmemcpyは0 xfff 804から0 xfff 958の位置をカバーし、対応する0 xfff 90 cの位置は0 x 680312 c 0に上書きされます。このカバーし始めたスタックアドレスはHrCheckIfHeader関数の中にあり、この関数はGS(securitycookie)保護を持っていますが、その保存方法は一般関数とは異なりEHuprologsなどで具体的な配置が見られます。

WinDBGでHrCheckIfHeaderを取得した場合、secuirty cookieの大体の位置は以下の通りです。

私たちが一番高い位置にカバーしているのがfff 958 hですので、この時はsecuritycookieに影響を与えずに検査を避けました。

(5)前に第一のスタックオーバーフロー時の状況を説明しましたが、今はPszNext Tokenを通じて第二のサイクルに入る場合(同じHrCheckIfHeader関数の中にあります。ですから、前のカバーのfff 90 chは0 x 680312 cのヒープアドレスです。)、つまり第二のセグメントです。そこで、ここにSstorragePathFroomUrlに入るqmemcpyは0 x 680312 c 0のアドレスをコピーします。この住所はいったいどの区域のメモリアドレスですか?

WinDBGに入力してみます!addressこのアドレスは、このエリアがrsaenh.dllモジュールのアドレスです。

現在はこの0 x 680312 c 0がどのように使用されているかは確認できませんが、SstragePathFroomUrlが呼び出された後も何度も呼び出されていますので、そこの状況を分析し続けています。

(6)観察したところ、SstragePathFroomUrlの呼び出しが何回かありました。これを手がかりに、スタックの呼び出しがHrCheckIfHeaderから来ていないことが分かりました。

その調整はCPropFindRequestから使用されます。Execute->FGet LockHandle->CParseLockTokenHeader:hrGet LockIdForPath。我々は、SstragePathFroomUrlがスタックオーバーフローの問題があることを知っています。ここで起動したコールを見てみます。デバッグ時に確認されたコピー元アドレスと宛先アドレスは以下の通りです。つまり0 xfffab 4と0 xfff 500のところです。

0 xfff 500はスタックアドレスですので、どの層の関数の局所変数なのかを確認したいです。私たちはr ebpを入力して0 xfff 93 cとして確認しました。ですから、現在の関数の範囲ではなく、WinDBGでptを入力して、それを実行してCParseLockTokenHeaderに戻らせます。ebpは0 xfffbd 0であることがわかったので、この関数の中にあるはずです。前の関数に戻り続けます。ここで異常が発生しましたので、shellcodeはもう実行されました。

これらの変数がカバーされています。0 xfffbd 0-0 xfffab 4=0 x 11 cに位置しています。ida逆コンパイルのコードの中で何に対応しているかを確認してください。

今はIDAもはっきりしていますが、v 29はカバーされた先頭です。このオーバーフローの範囲は0 xfffab 4-0 xfffc 07で、実際にはCParseLockTokenHeaderを超えました:HrGet LockIdForPathからFGet LockHandleの2つの関数体、つまりCParseLockTokenHeader:HrGetLockIdForPathのv 29からv 32まで全部カバーされています。

しかし、他の情報はありませんでした。どこでshellcodeを実行してプロセスの終了を招いたかを見ることにしました。実は毎回のf 10とf 11の試みです。一歩一歩ずつCParseLockToken Headerであることを発見しました。

0 x 680313 c 0を対象アドレスとして虚関数テーブルを取り出し、9番目の索引の虚関数ポインタにアクセスして実行します。0 x 680313 c 0という住所を見ましたので、どの位置がこの値に覆われているのかを調べてみます。

私たちは0 xfffbd 8と0 xfffベスト8でこの値を見ました。ebpはCParseLockTokenHeaderで覚えています。この二つのアドレスがカバーされているアドレスはebpのアドレスの近くにあります。0 xfffbd 8-0 xfff be7は関数着信パラメータであり、0 xfff be 8は最初にFGetLockHandleのV 7変数であり、IDAのビューを参照してください。

v 7はCParseLockToken Header変数であることが観測され、彼を格納するスタックアドレスが内部関数に伝達された。CMethUtil:SstragePathFroomUrl(*(CMethUtil*)v 11,v 28,Str,&v 26)中v 11は、前述のスタックアドレスを間接的にアドレス指定すると、0 x 680313 c 0がパラメータとして入ってきます。すなわち、以前カバーしていたヒープアドレス範囲内で、前回の分析に戻り、最終的にはScripAndCheckHttpPrfixが前述の虚数関数を呼び出したときに、Shellcodeの実行を開始します。

闘象科学技術能力センター-TCCグループ

スキャンコードは、ホールボックスに注目します。↓↓