본문 바로가기
Pwnable

Pwnable Tools

by ms-eo 2025. 11. 19.

gcc 컴파일

GCC (GNU Compiler Collection)

  • GNU 프로젝트의 일환으로 개발된 컴파일러
  • C, C++, Java, Objective-C, Fortran, Ada, Pascal 등 언어 지원

기본 컴파일 방법

  • gcc <컴파일 할 파일명> 명령어 입력 시, 해당 파일을 컴파일

메모리 보호 기법 설정 옵션

  • gcc 명령어를 사용해 컴파일 메모리 보호 기법 설정하거나 해제할 수 있는 옵션이 존재
    • NX 해제 : gcc -z execstack
    • SSP 해제 : gcc -fno-stack-protector
    • PIE 해제 : gcc -no-pie
    • RELRO 해제 : gcc -z norelro

gcc 컴파일

  • gcc를 사용해 C로 작성한 소스코드를 실행 가능한 바이너리 파일로 생성하는 과정

디버깅 Tool

Linux

GDB (GNU Debugger)

  • 리눅스에서 기본적으로 제공하는 디버깅 도구
  • gdb <실행 파일 명> 입력 시, 해당 파일을 gdb로 디버깅 가능

PEDA (Python Exploit Development Assistance for GDB)

  • binary 분석 및 Exploit을 도와주는 도구로 gdb의 발전된 버전
  • 여러 디버거들 중에서 비교적 오래된 도구
  • heap 영역을 보기에 까다로운 부분이 있어 Peda-heap 플러그인을 사용해 기능을 추가하기도 함
  • 동적 분석 시 레지스터 스택 코드 부분을 보기 쉽게 출력
  • 설치 방법 : git clone https://github.com/logld/peda.git
  • echo “source ~/peda/peda.py” >> ~/.gdbinit

GEF (GDB Enhanced Features)

  • Peda와 같이 gdb에 추가적인 기능들을 실행할 수 있도록 하는 툴
  • gdb에서 지원하는 모든 아키텍처(x86, arm, mips, powerpc, sparc 등)를 지원함
  • GEF 디버거의 사용법을 설명해주는 자료가 많음
  • 설치 방법 : git clone https://github.com/hugsy/gef.git

Pwndbg

  • heap 관련 문제를 풀 때 유용함
  • 레지스터, 스택, 실행 중인 코드의 정보에 대한 가독성이 좋음
  • 실제 레지스터와 메모리 구조가 한눈에 보기 쉬워 프로그램을 따라가며 이해하기 편리함
  • 메모리를 관리하는 명령어가 만들어져 있음
  • 설치 방법 : git clone https://github.com/pwndbg/pwndbg/archive/refs/tags/2021.06.22.tar.gz
  • cd pwndbg
  • ./setup.sh

.gdbinit

  • gdb가 실행될 때 로딩하는 환경설정 파일로 보통 /etc/gdb/gdbinit에 위치
  • 파일이 존재하지 않는다면, 직접 ~/.gdbinit을 생성해도 무방
  • gdb 명령어 하나에 다양한 디버거들로 전환하며 사용할 수 있음

기본 디버거 설정

  • 디버거 설치 후 .gdbinit 파일이 존재하는 위치로 이동한 뒤, sudo vim .gdbinit으로 파일 열기
  • 사용자가 기본 설정하려는 디버거의 .py의 위치를 확인하고, “source 경로/.py”를 입력 후 저장
  • .gdbinit에 기본 디버거 설정 값을 입력한 뒤 사용할 디버거 외 다른 설정은 주석(#) 처리

.gdbinit 설정 변경 후

  • gdb <실행 파일 명> 명령어 입력 시, 해당 파일을 pwndbg로 디버깅 가능

Windows

IDA (Interactive Disassembler)

  • Hex-Rays에서 직접 개발한 컴퓨터 소프트웨어용 디스어셈블러
  • IDA Pro 개꿀

Ghidra

  • NSA에서 제작한 리버스 엔지니어링 툴로 오픈소스로 공개함
  • 디컴파일, 디스어셈블리, 프로젝트 공유, 디버깅 등 기능 존재

Ollydbg

  • 용량이 가볍고 빠르며, 다양한 기능이 있어 사용이 편리함
  • 초보자도 쉽게 배울 수 있음

Windbg

  • Microsoft에서 직접 만든 디버거로 커널 드라이버 개발과 유지보수에 사용됨
  • 유저 모드 디버깅보다 커널 모드 디버깅에 유용함

Exploit Tool

Pwntools

  • 리눅스 환경에서 exploit을 쉽게 할 수 있게 하는 기능들이 있는 Python Module
  • 설치 후 다른 python 모듈처럼 import 해서 사용 (from pwn import *)

Pwntools 설치 방법

sudo apt-get update sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-deb build-essential python3 -m pip install --upgrade pip python3 -m pip install --upgrade pwntools

Pwntools 명령어

  • 접속 함수 : 사용자의 로컬 바이너리 파일이나 원격 환경에 접속하기 위해 사용하는 함수
    • process : 사용자의 로컬 바이너리 파일을 실행할 때 사용
    • remote : 원격 서버를 대상으로 접속할 때 사용
    • ssh : 원격 서버 대상을 ssh로 접속할 때 사용
  • 페이로드 전송 함수 : 작성한 페이로드를 접속한 환경의 바이너리 파일에 전송하기 위해 사용하는 함수
    • send : 파일에 문자열 ‘str1’ 전송
    • sendline : 파일에 문자열 ‘str1\n’ 전송
    • sendafter : 파일이 ‘str0’ 출력 시, 문자열 ‘srt1’ 전송
    • sendlineafter : 파일이 ‘str0’ 출력 시, 문자열 ‘str1\n’ 전송
  • 출력 데이터 저장 함수 : 접속한 환경의 바이너리 파일에서 출력하는 데이터를 받아오기 위해 사용하는 함수
    • recv : 출력하는 데이터 중 최대 (int)바이트 데이터 받기
    • recvline : 출력하는 데이터 중 개행 문자가 나올 때까지 받기
    • recvn : 출력하는 데이터 중 정확하게 바이트만 받기
    • recvuntil : 출력하는 데이터 중 문자열 ‘str0’ 뒤 부터 받기
    • recvall : 연결이 끊어지거나 프로세스가 종료될 때까지 받기
  • 패킹 / 언패킹 함수 : 패킹함수는 정수를 인자로 받아 패킹한 후 문자열 형태로 리턴
  • 언패킹 함수는 문자열을 인자로 받아 언패킹한 후 정수 형태로 리턴
  • 디버깅 함수 : exploit을 진행하는 중에 gdb를 실행하고자 할 때 사용하는 함수
  • 쉘 함수 : 쉘을 획득하고자 하거나, 쉘을 획득한 후에 사용하는 함수

Shellcode 작성

Shellcode

  • 시스템에서 특정 명령을 실행할 수 있도록 내부에 삽입하는 OP Code 조각
  • 일반적으로 명령 Shell을 실행시켜 대상 PC의 시스템을 제어하기 위해서 사용

Pwnable 시 Shellcode 작성 순서

  1. 문제가 요구하는 쉘 코드의 조건 / 기준 분석
  2. C 기반 쉘 실행 코드 작성
  3. Disassembling
  4. system call에 필요한 부분만 어셈블리어로 구현 후 컴파일
  5. 컴파일 후 objdump로 OP Code 출력
  6. Null Byte(0x00) 제거
  7. 최종 OP Code를 하나의 문자열로 연결

NASM (Netwide Assembler)

  • 인텔 x86 아키텍처용 어셈블러이자 역어셈블러
  • 어셈블리 파일(.s)을 컴파일하는 프로그램

어셈블리 파일 컴파일 명령어

  • nasm -f [출력 파일 포맷] -o [오브젝트 파일] [어셈블리 파일]

설치 방법

  • sudo apt-get install nasm

objdump

  • 바이너리 분석 프로그램으로 라이브러리, 컴파일된 오브젝트 모듈, 공유 오브젝트 파일, 독립 실행파일 등의 바이너리 파일들의 정보를 볼 때 쓰임
  • objdump로 수행 가능한 작업은 크게 바이너리 덤프ELF 파일 디스어셈블로 나눌 수 있음

주요 Flag Options

  • objdump -f <filename> : 파일 포맷, 아키텍처, 플래그, 시작 주소에 대한 정보 출력
  • objdump -d<filename> : 파이르이 실행 영역을 디스어셈블해서 출력
  • objdump -D <filename> : 파일의 모든 영역을 디스어셈블해서 출력
  • objdump -h <filename> : 섹션 헤더의 정보를 출력
  • objdump -t <filename> : 파일의 심볼 테이블을 출력

  1. C 기반 쉘 실행 코드 작성
  • C의 execve 함수를 이용해 쉘을 여는 간단한 실행 코드 작성 후 64비트로 컴파일

2. 디스어셈블링

  • 컴파일 후 생성된 바이너리 파일을 디버거로 열고, main 함수 분석

3. system call에 필요한 부분만 어셈블리어로 구현

  • 디버거로 분석한 내용을 바탕으로 execve(”/bin/sh”, 0, 0)를 호출할 어셈블리어 코드 작성

4. 컴파일

  • 작성한 어셈블리어 코드를 실행 파일로 생성 후 실행

5. objdump로 OP Code 출력

  • objdump로 바이너리 파일의 OP Code 출력

6. Null Byte(0x00) 제거

  • objdump로 OP Code(기계어) 확인 결과, Null Byte가 존재하는 것을 확인

7. Null Byte(0x00)제거

  • string Null Byte를 제거하기 위해서 코듣 변경 ; /bin/sh → /bin/sh
  • 변경된 코드로 실행 파일을 생성해, objdump로 확인해 보면 Null Byte가 존재하지 않음

8. 최종 OP Code를 하나의 문자열로 연결

  • OP Code를 하나의 문자열로 연결하고, 실행하기 위한 테스트 코드 작성
  • 작성한 코드를 컴파일 해 쉘이 열리는 것을 확인

'Pwnable' 카테고리의 다른 글

Integer Overflow  (0) 2025.11.19
Format String Bug  (0) 2025.11.19
Buffer Overflow  (0) 2025.11.19
Pwnable 방법론  (0) 2025.11.19
리눅스 & 어셈블리어  (0) 2025.11.19