미역줄기의 이모저모
[ Dreamhack ] Tool: gdb 본문
디버거는 프로그램을 어셈블리 코드 단위로 실행하면서, 실행 결과를 사용자에게 직관적으로 보여준다.
gdb는 리눅스의 대표적인 디버거 중 하나이다.
(나는 우분투 22.04 환경에서 진행했다.)
pwndbg를 다운로드 한다.
$ git clone https://github.com/pwndbg/pwndbg
$ cd pwndbg
$ ./setup.sh
실습예제 코드
// 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;
}
gdb debugee로 디버깅 시작
$ gcc -o debugee debugee.c -no-pie
$ gdb debugee
entry
ELF: 리눅스가 규정한 실행파일 형식이다. 실행에 필요한 여러 정보들이 적혀있는 헤더와 컴파일된 기계어 코드와 프로그램 문자열을 비롯한 여러 데이터가 포함되어 있는 섹션으로 구성된다.
ELF의 헤더 중에 EP(entry point)라는 필드가 있다. 운영체제는 ELF를 실행할 때, EP의 값부터 프로그램을 실행한다.
$ 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: 2s 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: 0x401050
readelf로 확인한 결과 debugee의 EP는 0x401050이다.
gdb의 entry 명령어는 진입점(EP)로부터 프로그램을 분석할 수 있게 해주는 gdb의 명령어이다. 화살표(►)가 가리키는 주소는 현재 rip의 값인데, entry 명령어를 실행하고 보면 0x401050을 가리키고 있다.
pwndbg> entry
Temporary breakpoint 12 at 0x401050
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Temporary breakpoint 12, 0x0000000000401050 in _start ()
[중략]
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
► 0x401050 <_start> endbr64
Context
pwbdbg는 주요 메모리들의 상태를 프로그램이 실행되고 있는 맥락이라고 부른다. 크게 4가지의 영역으로 구분된다.
- REGISTER: 레지스터의 상태
- DISASM: rip부터 디스 어셈블된 결과를 보여줌
- STACK: rsp부터 스택의 값들을 보여줌
- BACKTRACE: 현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지 보여줌
break & continue
break는 특정 주소에 중단점을 설정한다. continue는 중단된 프로그램을 계속 실행시킨다.
run
단순히 실행만 시킨다.
gdb의 명령어 축약 |
b: break |
c: continue |
r: run |
si: step into |
ni: next into |
i: info |
k: kill |
pd: pdisas |
ni, si는 모두 어셈블리 명령어를 한 줄 실행시킨다. ni는 서브루틴의 내부로 들어가지 않지만 si는 들어간다.
examine
gdb에서는 x라는 명령어를 제공한다. x를 이용하면 특정 주소에서 원하는 길이만큼의 데이터를 원하는 형식으로 코딩하여 볼수 있다.
#rsp부터 80바이트를 8바이트씩 hex형식으로 출력
pwndbg> x/10gx $rsp
0x7fffffffc228: 0x00007ffff7a05b97 0x0000000000000001
0x7fffffffc238: 0x00007fffffffc308 0x0000000100008000
0x7fffffffc248: 0x00000000004004e7 0x0000000000000000
0x7fffffffc258: 0x71eb993d1f26e436 0x0000000000400400
0x7fffffffc268: 0x00007fffffffc300 0x0000000000000000
#rip부터 5줄의 어셈블리 명령어 출력
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
#특정 주소의 문자열 출력
pwndbg> x/s 0x400000
0x400000: "\177ELF\002\001\001"
'Hacking > DreamHack 시스템 해킹 강의' 카테고리의 다른 글
[ Dreamhack ] Stack Canary (1) | 2024.02.08 |
---|---|
[ Dreamhack ] Return Address Overwrite (0) | 2024.02.06 |
[ Dreamhack ] 어셈블리어와 x86-64(2) (1) | 2024.02.05 |
[ Dreamhack ] 어셈블리어와 x86-64(1) (0) | 2024.02.05 |
[Dreamhack]Linux Memory Layout (0) | 2024.02.03 |