gdb 사용법과 pwndbg
gcc options
gdb 사용법
break point
info b (i b): 현재 브레이크 포인트 보기
d : 모든 브레이크 포인트 지우기
d n : n번 브레이크 포인트 지우기
enable/disable (브레이크 포인트 번호) : 활성화/비활성화
변수 출력
info locals : 현재 스택의 로컬변수 모두를 출력
info variables : 전역변수 모두 출력
p [변수명] : 해당변수 value 출력
p $[레지스터명] : 레지스터값 출력
p [변수명] = [value] : 특정 변수의 값을 설정
p 함수명 = 함수의 주소 출력
info registers (i r): 레지스터 전체 출력
스택 상태
info f (i f): 스택 프레임 내용 출력
info args : 함수 호출시 인자를 출력
info locals : 함수의 지역변수를 출력
메모리 상태
- x/[범위][출력형식][범위의단위] [메모리주소나 함수명]
범위는 기본 4byte
출력형식
t : 2진수
o : 8진수
u : 부호없는 10진수
x : 16진수
f : float
c : char
s: 문자열로 출력
i : 어셈블리 형식으로 출력 (instruction)
a : address
범위의 단위
b : 1 byte
h : 2 byte
w : 4 byte
g : 8 byte
기타
c : break point까지 실행
stepi(si)/nexti(ni)
: 코드 한줄 실행, si는 함수 안으로 들어가고 ni는 들어가지 않음.set {타입}[주소] = [값]
: 특정 메모리에 값을 지정 (set {int}0x8048300 = 100
)catch {event}
: event 발생 시 프로세스 중지,ex) catch syscall arch_prctl
watch {주소}
: 특정 주소에 저장된 값이 변경되면 프로세스를 중단,ex) watch *(0x7ffff7fdb4c0+0x28)
pwndbg
기본적인 gdb 명령어 (ni, si, break, continue, run 등) 외에 pwndbg에서 제공하는 명령어 정리
start
Linux는 실행파일의 형식으로 ELF(Execute and Linkable Format)
을 규정하고 있음.
크게 헤더와 여러 섹션들로 구성되어 있는데, 헤더에는 실행에 필요한 여러 정보가 적혀 있고 섹션들에는 컴파일된 기계어 코드, 프로그램 문자열을 비롯한 여러 데이터가 포함됨.
ELF 헤더 중 진입점(Entry Point, EP)라는 필드가 있는데, 운영체제는 ELF를 실행할 때 진입점의 값부터 프로그램을 실행한다고 함.
readelf 명령어로 확인할 수 있으며 readelf -h {file}
로 ELF 헤더를 확인할 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ readelf -h debugee
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400400 ---> 진입점
Start of program headers: 64 (bytes into file)
Start of section headers: 6376 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
start 명령어는 진입점부터 프로그램을 분석할 수 있게 해주는 gdb 명령어임.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pwndbg> start
Temporary breakpoint 1 at 0x400400
Temporary breakpoint 1, 0x0000000000400400 in _start ()
[중략]
───────────────────────────[ DISASM ]─────────────────────────────
► 0x400400 <_start> xor ebp, ebp
0x400402 <_start+2> mov r9, rdx
0x400405 <_start+5> pop rsi
0x400406 <_start+6> mov rdx, rsp
0x400409 <_start+9> and rsp, 0xfffffffffffffff0
0x40040d <_start+13> push rax
0x40040e <_start+14> push rsp
0x40040f <_start+15> mov r8, __libc_csu_fini <0x4005a0>
0x400416 <_start+22> mov rcx, __libc_csu_init <0x400530>
0x40041d <_start+29> mov rdi, main <0x4004e7>
0x400424 <_start+36> call qword ptr [rip + 0x200bc6] <__libc_start_main>
[중략]
pwndbg>
u, nearpc, pd
gdb에는 disassemb (disas) 함수
로 함수를 디스어셈블 할 수 있는데, u, nearpc, pdisassemble은 pwndbg에서 제공하는 가독성 좋은 디스어셈블 명령어이다.
finish
step into(si)로 함수 내부에 들어가서 필요한 부분을 모두 분석했는데, 함수의 규모가 커서 ni로는 원래 실행 흐름으로 돌아가기 어려울 수 있다.
이때 finish라는 명령어를 사용하여 함수의 끝까지 한 번에 실행할 수 있다고 한다.
telescope(tele)
pwndbg에서 제공하는 강력한 메모리 덤프 기능이라고 한다.
특정 주소의 메모리 값들을 보여주는 것에서 그치지 않고, 메모리가 참조하고 있는 주소를 재귀적으로 탐색하여 값을 보여준다고 한다.
1
2
3
4
5
6
7
8
9
pwndbg> tele
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
vmmap
vmmap은 가상 메모리의 레이아웃을 보여준다고 한다.
어떤 파일이 매핑된 영역일 경우, 해당 파일의 경로까지 보여준다.
파일 매핑이란 어떤 파일을 메모리에 적재하는 걸 뜻한다고 한다.
리눅스에서는 ELF를 실행할 때 먼저 ELF의 코드와 여러 데이터를 가상 메모리에 매핑하고, 해당 ELF에 링크된 공유 오브젝트(Shared Object, so)를 추가로 메모리에 매핑하는데, so 파일은 자주 사용되는 함수들을 미리 컴파일해둔 것이라 한다.
C언어의 printf, scanf 등이 리눅스에서는 libc(library C)에 구현되어 있고, 공유 오브젝트에 이미 구현된 함수를 호출할 때는 매핑된 메모리에 존재하는 함수를 대신 호출한다고 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x400000 0x401000 r-xp 1000 0 /home/dreamhack/debugee
0x600000 0x601000 r--p 1000 0 /home/dreamhack/debugee
0x601000 0x602000 rw-p 1000 1000 /home/dreamhack/debugee
0x7ffff79e4000 0x7ffff7bcb000 r-xp 1e7000 0 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7bcb000 0x7ffff7dcb000 ---p 200000 1e7000 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7dcb000 0x7ffff7dcf000 r--p 4000 1e7000 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7dcf000 0x7ffff7dd1000 rw-p 2000 1eb000 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7dd1000 0x7ffff7dd5000 rw-p 4000 0
0x7ffff7dd5000 0x7ffff7dfc000 r-xp 27000 0 /lib/x86_64-linux-gnu/ld-2.27.so
0x7ffff7dd5000 0x7ffff7dfc000 rwxp 27000 0 <explored>
0x7ffff7fe3000 0x7ffff7fe5000 rw-p 2000 0
0x7ffff7ff7000 0x7ffff7ffa000 r--p 3000 0 [vvar]
0x7ffff7ffa000 0x7ffff7ffc000 r-xp 2000 0 [vdso]
0x7ffff7ffc000 0x7ffff7ffd000 r--p 1000 27000 /lib/x86_64-linux-gnu/ld-2.27.so
0x7ffff7ffd000 0x7ffff7ffe000 rw-p 1000 28000 /lib/x86_64-linux-gnu/ld-2.27.so
0x7ffff7ffe000 0x7ffff7fff000 rw-p 1000 0
0x7ffffffdc000 0x7ffffffff000 rw-p 23000 0 [stack]
출처
- Link
- mitny.github.io/articles/2016-08/gdb-command -> GDB 명령어
- Dreamhack Tool: gdb –> pwndbg 명령어
- a1ways-hyerang.tistory.com/entry/System-Hacking-STAGE-3-Tool-gdb
- Dreamhack Tool: gdb –> pwndbg 명령어