drop-stones / titech-sysdev-2020

システム開発プロジェクト応用第一
0 stars 0 forks source link

GDB #2

Open drop-stones opened 4 years ago

drop-stones commented 4 years ago

演習1: 自分のOSSプロダクトをUBサニタイザで検査してみよ

int main (int argc, char *argv []) { if (strcmp (argv [1], "foo")) printf ("foo!\n"); else printf ("Not foo...\n"); }


- 実行結果
  - 引数なしなのにargv[1]にアクセスしようとして、エラー!

$ ./a.out UndefinedBehaviorSanitizer:DEADLYSIGNAL ==42316==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7fff6f355850 bp 0x7ffee200c750 sp 0x7ffee200c750 T925157) ==42316==The signal is caused by a READ memory access. ==42316==Hint: address points to the zero page.

0 0x7fff6f355850 in _platform_strcmp+0x50 (libsystem_platform.dylib:x86_64+0x850)

#1 0x10dbf6f02 in main+0xb2 (a.out:x86_64+0x100003f02)
#2 0x7fff6f15fcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)

==42316==Register values: rax = 0x0000000000000000 rbx = 0x0000000000000000 rcx = 0x0000000000000000 rdx = 0x00007ffee200c701
rdi = 0x0000000000000000 rsi = 0x000000010dbf6f8d rbp = 0x00007ffee200c750 rsp = 0x00007ffee200c750
r8 = 0x0000000000000001 r9 = 0x0000000000000070 r10 = 0x000000010ffda420 r11 = 0x00007fff6f355800
r12 = 0x0000000000000000 r13 = 0x0000000000000000 r14 = 0x0000000000000000 r15 = 0x0000000000000000
UndefinedBehaviorSanitizer can not provide additional info. SUMMARY: UndefinedBehaviorSanitizer: SEGV (libsystem_platform.dylib:x86_64+0x850) in _platform_strcmp+0x50 ==42316==ABORTING zsh: abort ./a.out


- 検査対象2

include

include

include

int main (int argc, char *argv []) { if (argc < 2) { fprintf (stderr, "Usage: %s \n", argv [0]); exit (1); }

if (strcmp (argv [1], "foo")) printf ("foo!\n"); else printf ("Not foo...\n"); }


- 実行結果
  - 引数がない場合、if文で処理することで未定義動作を防いでみると、エラーがない。

$ ./a.out Usage: ./a.out $ ./a.out aa foo!


- サニタイズ前後のアセンブリコードの長さ比較
  - 5倍以上違う!!

$ clang -fsanitize=undefined -S -masm=intel -o crash_sanitized.s crash.c $ wc -l crash_sanitized.s 235 crash_sanitized.s $ clang -S -masm=intel -o crash.s crash.c $ wc -l crash.s 42 crash.s

drop-stones commented 4 years ago

演習2: 自分のOSSプロダクトに対し、GDBでブレークポイントを設定して変数値を確認せよ

Breakpoint 1, main () at break.c:13 13 f2 = fib; (gdb) p i $1 = 2 (gdb) p fib $2 = 2 (gdb) c Continuing.

Breakpoint 1, main () at break.c:13 13 f2 = fib; (gdb) p i $3 = 3 (gdb) p fib $4 = 3 (gdb) c Continuing.

Breakpoint 1, main () at break.c:13 13 f2 = fib; (gdb) p i $5 = 4 (gdb) p fib $6 = 5 ... (gdb) p i $7 = 8 (gdb) p fib $8 = 34

drop-stones commented 4 years ago

演習3: コアダンプを利用したデバッグを試せ

Breakpoint 1, main () at crash.c:6 6 arr [i] = 'a' + i; // buffer overflow (gdb) c ... (gdb) p arr[8] $7 = 105 'i' (gdb) c Continuing. stack smashing detected : terminated

Program received signal SIGABRT, Aborted. __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.


- objdumpしてみると、スタックオーバーフローを検知するコードが見つかった!!

$ objdump -M intel -d a.out ... 1155: 64 48 8b 04 25 28 00 mov rax,QWORD PTR fs:0x28 115c: 00 00 115e: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax ... 1191: 64 48 33 0c 25 28 00 xor rcx,QWORD PTR fs:0x28 1198: 00 00 119a: 74 05 je 11a1 <main+0x58> 119c: e8 af fe ff ff call 1050 __stack_chk_fail@plt

drop-stones commented 4 years ago

演習4: 自分のOSSプロダクトにint3命令を埋め込んでデバッグを実験せよ

int main() { printf ("debug1\n"); asm("int3"); printf("debug2\n"); printf("debug3\n"); }


- 実行結果
  - `Program received signal SIGTRAP, Trace/breakpoint trap.`
  - int3命令によるシグナルが捕捉されているのがわかる。

$ clang -g -o int3 int3.c $ gdb ./int3 ... (gdb) b int3.c:7 Breakpoint 1 at 0x40114a: file int3.c, line 7. (gdb) run Starting program: /home/shizuku/Documents/sysdev/gdb/int3 debug1

Program received signal SIGTRAP, Trace/breakpoint trap. main () at int3.c:7 7 printf("debug2\n"); (gdb) c Continuing.

Breakpoint 1, main () at int3.c:7 7 printf("debug2\n"); (gdb) c Continuing. debug2 debug3


- アセンブリコードを覗いてみると、int3命令がある(当然)

$ clang -S -masm=intel int3.c $ cat int3.s ... call printf

APP

int3
#NO_APP

...

drop-stones commented 4 years ago

演習5: 自分のOSSプロダクトの変数変化をウォッチポイントを用いて観察せよ

Temporary breakpoint 1, main () at break.c:5 5 sum = 0; (gdb) watch fib Hardware watchpoint 2: fib (gdb) c Continuing.

Hardware watchpoint 2: fib

Old value = -8048 New value = 1 0x000000000040114e in main () at break.c:8 8 f1 = f2 = fib = 1; (gdb) c Continuing.

Hardware watchpoint 2: fib

Old value = 1 New value = 2 main () at break.c:12 12 f1 = f2; (gdb) c Continuing.

Hardware watchpoint 2: fib

Old value = 2 New value = 3 main () at break.c:12 12 f1 = f2; ... (gdb) c Continuing.

Hardware watchpoint 2: fib

Old value = 8 New value = 13 main () at break.c:12 12 f1 = f2; (gdb) c Continuing.

Hardware watchpoint 2: fib

Old value = 13 New value = 21 main () at break.c:12 12 f1 = f2;

drop-stones commented 4 years ago

演習6: 自分のOSSプロダクトのデバッグを作業記録を取りながら行おう

drop-stones commented 4 years ago

First-Come First-Served アルゴリズムの実装

drop-stones commented 4 years ago

gdb-pedaの導入

gdb-pedaというものを友達に教えてもらったので導入してみた。 参考url

drop-stones commented 4 years ago

CにはないC++特有?のvtableをgdbで覗いてみる