(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 *main
Breakpoint 1 at 0x4005bd
특정 지점에 break point를 주려면
+"line_number"
를 이어적으면 됩니다.(gdb) b "function_name"+"line_number"
Example
(gdb) b *main+8
Breakpoint 2 at 0x4005c5
b *main
에 비해 8증가 된 주소값을 볼 수 있습니다.
또한 특정 주소를 이용하여 break point를 걸 수도 있습니다.
(gdb) b "address"
Example
(gdb) b *0x00000000004005bd
Breakpoint 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 b
Num 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 $rsp
0x7fffffffdea0: 0xa0 0xdf 0xff 0xff 0xff 0x7f 0x00 0x00 0x7fffffffdea8: 0x00 0x00
특정 break point를 삭제하려면
delete
명령어와 함께info
에서 확인한 break point의 번호를 적으면 됩니다.(gdb) delete 2
그냥 delete라고만 치면 모든 break point를 삭제할 수 있습니다.
(gdb) delete
Delete all breakpoints? (y or n)
name | means |
---|---|
rip | instruction pointer |
esp |