1. 실습에 사용할 간단한 코드 준비
1.1 간단한 코드 작성
cat > basic.c
#include <stdio.h>
int main() {
int sum = 0;
int val1 = 1;
int val2 = 2;
sum = val1 + val2;
printf("1 + 2 = %d\n", sum);
}
1.2 컴파일
gcc -o basic basic.c -no-pie
2. gdb 사용법
기본적으로 해당 글에서는 pwngdb가 설치 되어 있다는 가정 하에 진행하도록 하겠습니다. 만약에 pwngdb가 설치되어 있지 않으신 분들은 제 글에서 시스템 105를 검색하셔서 elf, pe, pwngdb 설치 방법 등을 숙지 하시고 오시길 바랍니다. 또한 리눅스에서 gdb를 사용하는 법에 대한 글이라 elf 파일을 다룰 것 입니다.
2.1 ELF 파일 분석
ELF 헤더
ELF는 리눅스는 실행파일의 형식으로 ELF (Executable and Linkable Format)를 의미합니다. ELF는 크게 헤더와 여러 섹션들로 구성되어 있습니다. 헤더에는 실행에 필요한 여러 정보가 적혀 있고, 섹션들에는 기계어 코드, 문자열 등 여러가지 데이터가 포함되어 있습니다.
ELF 헤더 분석 방법
1) readelf 명령어
readelf -h 실행파일 이름
readelf -h basic.exe
exe는 윈도우 실행파일 확장자입니다. 편의를 위해서 임시로 표현하였습니다.
해당 명령어를 사용하게 되면 elf 파일에서 헤더정보를 읽을 수 있습니다. 여기서 중요한 부분은 Entry point address입니다. 프로그램이 실행 시 어느 주소부터 시작할지 알 수 있습니다.

여기서 readelf -h와 실제 실행 주소가 다르신 분들은 gcc로 컴파일 하실 때 -no-pie 옵션을 주지 않았기 떄문입니다. pie는 프로그램이 실행될 때마다 다른 실행 주소에서 실행하도록 되어있는 보호 기법임으로, 실제 파일을 분석할 때 잠시 기법을 해제하도록 하겠습니다.
2) gdb - entry 명령어
gdb에서도 마찬가지로 진입점을 확인할 수 있다. gdb에서 entry 명령어를 사용하게 되면 시작점을 알 수 있다.
2.2 gdb 명령어 사용
중단점, 시작
기본적으로 run 즉 r 명령어를 통해서 프로그램을 실행시킬 수 있습니다. 중단점이 없다면 실제로 프로그램을 실행시키는 것 처럼 프로그램이 실행되게 됩니다. gdb에서는 break -> b / continue -> c 명령어 등을 통해 디버깅 포인트를 지정할 수 있습니다.
gdb 명령어
명령어 | 예시 | 설명 |
b : break | 1. b *main b *0x메모리 주소 b +2 |
1. 메인 함수에 중단점을 겁니다. 2. 메모리 주소에 중단점을 겁니다. 3. 현재 행에서 2개 뒤의 행에 break point를 겁니다. |
c : continue | c | 다시 프로그램을 진행합니다. |
r | r | 프로그램을 실행합니다. |
si | step into | 함수를 호출하게 될 경우 함수 내부까지 접근할 수 있습니다. |
ni | next instruction | 다음 행으로 이동합니다. |
i | info | 정보를 알려줍니다. i break 등으로 사용할 수 있습니다. |
disass : disassemble | disass main | 함수의 어샘블리 코드를 볼 수 있습니다. |
u | u | 가까운 주소의 어샘블리 코드를 보여줍니다. |
x : examine | x/ 이후로 o : 8진수 x : 16진수 u : unsigned decimal t : binary f : float a: address i : instruction c : char s : string g : giant ( 8 bytes ) w : word *예시 1. x /10x $rip 2. x /s 0x1234 3. x /10i $rip |
가상 메모리에 존재하는 값을 분석할 수 있습니다. x를 이용하면 내가 원하는 부분에서 어떠한 형식으로 데이터를 읽을지 전달할 수 있습니다. *예시 해석 1. 주어진 메모리 주소에서 16진수 형태로 4바이트 10개를 표시합니다. 2. 0x1234 메모리 주소에 있는 문자열을 출력합니다. 3. rip가 가르키는 곳 부터 10줄의 어샘블리 명령어를 출력합니다. |
tele : telescope | tele | 메모리가 참조하는 주소를 재귀적으로 탐색하여 값을 나타냅니다. |
vmmap | vmmap | 가상 메모리 레이아웃을 보여줍니다. |
info | 1. info b 2. info locals 3. info variables |
1. break point 정보 출력 2. 현재 상태에서 지역변수 출력 3. 현재 상태에서 전역변수 조회 가능 |
finish | finish | si로 들어왔을 때 함수를 수행하고 빠져나옴 |
return | return | si로 들어왔을 때 함수를 수행하지 않고 빠져나옴 |
jump | jump *014124 | 해당 주소로 jump하여 인스트럭션을 수행 |
p : print | 1. p [val] 2. p [func name] |
1. 변수 값을 출력 2. 함수 주소를 출력 |
해당 내용은 많이 사용하는 내용을 관련해서 적은 것이고, 더 많은 명령어들이 존재합니다 .필요에 따라서 추가하거나 변형해서 사용하시면 됩니다.
2.3 gdb와 python을 이용하여 매개변수 전달하기
일반적으로 실행 파일 도중에 매개변수를 통하여 값을 입력 받는 경우가 많이 존재합니다. 그때마다 gdb실행 도중 값을 입력할 수 있지만. 어떤 값이 들어가야 할지 모르기 때문에 python을 이용해서 값을 넣는 경우가 많습니다.
이때 run 명령어와 함께 $() 를 사용하게 되면 값을 전달할 수 있습니다.
r <<< $(python -c "print '\xde\xad\xbe\xef'")
이상으로 gdb를 사용해서 분석할 때 알아야 할 매우 기본적인 사항들과 gdb 명령어 예시를 알아보았습니다.

'System 관련 CS > 시스템 해킹을 위한 기초 지식' 카테고리의 다른 글
[ 시스템 105 ] 실행파일의 종류 (PE파일, ELF파일)를 알아보고 gdb, pwndbg 플러그인 설치해보자 (0) | 2023.08.01 |
---|---|
[시스템 104] System Call (시스템 콜) (0) | 2022.09.07 |
[시스템 103] x86-64 어샘블리 기초지식 ( x86-64 assembly ) (0) | 2022.09.06 |
[시스템 102] 레지스터? x86-64 레지스터 분석 (0) | 2022.09.06 |
[시스템 101] Process Memory 프로세스 메모리 분석 (0) | 2022.09.05 |