FromNandの日記

自分的備忘録

【PEヘッダ】PEヘッダ解析における簡単な流れについて

大まかな流れは「https://tech.blog.aerie.jp/archive/category/Portable%20Executable」と「リバース・エンジニアリングバイブル」で確認してほしい。

中でも「https://tech.blog.aerie.jp/entry/2015/12/27/140649」」では、PEヘッダの流れが一望できる。

 

IMAGE_DOS_HEADERの中には「MZシグネチャ」と「IMAGE_NT_HEADERまでのオフセット」が入っている。


IMAGE_NT_HEADERには、「PEシグネチャ」と「IMAGE_FILE_HEADER」、「IMAGE_OPTIONAL_HEADER」が入っている。


IMAGE_FILE_HEADERには、そのファイルの属性(作成日・strippedかどうか・対象アーキテクチャ...)が記録されている。


IMAGE_OPTIONAL_HEADERには、ベースアドレス・セクションのアライメント・コードのサイズ・データのサイズといった重要な情報が格納されている。


IMAGE_OPTIONAL_HEADERの最後の要素は「IMAGE_DATA_DIRECTORY」という構造体が16個(IMAGE_NUMBEROF_DIRECROTY_ENTRIES)になっている。

 

IMAGE_SECTION_HEADERという、主に各セクションの名前・開始アドレス・サイズなどを管理する構造体があるのだが、これはIMAGE_OPTIONAL_HEADERの直後のアドレスに配置されている。


IMAGE_DATA_DIRECTORYには、エクスポート・インポート・リソース・IATといったディレクトリの仮想アドレスとサイズが格納されている。

【位置独立コード】PICやPIEについて

↓によると、PIE(position-independent executable)とは、PIC(position-independent code)だけから構成された実行形式のこと

https://ja.wikipedia.org/wiki/%E4%BD%8D%E7%BD%AE%E7%8B%AC%E7%AB%8B%E3%82%B3%E3%83%BC%E3%83%89

 

おそらく最もわかりやすいサイト↓

https://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

 

実際に位置独立の実行形式を作成する例が日本語で載っている

http://0xcc.net/blog/archives/000109.html

 

gccコンパイラオプションでは、「-fpic」は位置独立コード、「-fpie」は位置独立実行形式を作成するオプションである。

反対に「-fno-pic」や「-fno-pie」は位置依存コードを生成する。

「-fpic」と「-fPIC」の違いなどについてはよくわかったいない

【GAS】ENTER・LEAVE命令の使い方と同等コードの紹介

x86アセンブラ命令にENTER・LEAVEという物がある。

 

ENTERは2つのオペランドをとり、ENTER $0, $0などと使用する

LEAVEはアセンブリ関数の最後に記述することが多い

 

ENTER $0, $5は次のようなコードと同等である(ただし、ENTERは速度が遅い...)

push ebp
mov ebp, esp
sub esp, 5

 

LEAVEが行うことは、ENTERのほぼ逆である(こちらは遅くはないはず)

mov esp, ebp
pop ebp 

 

ENTERは遅いのでコンパイラもあまり使用しないらしい

割り込みの種類について

ハードウェア割り込み

周辺機器からの信号によって発生


トラップ

INT、INTO命令の実行によって発生(ソフトウェア割り込み)


フォールト

保護機能、MMU(メモリ管理ユニット)のチェックによって発生


アボート

処理を続けられないエラーが起きた場合に発生

 

【GAS】call・jmp命令のいろんな書き方【call *%eaxは?】

カーネルコードを書いていて詰まったのでまとめておきます

個人的によく使う「call・jmp」のうち、戸惑ったものを乗せます

レジスタに対して付ける「*」が非常に分かりづらいです(call *%eaxやcall *4(%esp)など)

https://stackoverflow.com/questions/21324087/what-c-code-would-compile-to-something-like-call-eax

 

【call】

「call %eax」

eaxに格納されているアドレスにジャンプする。

しかし、コードセグメントのベースアドレスを引いておくことを忘れないように!

(例えば、cs == 1で1番目のセグメントのベースが0x300000であれば、(コール先のアドレス - 0x300000)をeaxに入れておくべき)

「call *%eax」

書き方が違うだけで、上の記述と全く同じ意味(紛らわしい)

何度も実験したので正しいと思います。

あと、上に貼ったURLにもその事が書いてあります。

「call *0x????????」

0x????????に指定した番地に格納されている4byteの番地にジャンプします。

0x????????自体にジャンプするわけではないことに注意!!

コードセグメントやデータセグメントのベースやリミットを意識するべきです。

「call 0x????????」

0x????????にジャンプします。

「call 4(%esp)」もしくは「call *4(%esp)」

esp + 4の領域に存在するメモリの値を番地だと認識し、その番地へコールします。

他のレジスタも概ね使えると思います。

 

【jmp】

「jmp %eax」

eaxに格納されているアドレスにジャンプする。

しかし、コードセグメントのベースアドレスを引いておくことを忘れないように!

(例えば、cs == 1で1番目のセグメントのベースが0x300000であれば、(コール先のアドレス - 0x300000)をeaxに入れておくべき)

「jmp *%eax」

書き方が違うだけで、上の記述と全く同じ意味(紛らわしい)

何度も実験したので正しいと思います。

「jmp *0x????????」

0x????????に指定した番地に格納されている4byteの番地にジャンプします。

0x????????自体にジャンプするわけではないことに注意!!

コードセグメントやデータセグメントのベースやリミットを意識するべきです。

「jmp 0x????????」

0x????????にジャンプします。

「jmp 4(%esp)」もしくは「jmp *4(%esp)」

esp + 4の領域に存在するメモリの値を番地だと認識し、その番地へコールします。

他のレジスタも概ね使えると思います。

【QEMU On Windows】参考になるサイトをみつけたよ!

なんだか、役立ちそうなコマンドがたくさん↓

http://honmat.cocolog-nifty.com/txt/2009/02/qemu-on-windows.html

 

個人的には「qemu.exe -L . -m 32 -localtime -std-vga -fda fdimage0.bin」「qemu.exe -L . -m 32 -localtime -std-vga fdimage0.bin」の2つを使って、FDとUSB用のIPLからそれぞれ起動しています。

【VESA】VESAについてのまとまった資料

いつものようにosask.jp

http://oswiki.osask.jp/?VESA

 

0から作るOS開発(日本語)

http://softwaretechnique.jp/OS_Development/Tips/VESA/vbe01.html

 

海外のサイト(英語:中国語)

http://www.faqs.org/faqs/pc-hardware-faq/supervga-programming/

https://www.jianshu.com/p/f3a14b96d2a8 

↓ここが意外にもわかりやすい

https://blog.51cto.com/helloworld/69567