寒い

寒いですねぇ。 仕事の調子も悪く、それも寒い感じ。なんでかなぁ。

いまのチームに移ってから2週間少々。 かなり合わないんですが、そのうち慣れるんですかねぇ。

SIGSEGVの実験

突然ですが、アドレス指定による変数攻撃の実験をしてみました。 当たり前のことばかりですが、 実際に目で見るのもいいだろうということで。

実験1 (違うプロセス)

main.c として書きます。

#include <stdio.h>
#include <unistd.h>

int main()
{
  char p[] = "abcdefg";

  while (1) {
    printf("pointer of p = %x, p = %s\n", &p, p);
    sleep(5);
  }

  return 0;
}

実行すると次のようになります。

sugimura@ml110 ~/work/C $ gcc -g -o main main.c
sugimura@ml110 ~/work/C $ ./main
pointer of p = bfffc44c, p = abcdefg
pointer of p = bfffc44c, p = abcdefg
pointer of p = bfffc44c, p = abcdefg
...

このアドレスに対して、直接の変数書き換えを試みます。 上のプログラムを実行したまま、 attack.c として書いてみます。

#include <stdio.h>
#include <string.h>

int main()
{
  char *q = (char *) 0xbf9bc60c;

  *q = 'z';
  *(q+1) = 'z';
  *(q+2) = 'z';
  *(q+3) = 'z';
  printf("pointer of q = %x, q = %d\n", &q, q);

  return 0;
}

別ターミナルで実行してみます。

sugimura@ml110 ~/work/C $ gcc -g -o attack attack.c
sugimura@ml110 ~/work/C $ ./attack 
セグメンテーション違反です

落ちました。GDB で追います。

sugimura@ml110 ~/work/C $ gdb ./attack
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run
Starting program: /home/sugimura/work/C/attack 
Failed to read a valid object file image from memory.

Program received signal SIGSEGV, Segmentation fault.
0x080483b3 in main () at attack.c:7
8         *q = 'z';
(gdb) p q
$1 = 0xbfffc44c <Address 0xbfffc44c out of bounds>
(gdb) p *q
Cannot access memory at address 0xbfffc44c

アクセスできません。アドレスがわかっていても、他のプロセスは書き換えられないということです。

実験2 (同じプロセス)

main2.c として書きます。

#include <stdio.h>
#include <unistd.h>
#include <string.h>

void attack(char *);

int main()
{
  char p[] = "abcdefg";

  printf("pointer of p = %x, p = %s\n", &p, p);

  *(p+7) = 'z';
  *(p+8) = 'z';
  *(p+9) = 'z';
  printf("pointer of p = %x, p = %s\n", &p, p);

  return 0;
}

実行すると落ちます。 典型的なバッファオーバーフローですね。 メモリが破壊されていることもわかります。

sugimura@ml110 ~/work/C $ gcc -g -o main2 main2.c
sugimura@ml110 ~/work/C $ ./main2
pointer of p = bf9d761c, p = abcdefg
pointer of p = bf9d761c, p = abcdefgzzzv燭澤鷏
                                             v燭澤
セグメンテーション違反です

最後に、似たような例ですが異なる変数を破壊するものです。 main3.c として書きました。 あらかじめ p と q が格納されるアドレスの差を知っているものとします。

#include <stdio.h>
#include <unistd.h>
#include <string.h>

void attack(char *);

int main()
{
  char p[] = "abcdefg";
  char q[] = "12345678";

  printf("pointer of p = %x, p = %s\n", &p, p);
  printf("pointer of q = %x, q = %s\n", &q, q);

  *(q+7) = 'z';
  *(q+8) = 'z';
  *(q+9) = 'z';
  printf("pointer of p = %x, p = %s\n", &p, p);
  printf("pointer of q = %x, q = %s\n", &q, q);

  return 0;
}

正常終了はするものの、中身は書き換えられてしまっています。

sugimura@ml110 ~/work/C $ gcc -g -o main3 main3.c
sugimura@ml110 ~/work/C $ ./main3
pointer of p = bf956d9c, p = abcdefg
pointer of q = bf956d93, q = 12345678
pointer of p = bf956d9c, p = zbcdefg
pointer of q = bf956d93, q = 1234567zzzbcdefg

結論

他のプロセスからメモリを破壊することは出来ませんが、 同じプロセスならば破壊することができます。

そのとき必ずしも異常終了するとは限らず、 一見正常に動作していても意図しない結果になることがあるということですね。



トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-01-29 (土) 15:27:47