1月6日(木)3、4コマ目

今日、やったこと

バッファオーバーフローでリターンアドレス書き換え

今日のホワイトボード

プログラムを実行すると

コンパイルで出力された実行ファイル(実行命令のリスト)がメモリ上のコード領域にロードされ、命令が順番に実行される。

図 コード領域に実行ファイルがロードされる


関数を呼び出すと

コード領域にロードされた関数の命令リストへジャンプして関数を実行する。

関数実行後、呼び出し元に戻る。コード領域のどこに戻るかが、スタック上に書き込まれている。

このスタック領域の戻るべきアドレスをリターンアドレスと呼び、関数実行時に呼び出し元がスタック領域に書き込んでいる。

図 関数呼び出し時にスタック領域に書き込まれるデータ


サンプルプログラムを確認

main()関数からcheck()関数を呼び出すときのメモリの状態をデバッガで確認。

①コード領域のmain()関数をチェック

逆アセンブルすると、check()関数を呼び出す箇所がわかる。

図 main()を逆アセンブルした

callqでcheck()関数を呼び出し、0x00・・004007a5番地に戻ってくる。

この0x00・・004007a5番地をリターンアドレスとしてスタック上に書き込む。

図 メモリ上のイメージ


②リターンアドレスが書き込まれる位置を確認

ブレークポイントで一時停止して確認すると、pass_buffの先頭から40バイト離れたところにリターンアドレスが書き込まれている。

図 デバッガでメモリ確認

図 メモリのイメージ

③リターンアドレスを上書きする

このプログラムにはバッファオーバーフローの脆弱性があるため、リターンアドレスを上書きする。

上書きするアドレスはif()の条件成立時に実行するprintf()。

図 リターンアドレス書き換え済み


C言語は危険

strcpy()以外にもコピー先のサイズに関係なくコピーする関数がある。

上限バイト数が指定できる関数を利用すること。

get -> fgets

sprintf -> snprintf

strcat -> strncat

strcpy -> strncpy

vsprintf -> vsnprintf


サンプルプログラムを修正

strcpy()ではなく、strncpy()を使って文字列コピー。





このブログの人気の投稿

1月20日(木)3、4コマ目

1月13日(木)3、4コマ目