[GDB] GDB 메뉴얼

EUGENE·2023년 4월 5일
0

기본적인 실행, 종료

실행

> gdb
// 실행은 참 쉬움

종료

pwndbg> exit
// 종료도 참 쉬움

gdb 세팅 포맷이 무엇인지 확인하기

pwndbg> show disassembly-flavor

→ Intel 이면 Intel로 뜸

만약 다른 포맷이면 변경해야 함

써먹어보기

예시 코드

// Name : debugee.c
// Compile : gcc -o debugee debugee.c -no-pie
// --------------------------------------------
#include <stdio.h>

int main(void) { 

        int sum = 0;
        int val1 = 1;
        int val2 = 2;

        sum = val1 + val2;
        printf("1 + 2 = %d\n", sum);

        return 0;
}

바이너리 파일의 정보 확인하기

> readelf -h debugee // ELF (Executable and Linkable Format

→ 온갖 정보가 다 뜰거임

📌 Entry point address : 프로그램이 실제로 실행되는 주소(16진수)

시잒!

> gdb debugee

gdb + 실행파일

진짜 시잒!

pwndbg> start

Temporary breakpoint 1 at 0x40112a # 여기 멈춰 있다는 의미

Temporary breakpoint 1, 0x000000000040112a in main ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA # 세그먼트 정보들
────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────
# 레지스터 정보들
*RAX  0x401126 (main) ◂— push rbp
*RBX  0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'
*RCX  0x403e00 (__do_global_dtors_aux_fini_array_entry) —▸ 0x4010f0 (__do_global_dtors_aux) ◂— endbr64                                                                                        
*RDX  0x7fffffffde78 —▸ 0x7fffffffe213 ◂— 'CLUTTER_IM_MODULE=fcitx'
*RDI  0x1
*RSI  0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'
 R8   0x0
*R9   0x7ffff7fcf6a0 (_dl_fini) ◂— push rbp
*R10  0x7ffff7fcb878 ◂— 0xc00120000000e
*R11  0x7ffff7fe18c0 (_dl_audit_preinit) ◂— mov eax, dword ptr [rip + 0x1b552]
 R12  0x0
*R13  0x7fffffffde78 —▸ 0x7fffffffe213 ◂— 'CLUTTER_IM_MODULE=fcitx'
*R14  0x403e00 (__do_global_dtors_aux_fini_array_entry) —▸ 0x4010f0 (__do_global_dtors_aux) ◂— endbr64                                                                                        
*R15  0x7ffff7ffd020 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0x0
*RBP  0x7fffffffdd50 ◂— 0x1 # 레지스터 외워라 좀;
*RSP  0x7fffffffdd50 ◂— 0x1
*RIP  0x40112a (main+4) ◂— sub rsp, 0x10
─────────────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────────────
 ► 0x40112a <main+4>     sub    rsp, 0x10 # 여기서 멈춰 있다고 친절하게 알려줌
   0x40112e <main+8>     mov    dword ptr [rbp - 4], 0
   0x401135 <main+15>    mov    dword ptr [rbp - 8], 1
   0x40113c <main+22>    mov    dword ptr [rbp - 0xc], 2
   0x401143 <main+29>    mov    edx, dword ptr [rbp - 8]
   0x401146 <main+32>    mov    eax, dword ptr [rbp - 0xc]
   0x401149 <main+35>    add    eax, edx
   0x40114b <main+37>    mov    dword ptr [rbp - 4], eax
   0x40114e <main+40>    mov    eax, dword ptr [rbp - 4]
   0x401151 <main+43>    mov    esi, eax
   0x401153 <main+45>    lea    rax, [rip + 0xeaa]
───────────────────────────────────────────[ STACK ]───────────────────────────────────────────
00:0000│ rbp rsp 0x7fffffffdd50 ◂— 0x1
01:0008│         0x7fffffffdd58 —▸ 0x7ffff7df318a (__libc_start_call_main+122) ◂— mov edi, eax
02:0010│         0x7fffffffdd60 ◂— 0x0
03:0018│         0x7fffffffdd68 —▸ 0x401126 (main) ◂— push rbp
04:0020│         0x7fffffffdd70 ◂— 0x100000000
05:0028│         0x7fffffffdd78 —▸ 0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'
06:0030│         0x7fffffffdd80 —▸ 0x7fffffffde68 —▸ 0x7ffffffhack/debugee'
07:0038│         0x7fffffffdd88 ◂— 0x2181d7828d77fade
─────────────────────────────────────────[ BACKTRACE ]────────
 ► f 0         0x40112a main+4
   f 1   0x7ffff7df318a __libc_start_call_main+122
   f 2   0x7ffff7df3245 __libc_start_main+133
   f 3         0x401061 _start+33 # entry point + 33 byte
																	# 실제 프로그램이 시작하는 시점은 main이 아니다!
──────────────────────────────────────────────────────────────
pwndbg>

break point 잡기

메인에 걸어두는 습관이 있으면 좋다.

여러개 걸어둘 수 있다. 그리고 순서도 상관 없다.

pwndbg> break *main # 메인 함수에 브레이크 걸라는 명령
Breakpoint 1 at 0x401126 # 메인 함수에서 break 걸었다!

run (r도 가능)

중단점 설정된곳까지 실행

pwndbg> run # 프로그램 실행
Starting program: /home/eugene/Workspace/hack/debugee 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".                                                  

Breakpoint 1, 0x0000000000401126 in main ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────[ REGISTERS / show-flags off / show-compact-regs off ]────
*RAX  0x401126 (main) ◂— push rbp
*RBX  0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'
*RCX  0x403e00 (__do_global_dtors_aux_fini_array_entry) —▸ 0x4010f0 (__do_global_dtors_aux) ◂— endbr64                      
*RDX  0x7fffffffde78 —▸ 0x7fffffffe213 ◂— 'CLUTTER_IM_MODULE=fcitx'
*RDI  0x1
*RSI  0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'
 R8   0x0
*R9   0x7ffff7fcf6a0 (_dl_fini) ◂— push rbp
*R10  0x7ffff7fcb878 ◂— 0xc00120000000e
*R11  0x7ffff7fe18c0 (_dl_audit_preinit) ◂— mov eax, dword ptr [rip + 0x1b552]                                              
 R12  0x0
*R13  0x7fffffffde78 —▸ 0x7fffffffe213 ◂— 'CLUTTER_IM_MODULE=fcitx'
*R14  0x403e00 (__do_global_dtors_aux_fini_array_entry) —▸ 0x4010f0 (__do_global_dtors_aux) ◂— endbr64                      
*R15  0x7ffff7ffd020 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0x0
*RBP  0x1
*RSP  0x7fffffffdd58 —▸ 0x7ffff7df318a (__libc_start_call_main+122) ◂— mov edi, eax                                         
*RIP  0x401126 (main) ◂— push rbp
─────────────[ DISASM / x86-64 / set emulate on ]─────────────
 ► 0x401126 <main>       push   rbp # 여기서 멈췄다! 우리가 원했던 메인함수에 브레이크 걸림
   0x401127 <main+1>     mov    rbp, rsp
   0x40112a <main+4>     sub    rsp, 0x10
   0x40112e <main+8>     mov    dword ptr [rbp - 4], 0
   0x401135 <main+15>    mov    dword ptr [rbp - 8], 1
   0x40113c <main+22>    mov    dword ptr [rbp - 0xc], 2
   0x401143 <main+29>    mov    edx, dword ptr [rbp - 8]
   0x401146 <main+32>    mov    eax, dword ptr [rbp - 0xc]
   0x401149 <main+35>    add    eax, edx
   0x40114b <main+37>    mov    dword ptr [rbp - 4], eax
   0x40114e <main+40>    mov    eax, dword ptr [rbp - 4]
──────────────────────────[ STACK ]───────────────────────────
00:0000│ rsp 0x7fffffffdd58 —▸ 0x7ffff7df318a (__libc_start_call_main+122) ◂— mov edi, eax                                  
01:0008│     0x7fffffffdd60 ◂— 0x0
02:0010│     0x7fffffffdd68 —▸ 0x401126 (main) ◂— push rbp
03:0018│     0x7fffffffdd70 ◂— 0x100000000
04:0020│     0x7fffffffdd78 —▸ 0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'                    
05:0028│     0x7fffffffdd80 —▸ 0x7fffffffde68 —▸ 0x7fffffffe1ef ◂— '/home/eugene/Workspace/hack/debugee'                    
06:0030│     0x7fffffffdd88 ◂— 0xc884d300c9241961
07:0038│     0x7fffffffdd90 ◂— 0x0
────────────────────────[ BACKTRACE ]─────────────────────────
 ► f 0         0x401126 main
   f 1   0x7ffff7df318a __libc_start_call_main+122
   f 2   0x7ffff7df3245 __libc_start_main+133
   f 3         0x401061 _start+33
──────────────────────────────────────────────────────────────

continue

pwndbg> continue # 얘를 입력하면 프로그램이 끝까지 실행됨
Continuing.
1 + 2 = 3
[Inferior 1 (process 17990) exited normally]

gdb 명령어 요약

  • b : break
  • c : continue
  • r : run
  • si : step into ( 함수로 들어감 )
  • ni next instruction ( 함수를 넘어감 )
  • i : info
  • k : kill
  • pd : pdisas

disassemble

특정 부분의 어셈블리 코드를 볼 수 있다.

유사한 명령어 : u, nearpc, pdisassemble

pwndbg> disassemble main
Dump of assembler code for function main:
   0x0000000000401126 <+0>:     push   rbp
   0x0000000000401127 <+1>:     mov    rbp,rsp
   0x000000000040112a <+4>:     sub    rsp,0x10
   0x000000000040112e <+8>:     mov    DWORD PTR [rbp-0x4],0x0
   0x0000000000401135 <+15>:    mov    DWORD PTR [rbp-0x8],0x1
   0x000000000040113c <+22>:    mov    DWORD PTR [rbp-0xc],0x2
   0x0000000000401143 <+29>:    mov    edx,DWORD PTR [rbp-0x8]
   0x0000000000401146 <+32>:    mov    eax,DWORD PTR [rbp-0xc]
   0x0000000000401149 <+35>:    add    eax,edx
   0x000000000040114b <+37>:    mov    DWORD PTR [rbp-0x4],eax
   0x000000000040114e <+40>:    mov    eax,DWORD PTR [rbp-0x4]
   0x0000000000401151 <+43>:    mov    esi,eax
   0x0000000000401153 <+45>:    lea    rax,[rip+0xeaa]        # 0x402004                                                    
   0x000000000040115a <+52>:    mov    rdi,rax
   0x000000000040115d <+55>:    mov    eax,0x0
   0x0000000000401162 <+60>:    call   0x401030 <printf@plt>
   0x0000000000401167 <+65>:    mov    eax,0x0
   0x000000000040116c <+70>:    leave
   0x000000000040116d <+71>:    ret
End of assembler dump.

ni, si

공통점 : 어세믈리 명령어를 한줄 씩 실행

차이점 :

ni : 서브루틴의 내부로 들어가지 않음

si : 서브루틴의 내부로 진입

pwndbg> b *main+40
Breakpoint 2 at 0x40114e
pwndbg> b *main
Breakpoint 3 at 0x401126
# 일단은 두 군데에 브레이크 걸어둠
# si, ni 사용할때마다 한칸씩 앞으로 감
# continue는 브레이크 걸린 부분까지 하이패스

📌 si로 진입 후 함수 끝까지 한번에 실행하 : finish

메모리 값 확인

  • x/숫자단위포맷 시작주소

  • x/10gx $rsp

    → rsp에서 80바이트를 8바이트씩 hex형식으로 출력

📌 o : 8진법

x : 16진법

u : 10진법

t : 2진법

b : 1byte 단위

h : 2byte 단위 half word

w : 4byte 단위 word

g : 8byte 단위 giant

i : 역어셈블된 명령어의 명령 메모리를 볼 수 있음

c : ASCII 표의 바이트를 자동으로 볼 수 있음

S : 문자 데이터의 전체 문자열을 보여줌

pwndbg> x/10gx $rsp # rsp에서 80byte를 8byte씩 hex형식으로 출력
0x7fffffffdd98: 0x00007ffff7df318a      0x0000000000000000
0x7fffffffdda8: 0x0000000000401126      0x0000000100000000
0x7fffffffddb8: 0x00007fffffffdea8      0x00007fffffffdea8
0x7fffffffddc8: 0xe93492b27d999a21      0x0000000000000000
0x7fffffffddd8: 0x00007fffffffdeb8      0x0000000000403e00
pwndbg> x/5i $rip # rip부터 5줄의 어셈블리 명령어 출력
=> 0x401126 <main>:     push   rbp
   0x401127 <main+1>:   mov    rbp,rsp
   0x40112a <main+4>:   sub    rsp,0x10
   0x40112e <main+8>:   mov    DWORD PTR [rbp-0x4],0x0
   0x401135 <main+15>:  mov    DWORD PTR [rbp-0x8],0x1
pwndbg> x/s 0x400000 # 특정 주소의 문자열 출력
0x400000:       "\177ELF\002\001\001"

변수값 확인 : print

pwndbg> print args
$1 = 2

pwndbg> print argv[0]
$2 = 0x7fffffffe20b "/home/eugene/Workspace/hack/bugfile"

레지스터 값 확인 : info reg

pwndbg> info reg # 레지스터 전체값 
rax            0x555555555149      93824992235849
rbx            0x7fffffffde88      140737488346760
rcx            0x555555557dd8      93824992247256
rdx            0x7fffffffdea0      140737488346784
rsi            0x7fffffffde88      140737488346760
rdi            0x2                 2
rbp            0x7fffffffdd70      0x7fffffffdd70
rsp            0x7fffffffdd50      0x7fffffffdd50
r8             0x0                 0
r9             0x7ffff7fcf6a0      140737353938592
r10            0x7ffff7fcb878      140737353922680
r11            0x7ffff7fe18c0      140737354012864
r12            0x0                 0
r13            0x7fffffffdea0      140737488346784
r14            0x555555557dd8      93824992247256
r15            0x7ffff7ffd020      140737354125344
rip            0x555555555158      0x555555555158 <main+15>
eflags         0x206               [ PF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
pwndbg> info reg $rsp # 특정 레지스터 값
rsp            0x7fffffffdd50      0x7fffffffdd50

스택 확인

  • x/[조회하는 메모리 범위]xw[조회하는 메모리 지점]

0x7fffffffdd50: 0xffffde88      0x00007fff      0x00000000      0x00000002
0x7fffffffdd60: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffdd70: 0x00000002      0x00000000      0xf7df318a      0x00007fff
0x7fffffffdd80: 0x00000000      0x00000000      0x55555149      0x00005555
0x7fffffffdd90: 0x00000000      0x00000002      0xffffde88      0x00007fff
0x7fffffffdda0: 0xffffde88      0x00007fff      0xc2fecbe3      0x6cd326ff
0x7fffffffddb0: 0x00000000      0x00000000      0xffffdea0      0x00007fff
0x7fffffffddc0: 0x55557dd8      0x00005555      0xf7ffd020      0x00007fff

후기

어렵지만 재밌다.

profile
한 줄로 소개하기엔 여백이 좁아 적지 않겠습니다.

0개의 댓글