stack-buffer-overflow

具体例1: 確保した領域を超えた代入でのエラー

レポート結果

ログからわかること

・対象のプロセスIDは 26670
・アドレス 0x7ffee6d7d984 において、stack-buffer-overflow を検出した
・PCレジスタが 0x000108ed9d00, BPレジスタが 0x7ffee6d7d950, SPレジスタが 0x7ffee6d7d0f0 の状態だった

・スレッドT0(メインスレッドのこと)で発生
・5バイトの書き込みをしようとした時にアドレス0x7ffee6d7d984が違反した事を検知した
(※0x7ffee6d7d984からの5バイトの書き込みという意味ではない)
・test31.cpp の 7行目から呼び出された strcpy で発生(※コンパイラが自動的に strcpyの代わりに wrap_strcpy を呼び出す処理に書き換えていた)
・アドレス 0x7ffee6d7d984 は、test31.cppの3行目で確保された、スレッドT0におけるこのフレームのスタック領域での36バイト目にあたる
・このスレッドのこのフレームでは4行目で宣言された’buffer’という領域がオフセット32以上、36未満の範囲で宣言されている。
・オフセット36ということは’buffer’という変数の領域を超えたメモリアクセスである。

SUMMARY 以降】
・違反になったアドレスより前の領域はアクセス不能なスタック領域(f1)として32(8*4)バイト分設定されている
・違反になったアドレスは4バイトだけアクセスが許可されている領域(04)として設定されている
・違反になったアドレスより後の領域はアクセス不能なスタック領域(f3)として24(8*3)バイト分設定されている

【ログから推測できる不具合の内容】

・確保すべきバッファのサイズが小さい(確保サイズを間違えている)
・格納する内容が大きい(格納サイズを間違えている)
・先頭アドレスの計算を間違えている(オフセット計算)

参考)上記のログを発生させたソースコード

#include <string.h>

int main(int argc, char *argv[]) {
  char buffer[4];

  // スタック領域にある4バイト分の領域に、4文字+終端文字の5バイト格納
  strcpy(buffer, "ABCD");

  return 0;
}

参考)コンパイル・実行例

$ clang++ -g -O0 -o test31 -fsanitize=address test31.cpp
$ ./test31

具体例2: 宣言した型よりも大きな変数として参照した場合のエラー

レポート結果

ログからわかること

・対象のプロセスIDは 26838
・アドレス 0x7ffee64f1960 において、stack-buffer-overflow を検出した
・PCレジスタが 0x00010970ee5d, BPレジスタが 0x7ffee64f1930, SPレジスタが 0x7ffee64f1928 の状態だった

・スレッドT0(メインスレッドのこと)で発生
・4バイトの読み込みをしようとした時にアドレス0x7ffee64f1960が違反した事を検知している

・test32.cpp の 9行目から呼び出された処理で発生
・アドレス 0x7ffee64f1960 は、test32.cppの2行目で確保された、スレッドT0におけるこのフレームのスタック領域での32バイト目にあたる
・このスレッドのこのフレームでは3行目で宣言された’shortValue’という領域がオフセット32以上、34未満の範囲で宣言されている。
・オフセット32ということは’buffer’という変数の領域を超えたメモリアクセスである。
※実際に違反が起きているアドレスは 0x7ffee64f1962 のハズだが、0x7ffee64f1960から 4バイト取得する命令で違反になったことで、アドレスを誤認していると思われる。

SUMMARY 以降】
・違反になったアドレスより前の領域はアクセス不能なスタック領域(f1)として32(8*4)バイト分設定されている
・違反になったアドレスは2バイトだけアクセスが許可されている領域(02)として設定されている
・違反になったアドレスより後の領域はアクセス不能なスタック領域(f3)として24(8*3)バイト分設定されている

【ログから推測できる不具合の内容】

・確保すべきバッファのサイズが小さい(確保サイズを間違えている)
・格納する内容が大きい(格納サイズを間違えている)
・先頭アドレスの計算を間違えている(オフセット計算)

参考)上記のログを発生させたソースコード


int main(int argc, char *argv[]) {
  short shortValue = 123;

  // 2バイト分確保したスタック領域へのポインタ
  void* ptr = &amp;shortValue;

  // ざわと4バイト分として参照する
  int value = *(int*)ptr;

  return 0;
}

参考)コンパイル・実行例

$ clang++ -g -O0 -o test32 -fsanitize=address test32.cpp
$ ./test32

コメントを残す

メールアドレスが公開されることはありません。