Tool: gdb
gdb: 리눅스의 디버거
gdb 플러그인중에서 바이너리 분석 용도로 pwngdb 사용
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh
위 명령어 한 줄씩 입력

wsl에 깔아주려는데 22.04가 자꾸 안되길래 20.04로 했더니 성공적으로 설치되었다
디버깅 실습 1


gdb debugee로 디버깅 시작
- entry
리눅스의 실행파일 포맷: ELF
헤더+여러 섹션으로 구성되어있음
헤더: 실행에 필요한 여러 정보 담김
섹션: 컴파일된 기계어 코드, 프로그램 문자열 등 데이터 담김
ELF 헤더 중에 진입점(Entry Point) 존재
OS가 ELF 실행 시, 진입점 값부터 프로그램 실행

위 파일의 entry point address는 0x401050

gdb의 entry 명령어: 진입점부터 분석함
rip 값을 보면 진입점의 0x401050 주소임을 알 수 있
- context
프로그램 실행 -> 여러 메모리 접근(레지스터 포함)
pwndbg에서 주요 메모리 상태를 context라 부름
제공되는 context는 4개 - REGISTERS: 레지스터 상태
- DISASM: rip부터 디스어셈블된 결과
- STACK: rsp부터 스택 값
-
BACKTRACE: rip에 도달하기까지 중첩,호된 함수들 목록
- break&continue/run

run(r): 프로그램 단순 실행
- disassembly

disassemble: gdb의 기본 디셈블 명령어, 함수 이름을 인자로 전달하면 함수 반환까지 디셈블
u, nearpc, pdisass: pwndbg에서 제공하는 디셈블 명령어

- navigate - ni(next instruction)
서브루틴으로 들어가지 않는 게 ni
서브루틴으로 들어가는 게 si(step into)
내 실습에서는 printf call이 main+61


ni는 다음 명령인 main+66으로 넘어감
- navigate -si(step into)/finish
위 실습에서 ni가 아닌 si로 이동하면

printf 안으로 넘어감

backtrace 참조 시, main위에 printf 쌓임
finish실행하면 si를 내부 함수 끝까지 실행 후 밖으로 나옴
backtrace를 확인해보면 main만 위로 쌓임
- examine
가상 메모리 임의 주소의 값 출력
x라는 명령어 제공: 특정 주소에서 원하는 길이만큼 원하는 포맷으로 인코딩하여 출력하는 명령어
포맷 자세히는 아래 접은글
더보기
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char), s(string) and z(hex, zero padded on the left). Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).


- telescope/vmmap
telescope: pwndbg가 제공하는 메모리 덤프 기능
주소의 메모리 값도 보여주고, 메모리가 참조하는 주소 탐색하여 값 열

vmmap: 가상 메모리 레이아웃 출력, 매핑 영역이면 파일의 경로도 출력

- gdb/python
다음 코드의 경우 argv 필요
이때 파이썬으로 입력값 생성 후 프로그램 입력으로 넘겨주어야 함
// Name: debugee2.c
// Compile: gcc -o debugee2 debugee2.c -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char name[20];
if( argc < 2 ) {
printf("Give me the argv[2]!\n");
exit(0);
}
memset(name, 0, sizeof(name));
printf("argv[1] %s\n", argv[1]);
read(0, name, sizeof(name)-1);
printf("Name: %s\n", name);
return 0;
}
- gdb/python argv
r 명령어와 $()를 같이 입력하면 값 전달 가능

여기서 $()는 argv

여기서 «< $()는 read함수가 읽는 입력값