버그(bug): 실수로 발생한 프로그램의 결함
디버거(Debugger): 버그를 없애기 위해 사용하는 도구
* 디버거 사용 => 버그 발견이 쉬워짐 => 개발자들이 버그를 고치기 쉬워짐 & 해커들이 취약점을 발견하기 쉬워짐
: 리눅스의 대표적인 디버거
ELF(Executable and Linkable Format): 리눅스의 실행파일의 형식
진입점(Entry Point, EP)
=> 운영체제는 ELF를 실행할 때, 진입점의 값부터 프로그램을 실행
readelf -h (디렉토리명)을 사용하여 진입점 확인 가능
gdb (디렉토리명): 디버깅 시작
entry: 진입점부터 프로그램을 분석할 수 있게 해주는 gdb의 명령어
주요 메모리들의 상태를 프로그램이 실행되고 있는 맥락이라 부름
REGISTERS: 레지스터의 상태를 보여줌DISASM: rip부터 여러 줄에 걸쳐 디스어셈블된 결과를 보여줌STACK: rsp부터 여러 줄에 걸쳐 스택의 값들을 보여줌BACKTRACE: 현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지를 보여줌break: 특정 주소에 중단점(breakpoint)을 설정하는 기능
continue: 중단된 프로그램을 계속 실행시키는 기능
run: 단순히 실행시키는 기능
어셈블리 명령어를 한 줄씩 실행시키는 명령어
ni(next instruction): 서브루틴의 내부로 들어가지 않음
si(step into): 서브루틴의 내부로 들어감
finish: 함수의 끝까지 한 번에 실행시키는 기능
main() 심볼이 존재할 때 유용한 명령어
start
main: start 명령어와 동일
examine
x: 가상 메모리에 존재하는 임의 주소의 값을 관찰할 수 있는 기능(gdb에서 기본적으로 제공)
telescope
tele: 메모리가 참조하고 있는 주소를 재귀적으로 탐색하여 값을 보여주는 기능(pwndbg가 제공하는 강력한 메모리 덤프 기능)
vmmap: 가상 메모리의 레이아웃을 보여주는 기능
disassemble: gdb가 기본적으로 제공하는 디스어셈블 명령어
# 예시 (helloworld.c 디스어셈블)
- helloworld.c 작성

- 디스어셈블

* 어셈블리어 분석
0x0000000000001149 <+0>: endbr64
0x000000000000114d <+4>: push rbp # rbp를 스택 최상단에 쌓음
0x000000000000114e <+5>: mov rbp,rsp # rsp의 값을 rbp에 대입
0x0000000000001151 <+8>: lea rax,[rip±0xeac] # [rip±0xeac]를 rax에 저장
0x0000000000001158 <+15>: mov rdi,rax # rax의 값을 rdi에 대입
0x000000000000115b <+18>: call 0x1050 <puts@plt> # 0x1050에 위치한 프로시져 호출
0x0000000000001160 <+23>: mov eax,0x0 # 0x0의 값을 eax에 대입
0x0000000000001165 <+28>: pop rbp # 스택 최상단 값을 rbp에 대입
0x0000000000001166 <+29>: ret # return address로 반환
u, nearpc, pdisass는 디스어셈블된 코드를 가독성 좋게 출력해주는 디스어셈블 명령어
*argv
run 명령어의 인자로 $()와 함께 파이썬 코드를 입력하면 값을 전달할 수 있음
*input
$()와 함께 파이썬 코드를 입력하면 값을 입력할 수 있음. 입력값으로 전달하기 위해서는 <<<를 사용
ex) pwndbg > r $(python3 -c "print('\xff' * 100)") <<< $(python3 -c "print('dreamhack')")