(gdb)가 붙은 것은 gdb 명령어임을 의미합니다. 실제로 명령어를 칠 때는 (gdb)를 빼고 입력합니다.$가 붙은 것은 shell 명령어임을 의미합니다.실제로 명령어를 칠 때는 $를 빼고 입력합니다.
GDB란 GNU DeBugger의 약자로 GNU 소프트웨어를 위한 기본 디버거라는 의미입니다.
GDB가 지원하는 언어는 다양합니다.
Ada, Assembly, C, C++, D, Fortran, Go, Objective-C, OpenCL, Modula-2, Pascal, Rust
한 줄이면 쉽게 설치할 수 있습니다.
sudo apt install gdb
gdb는 기본적으로 AT&T문법을 따릅니다. 하지만 intel 문법이 보기 좋기 때문에 intel 문법으로 변경하고 시작합니다.
(gdb) set disassembly-flavor intel
.gitconfig나 .bashrc처럼 gdb쉘이 시작할 때 자동으로 실행되는 initial script 파일이 있습니다. 경로는 ~/.gdbinit입니다.
따라서 위 명령어를 매번 입력하기 싫다면 다음 명령어를 입력하여 스크립트를 추가해줍니다.
$ echo set disassembly-flavor intel >> ~/.gdbinit
잘 적용되었는지 확인하려면 다음 명령어를 입력하면 됩니다.
(gdb) show disassembly-flavor
제 터미널 출력은 다음과 같습니다.
The disassembly flavor is "intel".
GDB를 시작하려면 바이너리명을 인수로 주면 됩니다.
$ gdb "binary_name"
GDB를 종료하려면
q를 입력하면 됩니다.(gdb) q
현재 터미널에서 실행하고 있는 프로그램이 있을 때
Ctrl+Z를 누르면 suspend가 되고bg명령어를 치면 background에서 실행시킬 수 있습니다.
ps를 입력하면 현재 실행 중인 process를 볼 수 있습니다.
break point를 주려면
break명령을 사용하면 됩니다.b라고만 해도 동작합니다.(gdb) b "function_name"Example
(gdb) b *mainBreakpoint 1 at 0x4005bd
특정 지점에 break point를 주려면
+"line_number"를 이어적으면 됩니다.(gdb) b "function_name"+"line_number"Example
(gdb) b *main+8Breakpoint 2 at 0x4005c5
b *main에 비해 8증가 된 주소값을 볼 수 있습니다.
또한 특정 주소를 이용하여 break point를 걸 수도 있습니다.
(gdb) b "address"Example
(gdb) b *0x00000000004005bdBreakpoint 3 at 0x4005bd
EIP, RIP를 알고 있다면 현재 주소에 상대적인 주소값을 이용하여 break point를 지정할 수도 있습니다.
(gdb) b -10
GDB에서 바이너리를 실행하려면 run을 입력하면 됩니다. 인수를 줄 수도 있습니다.
(gdb) run "arguments"
break point가 걸려 있는 상태에서 run을 하면 break point에서 일시정지가 됩니다.
계속 진행을 하려면 continue의 약자cont를 입력하면 됩니다.(gdb) cont
break point가 걸려 있는 상태에서 계속 진행하지 않고 한 step만 진행하려면
ni명령어를 사용합니다.(gdb) ni
어떤 break point가 있는지 확인하려면
info b명령을 사용하면 됩니다.(gdb) info bNum Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005bd <main> 2 breakpoint keep y 0x00000000004005c5 <main+8>
바이너리를 실행 중에 레지스터를 보려면
info reg명령어를 사용합니다.(gdb) info reg
바이너리를 실행 중에 특정 레지스터를 확인하려면 다음 명령어를 사용합니다.
레지스터는 항상$기호를 붙입니다. 레스터 이름 대신 메모리 주소를 입력해도 됩니다.(gdb) info reg "register_name"
command mean result (gdb) x/t $rsp 2진법 0x7fffffffdea0: 11111111111111111101111110100000 (gdb) x/o $rsp 8진법 0x7fffffffdea0: 037777757640 (gdb) x/d $rsp 10진법 0x7fffffffdea0: -8288 (gdb) x/u $rsp 16진법 0x7fffffffdea0: 4294959008 (gdb) x/x $rsp char 0x7fffffffdea0: 0xffffdfa0 (gdb) x/c $rsp float 0x7fffffffdea0: -96 '\240' (gdb) x/f $rsp float 0x7fffffffdea0: 6.9533558074255227e-310 (gdb) x/s $rsp string 0x7fffffffdea0: "\240\337\377\377\377\177 (gdb) x/bx $rsp 1바이트 0x7fffffffdea0: 0xa0 (gdb) x/bx $rsp 2바이트 0x7fffffffdea0: 0xa0 (gdb) x/wx $rsp 4바이트 0x7fffffffdea0: 0xffffdfa0 (gdb) x/gx $rsp 8바이트 0x7fffffffdea0: 0x00007fffffffdfa0 예를 들어 x/bx에서
x/와bx사이에 숫자 N을 넣으면 N만큼 연속으로 읽으라는 의미입니다.(gdb) x/10bx $rsp0x7fffffffdea0: 0xa0 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00 0x7fffffffdea8: 0x00 0x00
특정 break point를 삭제하려면
delete명령어와 함께info에서 확인한 break point의 번호를 적으면 됩니다.(gdb) delete 2
그냥 delete라고만 치면 모든 break point를 삭제할 수 있습니다.
(gdb) deleteDelete all breakpoints? (y or n)
| name | means |
|---|---|
| rip | instruction pointer |
| esp |