初めに
seccamp’24 Cコース(脅威解析クラス)の応募課題の答案さらしです.
本記事の内容には 明確な誤り を含みます. すなわち、誤っていてもセキュキャンは意欲があれば通してくれるということと考えられます.←ほんまか?
したがって、引用として利用されても十分な正当性は担保されませんので、お控えください. また、何かあればいつでも質問してください.twitterのDMにどうぞ.
問1
プライベートな内容を含むため省略
問2(2000文字以内)
一番最近解析したC言語のrandomの仕様について説明します.この課題では,私が調査したglibcのRNGの仕様について調査し,そのexploitも含めて説明します.
ユーザが乱数を生成する時,srandでseedを割り付け,randで乱数を生成します.このsrandとrandの使用について説明します.また,srandomとrandomについても説明します. randomは,全体として内部状態を保持します.内部状態は,struct random_data unsafe_stateという構造体で管理されます.構造体は,TYPE, DEG, SEP, rand_type, rand_deg, rand_sep, fptr, rptr, state, end_ptrのメンバを持っています. srand/srandomは,seedを受け取り,内部状態を初期化します.このとき,initstate函数が呼び出されます. initstateは,unsafe_stateの構造体の情報を確認し,その構造体の大きさに基づいて乱数テーブルを初期化します.乱数テーブルは,randtblという配列で管理されます.randtblの大きさに基づいてTYPEというものが決定されます.TYPEは,TYPE0からTYPE4までの5種類が存在します.デフォルトでは,TYPE3が選択されます.TYPE3の場合,randtblの大きさは31です. rand/randomは,内部状態に基づいて乱数を生成するRNGとして作用します.randtblの初期値はTYPE3の場合ハードコーディングされていて,srand/srandomを呼ばないときは毎回同じテーブルが生成される理由です.seedを与えると,乱数テーブルが生成されます.
TYPE0は,線形合同法が用いられています.線形合同法は,X_{n+1} = A*X_n + B mod Mという式で表されます.ここで,A, B, Mは定数です. デフォルトでは,A=1103515245, B=12345, M=0x7fffffffが設定されています.
TYPE_0のRNGは非常にサイクルが早く貧弱です.後述しますが,ハードコーディングされている初期値が極めて貧弱ですが,値が空間上に均等に配置される利点もあります.0x7fffffffという数字は INT_MAXです.INT_MAXの範囲で値を取り出すことで,正負の値に関わらず正しい正の値が得られます.これはC言語の仕様で,unsignedの値をsignedに変換した時に,この範囲に収まっているとき2の補数表現によって正しい値が得られるためです.
TYPE1~4では,線形加算帰還法が用いられています.線形加算帰還法は,X_{n+1} = X_{n-size} + X_{n-sep} mod Mという式で表されますが,初期値の与え方は以下です.ただし,戦術と同じ理由でX_n >> 1です. X_0 := [seed]\ X_{n+1} := AX_{n} (mod M), n∈[0,size-1] X_{n+1} := X_{n-size}, n∈[size, size+sep-1] X_{n} := X_{n-size} + X_{n-sep} (mod M) n∈[size+sep,)
TYPE1~4のそれぞれのタイプの違いは、主に内部で保持される状態の数です.
TYPE | 状態数 |
---|---|
1 | 7 |
2 | 15 |
3 | 31 |
4 | 63 |
TYPE_3においては初期値がハードコーディングされている.srandにseedを与えるとX_{size}までのrandtblを生成します. ここで,rand函数のTYPE0のRNGについてexploitを考えました.
int32_t state =0;
int32_t random() {
int32_t val = ((state * 1103515245U) + 12345U) & 0x7fffffff;
state = val;
return val;
}
rand函数のTYPE0の初期値では,先述の通り空間上に均等に配置されていますが,この生成周期が極めて短く予測が可能です.まず,seedの値にかかわらずstateの最小ビットの周期は2で,0->1->0->1となります.続いて,stateの最小ビットの周期は4で,0->1->2->3->0->1->2->3となります.しかもstateの周期は2^8という予測攻撃があります.
問3(2000文字以内)
プライベートな事項を含むため省略
問4(2000文字以内)
脆弱性,エクスプロイトに関連して,「2015 IEEE Symposium on Security and Privacy (SP) Counterfeit Object-oriented Programming: On the Difficulty of Preventing Code Reuse Attacks in C++ Applications」にて発表されたCounterfeit Object-oriented Programmingという攻撃手法について記述する. Counterfeit Object-oriented Programming(以下COOP)とは,オブジェクト指向プログラミングの機能を悪用して,悪意あるコードを実行する攻撃手法である.この攻撃手法を記述する理由は,私が初めて知ったときに言語の潜在的な脆弱性に驚いたからである.今までCTFを通じて,様々な脆弱性に関する知識を得てきたが,このvtableの脆弱性は初めて知った言語構造に関する脆弱性であった.例えばJOP・ROPチェーンやBOFは,プログラムの実行フローを制御するための技術であるが,これはCPUの持つ命令セットの特性を悪用している.一方で,vtableの脆弱性は,C++言語の特有の機能であるオブジェクト指向プログラミングの機能を悪用する. vtableは,仮想函数と継承をうまく処理するための仕組みである.C++言語に固有の仮想函数という機能があり,派生クラスで基底クラスの函数をオーバーライドする際に使われる動的ポリモーフィズムを実現するための仕組みである.あるオブジェクトから呼び出す函数が派生クラスか基底クラスの函数かを判断するために参照する,仮想函数のアドレスを保持するテーブルである.オブジェクトの中に普通のメンバーと同じようにメンバ函数群を格納したテーブルを指すポインタを保持し,そのテーブルのアドレスを指すポインタがvtableを指す.vtableは,仮想函数のアドレスを保持しているため,オブジェクトのアドレスを知っていれば,仮想函数のアドレスを取得することができ,それを用いてその函数を呼び出すことができる.同時に,このvtableは,オブジェクトの中にアドレスが格納されているため,オブジェクトのアドレスを知っていれば,vtableのアドレスを取得することができる.したがって,vtableの中身を書き換えることができれば仮想函数のアドレス,すなわち任意の函数を呼び出すことができる.これがCOOPの攻撃手法である. この攻撃手法の偉大な点は,バイナリまで落ちてきたプログラムのうち,C++というコンパイル前の言語の持つセマンティクスデザインを悪用している点である.今まで私が見てきたバイナリの脆弱性は,プログラムの実行フローを制御するための技術であるが,C++のvtableの脆弱性は,プログラムの構造を悪用している.プログラムが潜在的に持つ函数ポインタを書き換えることで,任意の函数を呼び出すことができるというのは非常に強力な攻撃であるが,COOPではある言語の文法や構造という非常に狭いものが引き起こすという大きな影響力を持つ. これを解決する方法の一例として,VTrustがある.VTrustではソースコードを参照しながら,呼び出せる函数を制限する.仮想函数呼び出し時に,呼び出せる仮想函数を継承関係があるクラスのみに制限する.さらに引数の数が一致している函数に制限している.ソースコードを用いて解析する利点として,引数の数やC++におけるクラスがはっきりとわかるというのがある.しかし,短所としてソースコードが入手できない,例えばOSSではない商用アプリケーションやライブラリの場合CFIをすることができなくなる. ソースコードを用いない例として,TypeArmorがある.TypeArmorでは,呼び出し元でセットした引数の個数と呼び出された函数で使われた引数の数を比較することによって実現している.C++のクラスでは一般の函数とは構造が異なりthisポインタが引数として渡されるため,引数とその構造を外部の函数と揃えることが難しいことを用いる.
この問題を解決するための手法として,CPUレベルでの対策を提案する.最近のCPUでは非常に高性能な演算が可能であるが,特定のセマンティクスデザインのプログラムの実行フローの制御に回してもよいのではないかと考えた.例えば,現代のプログラムでは最終的には一般に膾炙するコンパイラを用いて機械語バイナリを生成して実行する.コンパイラ群とそのバイナリを実行するCPUの間に,特定のセマンティクスデザインのプログラムの実行フローの制御に関する情報をやり取りするためのプロトコルを設けることができるのではないかと考えた.
問5
問5-1
TCP通信では,three way handshakeという手順で通信を確立する.
- クライアントがサーバにSYNパケットを送信
- サーバがSYN/ACKパケットを返信
- クライアントがACKパケットを返信 という順序で通信を確立する. このうち,1, 2のみを行いRSTを送り返すことで通信を確立しないのがTCP SYNスキャン,1,2,3全てを行いRSTを送り返し通信を全うできることを確認するのがTCP connectionスキャンである.
TCP SYNスキャンは,通信を確立しないため,サーバに負荷をかけずにポートスキャンを行うことができる. このとき,接続が確立しないため本体のOSにはログが残らない.サーバーソフトウェアにもログが残らないため,TCP Connectionスキャンに比べて検出されにくいスキャン方法である. TCP connectionスキャンは,通信が送信可能か,ポートが開いているかどうかだけでなく,接続が確立できるかどうかも判断できることできる.このとき,接続が確立できない場合,ポートが閉じていると判断する.
TCP SYNスキャンは通信を確立しないため,TCP Connectionスキャンに比べて高速にポートスキャンを行うことができる. 一方で,TCP SYNスキャンを遂行するためにはSYNを送信,SYN/ACKを受信,RSTを送信という3つの通信を行う必要がある.この際,LinuxシステムやWindowsシステムでは,SYNを送信するためにはroot権限が必要である.一般的なユーザー権限では,SYNを送信することができないため,TCP SYNスキャンを行うことができない. 検知可能性に関しては,TCP SYNスキャンは通信を確立しないため,サーバソフトウェアまで通信が届かず,ログが残らないため検知が難しい.一般的な進入検知システムでは,前段のFWや進入検知システムがTCP SYNスキャンを検知しない限り,検知することが難しい. 一方で,TCP connectionスキャンは通信を確立するため,サーバのソフトウェアにログが残るため検知が侵入検知システムとサーバーソフトウェアの2か所で可能である.どちらも検知が難しいが,TCP connectionスキャンの方が検知が簡単である.
問5-2
高速なポートスキャンを行うと,ネットワークに負荷がかかり,ネットワークの通信が遅くなる可能性がある.インターネットに比べて,社内ネットワークや学内ネットワークは,帯域幅が限られているためである. 例えば,社内ネットワークに対して高速なポートスキャンを行うと,社内ネットワークの通信が遅くなり,社内ネットワークの利用者に影響が出る可能性がある.これは,ネットワークには帯域幅が限られているため,ポートスキャンによる通信が他の通信を圧迫するためである.例えば私の持っているSR-S324TL1のスイッチは,1Gbpsの帯域幅を持っているため,1Gbpsを超える通信が発生すると,通信が遅くなる可能性がある.このため,高速なポートスキャンを行う場合は,ネットワークの帯域幅を考慮して,通信の負荷をかけないように配慮する必要がある.
問6
問6-1
初めに,渡されたファイルが何かを確認するためにfileコマンドを使用します.
image.dd: DOS/MBR boot sector; partition 1 : ID=0xee, start-CHS (0x0,0,2), end-CHS (0x3ff,255,63), startsector 1, 2097151 sectors, extended partition table (last)
ディスクイメージであることが確認できました.DOSとありますが,MBRのパーティションテーブルがあり,パーティション1は0xee
となっています.0xeeはGPTパーティションを示すため,GPTパーティションテーブルがあることがわかります.
次に,このディスクイメージのパーティションテーブルを確認します.パーティションテーブルを確認するために,gdiskコマンドを使用します.
Disk image.dd: 2097152 sectors, 1024.0 MiB
Sector size (logical): 512 bytes
Disk identifier (GUID): E83A394F-0BFE-47F9-9837-763DF6404F58
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 2097118
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 2095103 1022.0 MiB 8300 Q1Q2
gdiskコマンドでパーティションテーブルを確認すると,パーティション1が2048から2095103までの1022.0MiBであることがわかります.また,パーティション1のコードは8300で,名前はQ1Q2となっています.セクターサイズは512バイトでした.
次に,このディスクイメージの概略を確認します.概略を確認するために,odを使用します odコマンドで眺めていると,0000650バイト付近にUEFI PARTという文字列があります.UEFI PARTという文字列は,GPTパーティションテーブルのシグネチャであることがわかります.よって,GPTパーティションテーブルが実際にあることが確認できます.
続いて,4002200バイト付近に/mnt/q1q2
という文字列があります.この文字列から,Linuxのファイルシステムがあることがわかります.ファイルシステムの種類は不明ですが,Linuxのファイルシステムがあることがわかりました.決め打ちでext4と仮定して,調査を続行します.
調査の初めに,このディスクイメージにはGPTパーティションテーブルがあることがわかりました.GPTパーティションテーブルは,ファイルシステムを示す情報を持っています.これらの情報がノイズになっている可能性があるため,ファイルシステムの情報以外は破損していないと仮定して,ファイルシステムの情報を探します.
sudo losetup -P --show -f image.dd
sudo mount /dev/loop0p1 mnt
として,ディスクイメージをマウントします. しかし,マウントに失敗しました.よって,ファイルシステムが破損している可能性が高いです.
パーティションの情報だけを取り出すために,ddコマンドを使用します.
dd if=/dev/loop0p1 of=partition1.img
file partition1.img
として,ファイルの種類を確認します.
partition1.img: data
ファイルの種類がdataとなっているため,ファイルシステムが破損している可能性が高いです. また,fileコマンドではファイルの中身は確認せず,ファイルのマジックナンバーを確認します.このため,マジックナンバーが破損している可能性があります. partition1.imgの中身を確認するために,再びodコマンドを使用します.
od -w 64 -A x -t x1z partition1.img | less
として,partition1.imgの中身を確認します.
ext4のファイルシステムの構造は知らなかったので,調査を行いました.
https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Layout
これを全てに当てはめるのは難しいので,まずはスーパーブロックを探します. スーパーブロックはファイルシステムの先頭1024バイト目からあり,ファイルシステムの構造を示す情報が書かれています. ファイルシステムの先頭1024バイト目まではMBRの情報が書かれているため未使用領域になっていて,実際にNULLで埋められていることがわかりました.
000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................................<
*
000400 80 ff 00 00 00 fe 03 00 19 33 00 00 85 d8 03 00 6c ff 00 00 00 00 00 00 02 00 00 00 02 00 00 00 >.........3......l...............<
000420 00 80 00 00 00 80 00 00 f0 1f 00 00 55 1a 4a 66 55 1a 4a 66 02 00 ff ff 00 00 01 00 01 00 00 00 >............U.JfU.Jf............<
000440 5e c4 ee 65 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 0b 00 00 00 00 01 00 00 3c 00 00 00 >^..e........................<...<
000460 c6 02 00 00 6b 04 00 00 f0 06 1a 84 ff c3 41 b1 93 20 0d e0 8c 89 50 9f 00 00 00 00 00 00 00 00 >....k.........A.. ....P.........<
000480 00 00 00 00 00 00 00 00 2f 6d 6e 74 2f 71 31 71 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >......../mnt/q1q2...............<
ext4のマジックナンバーは0xEF53で,スーパーブロックの0x38バイト目にビッグエンディアンであることが記載されていますが,矛盾しています.試しに,0x38バイト目の値を0xEF53に変更して,ファイルシステムをマウントしてみます. sudo mount partition1.img mnt として,ファイルシステムをマウントしたところ,マウントに成功しました.マウントできなかった理由は,スーパーブロックの情報が破損していたためでした.スーパーブロックの情報が破損している場合,ファイルシステムを展開することができないため,マウントに失敗します.特に,マジックナンバーが破損している場合はどのファイルシステムかもわからないため,マウントに失敗します.
問6-2
以上の調査から,ファイルシステムはext4であることがわかり,実際にファイルシステムをマウントすることができました.
問6-3
次に,ファイルシステムをマウントしたディレクトリに移動して,ファイルを確認します.
ls mnt/rootd/websites -li
ls: cannot access 'jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdf': Bad message
total 692
18 -rw-r--r-- 1 root root 344901 Mar 11 17:51 'Cyber Intelligence Center_ Services_ Cyber Security _ Deloitte Japan _ Tohmatsu.html'
19 -rw-r--r-- 1 root root 359057 Mar 11 17:51 'Deloitte Tohmatsu Cyber LLC _ Deloitte Japan.html'
? -????????? ? ? ? ? ? jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdf
lsの結果から,jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfが破損していることがわかりました.jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfのinode番号が不明なため,inode番号を復元する必要があります. 前後のファイルのinode番号が連番であることから,jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfのinode番号は20であると仮定します. 実際にinode番号が20であるか確認するために,findコマンドを使用します.
find -inum 20
./jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdf
実際にinode番号が20であることが確認できました. 続いてinode番号を復元するために,ディスクイメージの中身を詳しく調査します. 前述のページよりディレクトリの構造は以下のようになっています.
0x0 __le32 inode Number of the inode that this directory entry points to.
0x4 __le16 rec_len Length of this directory entry. Must be a multiple of 4.
0x6 __le16 name_len Length of the file name.
0x8 char name[EXT4_NAME_LEN] File name.
od -w 64 -A x -t x1z partition1.img | less
として,partition1.imgの中身を確認します.
jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfで検索すると,inodeテーブルの中に次のダンプのような情報があります.
100400a0 74 65 20 4a 61 70 61 6e 2e 68 74 6d 6c 00 00 00 14 00 00 00 44 0f 3c 01 6a 70 2d 63 72 2d 64 65 >te Japan.html.......D.<.jp-cr-de<
100400c0 6c 6f 69 74 74 65 2d 63 79 62 65 72 2d 74 72 65 6e 64 73 2d 61 6e 64 2d 69 6e 74 65 6c 6c 69 67 >loitte-cyber-trends-and-intellig<
100400e0 65 6e 63 65 2d 72 65 70 6f 72 74 2d 32 30 32 33 2e 70 64 66 00 00 00 00 00 00 00 00 00 00 00 00 >ence-report-2023.pdf............<
これを先述のディレクトリ構造と照らし合わせると,inode番号が0x14であることがわかります.inode番号が0x14であることから,jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfのinode番号は20であることがわかりました. すなわち,inode番号は間違っていないです. 続いて,生データを正しく示せているか確認するために,ファイルの中身を確認します.
8200000 48 65 72 65 20 69 73 20 6d 79 20 70 72 69 76 61 74 65 20 64 69 72 65 63 74 6f 72 79 0a 00 00 00 >Here is my private directory....<
8200020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................................<
*
8400000 25 50 44 46 2d 31 2e 36 0d 25 e2 e3 cf d3 0d 0a 33 31 30 39 20 30 20 6f 62 6a 0d 3c 3c 2f 46 69 >%PDF-1.6.%......3109 0 obj.<</Fi<
8400020 6c 74 65 72 2f 46 6c 61 74 65 44 65 63 6f 64 65 2f 46 69 72 73 74 20 34 32 2f 4c 65 6e 67 74 68 >lter/FlateDecode/First 42/Length<
8400040 20 31 37 35 2f 4e 20 35 2f 54 79 70 65 2f 4f 62 6a 53 74 6d 3e 3e 73 74 72 65 61 6d 0d 0a 68 de > 175/N 5/Type/ObjStm>>stream..h.<
8400060 94 90 cd 0a c2 30 10 84 5f 65 df 20 3f 9b cd 0f 94 5e 3c 7a 29 c5 9b 78 28 58 c4 8b 8a ad 07 df >.....0.._e. ?....^<z)..x(X......<
ファイル名から,jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfはPDFファイルであることがわかります.ダンプから,%PDF%という文字列があることがわかります.%PDF%はPDFファイルのヘッダーであるため,jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfはPDFファイルであることが確認できました. 同時に,このPDFの先頭アドレスが0x8400000で,ブロックサイズが4096バイトであることからブロック番号は8400であることがわかりました.
続いて,データブロックへのポインタを復元します.データブロックへのポインタは,inodeテーブルの中にあります.inode tableの中に次のダンプのような情報があります
092300 a4 81 00 00 58 f2 1b 00 76 c6 ee 65 76 c6 ee 65 >....X...v..ev..e<
092310 76 c6 ee 65 00 00 00 00 00 00 01 00 00 0e 00 00 >v..e............<
092320 00 00 08 00 01 00 00 00 0a f3 01 00 04 00 00 00 >................<
092330 00 00 00 00 00 00 00 00 c0 01 00 00 42 41 44 00 >............BAD.<
092340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >................<
先述のリンクからinodeテーブルの構造通りに復元すると以下のようになります.
eh_magic 0a f3
eh_entries 01 00
eh_max 04 00
eh_depth 00 00
eh_generation 00 00 00 00
ee_block 00 00 00 00
ee_len c0 01
ee_start_hi 00 00
ee_start_lo 42 41 44 00
ここで,ee_start_hiとee_start_loを結合すると,0x424144となりますが,これはPDFのブロック番号8400に一致しません. これを修復すると,
$ ls
'Cyber Intelligence Center_ Services_ Cyber Security _ Deloitte Japan _ Tohmatsu.html' jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdf
'Deloitte Tohmatsu Cyber LLC _ Deloitte Japan.html'
となり,jp-cr-deloitte-cyber-trends-and-intelligence-report-2023.pdfが復元されました.
問7
問7-1
私が今後より重要になると感じる技術は,機械学習を用いたふるまい検知技術です. 機械学習を用いたふるまい検知技術は機械学習を用いて対象ののふるまいを監視し,異常なふるまいを検知する技術です. 既存のアンチウィルスソフトウェアやマルウェア対策のソフトウェアでは,既知のジェネリックパターンを用いてマルウェアを検知する方法があります.ジェネリックパターンを用いたウィルス検知では未知のマルウェアに対しては対応できないことがあります. そこで,機械学習を用いたふるまい検知技術は,既知のマルウェアのふるまいを学習し,未知のマルウェアに対しても対応できるという特徴があります.機械学習を用いたふるまい検知は,プログラムのシステムコールやネットワークトラフィックなどのふるまいを監視し,そのウィルス的傾向を見てウィルスと検知します. 機械学習を用いたふるまい検知技術は,機械学習の学習データによって検知精度が変わるため,学習データの質が検知精度に影響します.また,機械学習を用いたふるまい検知技術は,機械学習の学習データによって検知精度が変わるため,学習データの質が検知精度に影響します.すなわち,亜種のマルウェアや未知のマルウェアに対しては検知精度が高くしめすことがわかります.
問7-2
この技術が脆弱になり得るのは,学習データの質が悪い場合です. 学習データの質が悪いと,検知精度が低くなります. すなわち,完全に未知のマルウェアに対しては検知精度が低くなる可能性があります. 例えば,spectreやmeltdownのような革新的な脆弱性を利用したマルウェアに対しては検知精度が低くなる可能性があります. 他にも,最近現れたCPUの負荷を利用したduty cycle attackや,電力消費を利用したpower side channel attackなどのマシン内部から検出しづらい新しい攻撃手法に対しては検知精度が低くなる可能性があります.
問7-3
その技術に対して攻撃することを考えたときに,思いつく障壁は,学習データの質を悪化させることです. 学習データの質を悪化させることで,検知精度を低くすることができますが,個人で学習データにインジェクトするほどの大量のデータを用意することは難しいです.個人でなくても,亜種のマルウェアや未知のマルウェアを大量に用意することは難しいです. その技術に対して攻撃することを考えたときに,思いつく障壁は,学習データの質を悪化させることです. 学習データの質を悪化させることで,検知精度を低くすることができますが,個人で学習データにインジェクトするほどの大量のデータを用意することは難しいです.個人でなくても,亜種のマルウェアや未知のマルウェアを大量に用意することは難しいです. また,あるエンドポイントの汚染などを考えうことができる.miraiボットネットがそうであるように,大量のエンドポイントから一定の場所へアクセスすることによって,さらにその場所を怪しく思わせるようなことができます.しかし,こうしたエンドポイントの2次汚染は,エンドポイントの管理者によって検知される可能性があります. そのため,エンドポイントの管理者によるエンドポイントの監視が重要です.
問8
与えられた実行ファイルについて、確かにstrcmpとstrncmpの結果が不自然であることを認めたので、初めに動的調査をした. gdbとともに実行したところ、以下のダンプが得られた.
Dump of assembler code for function main:
0x000007f0 <+0>: push %rbp
0x000007f1 <+1>: mov %rsp,%rbp
0x000007f4 <+4>: sub $0x10,%rsp
0x000007f8 <+8>: lea 0xf5(%rip),%rax # 0x8f4
0x000007ff <+15>: mov %rax,-0x10(%rbp)
0x00000803 <+19>: lea 0xfd(%rip),%rax # 0x907
0x0000080a <+26>: mov %rax,-0x8(%rbp)
0x0000080e <+30>: mov -0x8(%rbp),%rcx
0x00000812 <+34>: mov -0x10(%rbp),%rax
0x00000816 <+38>: mov $0xd,%edx
0x0000081b <+43>: mov %rcx,%rsi
0x0000081e <+46>: mov %rax,%rdi
0x00000821 <+49>: call 0x670 [strcmp@plt](mailto:strcmp@plt)
0x00000826 <+54>: test %eax,%eax
0x00000828 <+56>: jne 0x85d <main+109>
0x0000082a <+58>: mov -0x8(%rbp),%rdx
0x0000082e <+62>: mov -0x10(%rbp),%rax
0x00000832 <+66>: mov %rdx,%rsi
0x00000835 <+69>: mov %rax,%rdi
0x00000838 <+72>: call 0x6a0 [strncmp@plt](mailto:strncmp@plt)
0x0000083d <+77>: test %eax,%eax
0x0000083f <+79>: jne 0x84f <main+95>
0x00000841 <+81>: lea 0xd1(%rip),%rdi # 0x919
0x00000848 <+88>: call 0x680 [puts@plt](mailto:puts@plt)
0x0000084d <+93>: jmp 0x869 <main+121>
0x0000084f <+95>: lea 0xc9(%rip),%rdi # 0x91f
0x00000856 <+102>: call 0x680 [puts@plt](mailto:puts@plt)
0x0000085b <+107>: jmp 0x869 <main+121>
0x0000085d <+109>: lea 0xd5(%rip),%rdi # 0x939
0x00000864 <+116>: call 0x680 [puts@plt](mailto:puts@plt)
0x00000869 <+121>: mov $0x0,%eax
0x0000086e <+126>: leave
0x0000086f <+127>: ret
End of assembler dump.
(gdb) disass strcmp
Dump of assembler code for function strcmp@plt:
0x00000670 <+0>: jmp *0x2009a2(%rip) # 0x201018 [[email protected]](mailto:[email protected])
0x00000676 <+6>: push $0x0
0x0000067b <+11>: jmp 0x660
End of assembler dump.
pltセクターに置いて不自然なpush命令があることがわかった.pltセクターは、共有ライブラリの関数を呼び出すためのセクターであるはずが、このセクターにpush命令があることはおかしい. strcmp関数を呼び出すためのJMP命令の直後にpush 0命令があることから、strcmp関数の戻り値を取得するための処理がおかしいことがわかった. 同様にして、strncmp関数を呼び出すためのJMP命令の直後にpush 3命令があることから、strncmp関数の戻り値を取得するための処理がおかしいことがわかった.