gdb설치와 실습

Tool: gdb
gdb: 리눅스의 디버거
gdb 플러그인중에서 바이너리 분석 용도로 pwngdb 사용

git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh

위 명령어 한 줄씩 입력

pwndbg 설치 화면

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

디버깅 실습 1

디버깅 실습 화면

pwndbg에 만들어서 mv로 옮겨

gdb debugee로 디버깅 시작

  1. entry
    리눅스의 실행파일 포맷: ELF
    헤더+여러 섹션으로 구성되어있음
    헤더: 실행에 필요한 여러 정보 담김
    섹션: 컴파일된 기계어 코드, 프로그램 문자열 등 데이터 담김

ELF 헤더 중에 진입점(Entry Point) 존재
OS가 ELF 실행 시, 진입점 값부터 프로그램 실행

elf의 헤더 정보

위 파일의 entry point address는 0x401050

rip 값 확인

gdb의 entry 명령어: 진입점부터 분석함
rip 값을 보면 진입점의 0x401050 주소임을 알 수 있

  1. context
    프로그램 실행 -> 여러 메모리 접근(레지스터 포함)
    pwndbg에서 주요 메모리 상태를 context라 부름
    제공되는 context는 4개
  2. REGISTERS: 레지스터 상태
  3. DISASM: rip부터 디스어셈블된 결과
  4. STACK: rsp부터 스택 값
  5. BACKTRACE: rip에 도달하기까지 중첩,호된 함수들 목록

  6. break&continue/run

중단점 설정과 continue

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

  1. disassembly

disassemble 명령어

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

디셈블 명령어 예시

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

ni 명령어 예시

ni 명령어 결과

ni는 다음 명령인 main+66으로 넘어감

  1. navigate -si(step into)/finish
    위 실습에서 ni가 아닌 si로 이동하면

si 명령어 예시

printf 안으로 넘어감

backtrace 확인

backtrace 참조 시, main위에 printf 쌓임

finish실행하면 si를 내부 함수 끝까지 실행 후 밖으로 나옴
backtrace를 확인해보면 main만 위로 쌓임

  1. 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).

rsp부터 8바이트 hex형식으로 10번

rip부터 5줄

특정 주소 문자열

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

telescope 예시

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

vmmap 예시

  1. 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;
}
  1. gdb/python argv
    r 명령어와 $()를 같이 입력하면 값 전달 가능

argv 전달 예시

여기서 $()는 argv

read 함수 입력값

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