1. GNU Debugger (GDB)
설치
sudo apt-get install gdb
pwndbg
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh
- GDB vs. pwndbg
: gdb는 리눅스 기본 디버거, 명령어 위주로 가독성 낮고 직접 다 쳐야함
: pwndbg는 gdb 위에서 돌아가는 확장 플러그인으로 스택, 레지스터, 힙, pie, alsr 한눈에 보여줌
2. 사용 방법
1) 파일 불러오기
file ./debugee
디버깅 정보 포함: 컴파일 할때 -g 옵션을 주어 컴파일함
근데 대부분의 바이너리는 -g 옵션 없이 컴파일한 바이널임

2) 실행 흐름 제어
'run'
디버거는 프로그램을 실행시키면서 분석하는 도구
pwndbg> run <프로그램 인자>
'break & continue'
break로 breakpoint 잡음
continue로 실행 재개하고 다음 중단점까지 실행함, breakpoint없으면 끝까지 실행
-> 여러번 실행하고 싶으면 'c <숫자>' 입력
'entry & start'
리눅스는 실행파일의 형식으로 ELF(Executable and Linkable Format)를 규정하고 있음
ELF-> 헤더 + 여러 섹션으로 구성되어있음
헤더 -> 실행에 필요한 여러 정보
섹션 -> 머신 코드, 프로그램 문자열 등 데이터
ELF의 헤더 중 진입점(Entry Point, EP)라는 필드가 있음, 운영체제는 ELF를 실행할 때, EP의 명령어부터 프로그램을 실행함
'readelf' 명령어로 확인할 수 있음

ep가 0x401050임을 알 수 있음
start 명령어는 gdb에서 main()부터 분석할 수 있게 함
si(Step into) : 함수 흐름대로 진행, 함수에 들어감
ni(next instruction): 함수 스택프레임 건너뛰고 진행됨
finish: si한 후 함수 스택프레임 길어지면 원래 흐름대로 돌아감
3. 디버깅을 위해 사용하는 명령어
1) INFO
'info reg ~', 'info breakpoints'
pwndbg> b $rdi
info reg -> 단축어로 i r
info breakpoints -> 단축어로 i b
disable 1 -> 1번 중단점 비활성화
enable 1 -> 1번 중단점 활성화
delete 1 -> 중단점 1 삭제 d 1
2) disassemble
disass 로 사용가능
u, nearpc, pdisass -> 디어셈블된거 가독성 좋게 바꿔줌
3) examine / x/s ..

'x/< 포맷 및 크기>' 'x/<개수><포맷 및 크기>
ex)
pwndbg> x/5i $rip
=> 0x4004e7 <main>: push rbp
0x4004e8 <main+1>: mov rbp,rsp
0x4004eb <main+4>: sub rsp,0x10
0x4004ef <main+8>: mov DWORD PTR [rbp-0xc],0x0
0x4004f6 <main+15>: mov DWORD PTR [rbp-0x8],0x1
4) telescope
강력한 메모리 덤프임, 메모리가 참조하고 있는 주소를 재귀적으로 탐색하여 값을 보여줌
pwndbg> tele $rsp
00:0000│ rsp 0x7fffffffc228 —▸ 0x7ffff7a05b97 (__libc_start_main+231) ◂— mov edi, eax
01:0008│ 0x7fffffffc230 ◂— 0x1
02:0010│ 0x7fffffffc238 —▸ 0x7fffffffc308 —▸ 0x7fffffffc557 ◂— '/home/dreamhack/debugee'
03:0018│ 0x7fffffffc240 ◂— 0x100008000
04:0020│ 0x7fffffffc248 —▸ 0x4004e7 (main) ◂— push rbp
05:0028│ 0x7fffffffc250 ◂— 0x0
06:0030│ 0x7fffffffc258 ◂— 0x71eb993d1f26e436
07:0038│ 0x7fffffffc260 —▸ 0x400400 (_start) ◂— xor ebp, ebp
5) vmmap
가상의 메모리 레이아웃을 보여줌, 프로그램이 실행된 상태에서 이용 가능
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
Start End Perm Size Offset File
0x400000 0x401000 r--p 1000 0 /home/dreamhack/debugee
0x401000 0x402000 r-xp 1000 1000 /home/dreamhack/debugee
0x402000 0x403000 r--p 1000 2000 /home/dreamhack/debugee
0x403000 0x404000 r--p 1000 2000 /home/dreamhack/debugee
0x404000 0x405000 rw-p 1000 3000 /home/dreamhack/debugee
0x405000 0x426000 rw-p 21000 0 [heap]
0x7ffff7d7f000 0x7ffff7d82000 rw-p 3000 0 [anon_7ffff7d7f]
0x7ffff7d82000 0x7ffff7daa000 r--p 28000 0 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7daa000 0x7ffff7f3f000 r-xp 195000 28000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7f3f000 0x7ffff7f97000 r--p 58000 1bd000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7f97000 0x7ffff7f9b000 r--p 4000 214000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7f9b000 0x7ffff7f9d000 rw-p 2000 218000 /usr/lib/x86_64-linux-gnu/libc.so.6
0x7ffff7f9d000 0x7ffff7faa000 rw-p d000 0 [anon_7ffff7f9d]
0x7ffff7fbb000 0x7ffff7fbd000 rw-p 2000 0 [anon_7ffff7fbb]
0x7ffff7fbd000 0x7ffff7fc1000 r--p 4000 0 [vvar]
0x7ffff7fc1000 0x7ffff7fc3000 r-xp 2000 0 [vdso]
0x7ffff7fc3000 0x7ffff7fc5000 r--p 2000 0 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7fc5000 0x7ffff7fef000 r-xp 2a000 2000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7fef000 0x7ffff7ffa000 r--p b000 2c000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7ffb000 0x7ffff7ffd000 r--p 2000 37000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffff7ffd000 0x7ffff7fff000 rw-p 2000 39000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7ffffffde000 0x7ffffffff000 rw-p 21000 0 [stack]
0xffffffffff600000 0xffffffffff601000 --xp 1000 0 [vsyscall]
pwndbg>
** 파일 매핑?
-> 어떤 파일을 메모리에 적재하는 것을 파일 매핑이라고 함

6) backtrace
bt 라는 명령어로 콜 스택을 확인할 수 있음, 어떤 인자가 어디서왔는지 추적 가능
pwndbg> b add
Breakpoint 1 at 0x40113e
pwndbg> r
[중략]
pwndbg> bt
#0 0x000000000040113e in add ()
#1 0x0000000000401177 in main ()
#2 0x00007ffff7dce1ca in __libc_start_call_main (main=main@entry=0x40114e <main>, argc=argc@entry=1, argv=argv@entry=0x7fffffffc938) at ../sysdeps/nptl/libc_start_call_main.h:58
#3 0x00007ffff7dce28b in __libc_start_main_impl (main=0x40114e <main>, argc=1, argv=0x7fffffffc938, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffc928) at ../csu/libc-start.c:360
#4 0x0000000000401075 in _start ()
pwndbg>
7) dump memory
프로세스 메모리 상태를 파일로 저장하는 명령어
dump memory <파일명> <시작주소> <끝주소>
8) context
pwndbg는 주요 메모리들의 상태를 프로그램이 실행되고 있는 context라고 부름
기본적으로 프로그램이 중단되면 ctx를 출력하지만 별도로 ctx 명령어로 실행할 수도 있음
4개의 영역 -> reg, disasm(rip부터 여러 줄에 걸쳐 디스어셈블된 결과), stack(rsp부터 스택의 값), backtrace(현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지 보여줌)
9) set
프로세스 메모리 상태를 변경할 수 있는 명령어
주로 레지나 특정 주소의 메모리 값을 변경함
실행 중에서 가능
set <주소/레지스터> = <변경할 값>
pwndbg> set $rax = 0
pwndbg> set $rsp = $rbp
자료형 변경
pwndbg> set *(unsigned int*)0x400000 = 10
# 0x400000 주소를 unsigned int * 형으로 역참조 후 여기에 정수 10을 저장한 것
pwndbg> set *(float*)0x400010 = 3.14
# 0x400010 주소를 float* 형으로 역참조 후 여기에 부동소수점 값 3.14 저장
타입크기
| unsigned byte | 1 byte |
| unsigned int | 4 bytes |
| unsigned long | 8 bytes |
'computer basics' 카테고리의 다른 글
| [GDB 명령어] 명령어 모음 (0) | 2026.05.15 |
|---|---|
| [Linux] Linux Memory Layout (0) | 2026.02.10 |