外壁2017-03-14ELFとELFローダについてROPというハッキング手法がある。これを勉強していたら、共有ライブラリがメモリ上のどこに配置されるのか、それはどのタイミングなのか気になり始めた。文献を漁ってぼんやりとしたことは分かってきたが、知識が定着したとは言えないので、自分の理解をより深めるため、知識を定着させるため以下に、ELF周りの話を記す。Format)ELFとは、実行可能バイナリやオブジェクトファイルなどのフォーマットを規定したもの。ELFフォーマットのファイルは、ELFヘッダが先頭にあり、プログラムヘッダテーブル及びセクションテーブルがその後にあります。これらのヘッダ構造はelf.hに記述されている。};ELFヘッダELFヘッダはELFファイルの先頭に必ず存在し、そのファイルがELFファイルであることを示す。ELFヘッダはelf->ehdrのことで以下のように定義されている。27プログラムヘッダプログラムヘッダテーブルはELFヘッダのe_phoffで指定されるオフセットから始まり、e_phentsizeとe_phnumで決まる大きさのテーブルからなります。e_phentsizeがテーブルの中のプログラムヘッダのサイズを表し、e_phnumがそのテーブルの中にいくつセッションヘッダがあるか示しています。ももいろテクノロジーを参照すると良い。INTERPとは動的リンクを実際に処理するインタプリタ(リンカ)のことである。http://lxr.free-electrons.com/source/fs/binfmt_elf.c?v=3.2#L559にELFファイルをメモリにロードする部分がある(多分)。型という、構造体の説明。これは、ユーザー空間にある引数をカーネル側で保持・加工する為のデータ構造らしい。};はじめに、ELFヘッダのサイズ分をmallocして、ELFヘッダを読み込み、各要素をチェックする。次に、全てのプログラムヘッダのサイズ分をmallocして、全てプログラムヘッダを読み込む。それを順にチェックしていき、p_type(セグメンタイプ)がINTERPの場合、その内容を読み取る。elf_interpreter="/lib64/ld-linux-x86-64.so.2"。ここでは、open_exec()した後、interpreterのBINPRM_BUF_SIZE分(128byte)をloc->interp_elf_exに代入。interpreterの情報。次にp_typeがPT_GNU_STACKセクションの場合、ELFヘッダのp_flagsをチェックしてスタック上でのコード実行の可否を決める。(ここはDEPと関わってくる)。次に、INTERPの妥当性(マジックナンバーと、アーキテクチャの適合性)をチェック。flush_old_exec()で現在のprogramの情報を消し、新しいprogramのための情報にcurrentの情報をいれかえていく。(プロセス、リンク、task_struct構造体)SET_PERSONALITY()で親のpersonalityを継承する。その後、currentの情報を更新していく。(ここはlinuxのプロセス管理のお話なので、いつか勉強したい)次はELFをmmapingする。p_typeがPT_LOADの場合にp_flagsを調べ、パーミッションを設定する。MAP_PRIVATEとe_typeがET_EXECであった場合ET_MAP_FIXEDをelf_flagsに設定。(https://linuxjm.osdn.jp/html/LDP_man-pages/man2/mmap.2.html/)共有オブジェクトならランダムフラグを見てアドレス計算。オフセットとか計算したら、elf_map(おそらく中身はmmap()、セマフォとかしてるし、後々解析する予定)する。mmap()した先のアドレス、セクションのサイズ等をチェックする。その後、ヒープセクション、bssセクションの調整?(よくわかっていない)load_elf_interp()でinterpreterを読み込む。operation等をチェック。e_phentsizeとe_phnumでサイズチェック。interpreterのサイズ分のメモリを確保して、kernel_read()する。その後、elf_map()で共有ライブラリをmappingする。その後、読み込んだアドレス等をチェック。current情報を更新。bprm->p)で先ほどのerrorがeipに設定される。この呼び出し元に戻ると、どうやらeipから実行するらしく、すなわち共有ライブラリが実行されることになる。感想OSのメモリマッピングの知識が欠けていたので、mmap()周辺が正しく解析できていない。よって、共有ライブラリの読み込み先アドレス等の計算が未だに分かっていないため、目的は達成できていない(参考文献読んだら理解できた)。メモリマッピングの勉強をしたら、また読んでみよう。kernelのソースコードを初めて読んだ。面白くて仕方なかった。特有のデータ構造や頻繁に使われる関数等を一々追っていたため、記事の内容もまとまらず、知識も断片的なものとなった。これから他のところを読んだ時に、今回の知識は役に立つのであろうか?もしそうでない場合は、また色々と追っているうちに闇に吸い込まれていくわけであるが、いつかは塵も積もり山となるであろう。21:29ELFとELFローダについてTweet広告を非表示にする関連記事2020-01-05【Python】ListとDequeのパフォーマンスの違い〜CPyhtonの実装を読んで〜先日以下のブログを読みました。(1)はてなブログをはじめよう!blue_9さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。