~ 간단한 코드로 gdb 실습을 해 보자 ~
ctrl + f
1. 코드 작성
2. 코드 컴파일
3. 디버깅 시작
4. 파이썬 이용
5. 명령어 정리
코드 작성
// Name: debugee.c
// Compile: gcc -o debugee debugee.c -no-pie
#include <stdio.h>
int main(void) {
int sum = 0;
int val1 = 1;
int val2 = 2;
sum = val1 + val2;
printf("1 + 2 = %d\\n", sum);
return 0;
}
vi 편집기를 이용했음. 참고로 리눅스에서 C언어 코딩 하려면
vi (파일명).c로 생성하고, i (insert) 눌러서 작성, 코드 다 입력한 뒤에는 esc 입력하고 :wq로 저장함
vi (파일명).c
// i(insert)누르고 입력하면 됨
// 저장할 땐 esc 누르고 :wq 입력해서 터미널 창으로 돌아옴
코드 컴파일
gcc (파일명) -o (컴파일 후 만들어질 파일명)
디버깅 시작
gdb (컴파일 된 파일명)
ex) gdb debugee
start 명령어를 진행하고 나서 DISASM 영역의 화살표를 보면 현재 rip값을 알 수 있는데,
0x121b값을 가리키고 있다.
pwndbg는 주요 메모리들의 상태를 프로그램이 실행되고 있는 맥락(context)이라고 부르며,
context는 크게 4개의 영역으로 구분된다.
registers | 레지스터의 상태를 보여준다. |
disasm | rip부터 여러 줄에 걸쳐 디스어셈블된 결과를 보여준다. |
stack | rsp붙 여러 줄에 걸쳐 스택의 값들을 보여준다. |
backtrace | 현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출됐는지 보여준다. |
break : 특정 주소에 중단점(break point)을 설정하는 기능
continue : 중단된 프로그램을 계속 실행시키는 기능
run : 단순히 프로그램을 실행 시킴
//gdb의 명령어 축약
b: break
c: continue
r: run
si: step into
ni: next instruction
i: info
k: kill
pd: pdisas
disassemble : gdb가 기본적으로 제공하는 디스어셈블 명령어로,
함수 이름을 인자로 전달하면 해당 함수가 반환될 때 까지 전부 디스어셈블하여 보여준다.
ni : 어셈블리 명령어를 한 줄 실행 / call을 통해 서브루틴을 호출하는 경우 - 내부로 들어가지 않음
si(step into): 어셈블리 명령어를 한 줄 실행 / call을 통해 서브루틴을 호출하는 경우 - 내부로 들어감
ni로 원래 실행 흐름으로 돌아가기 어려울 때에는 finish 명령어를 이용하여 함수의 끝까지 한번에 실행함
pwndbg 명령어 예시
1. rsp부터 80바이트를 8바이트씩 hex 형식으로 출력
pwdbg> x/19gx $rsp
2. rip부터 5줄의 어셈블리 명령어 출력
pwndbg> x/5i $rip
3. 특정 주소의 문자열 출력
pwndbg> x/s 0x400000
파이썬 이용
gdb를 통해 디버깅하는 경우, 숫자와 알파벳이 아닌 값을 입력하려면
파이썬으로 입력값을 생성한 다음 사용해야함
(사용한 코드)
// 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;
}
python argv run의 명령어로 $()와 함께 파이썬 코드를 입력하면 값을 전달할 수 있음 |
python input run의 명령어로 $()와 함께 파이썬 코드를 입력, 입력값으로 전달하려면 <<< 사용 |
r $(python -c 'print "\xff"*100) | r $(python -c 'print "\xff"*100') <<< $(python -c 'print "dreamhack"') |
명령어 정리
start : 진입점에 중단점을 설정하고 실행함
break(b) : 중단점 설정
continue(c): 계속 실행
disassemble: 디스어셈블 결과 출력
u, nearpc, pd: 디스어셈블 결과를 가독성 좋게 출력
x: 메모리 조회
run(r): 프로그램 처음부터 실행
context: 레지스터, 코드, 스택, 백트레이스의 상태 출력
nexti(ni): 명령어 실행, 함수 내부로는 들어가지 않음
stepi(si): 명령어 실행, 함수 내부로 들어감
telescope(tele): 메모리 조회, 메모리값이 포인터일 경우 재귀적으로 따라가며 모든 메모리값 출력
vmmap: 메모리 레이아웃 출력
'INTERLUDE ✦ > 2022 SYSTEM STUDY' 카테고리의 다른 글
[ DreamHack ] ShellCode (0) | 2022.11.03 |
---|---|
[ DreamHack ] Shell_basic 풀이 (0) | 2022.11.01 |
pwndbg, pwntools 설치 (0) | 2022.10.04 |
[ DreamHack ] 동적 분석 연습 1 (0) | 2022.09.29 |
[ DreamHack ] x86 Assembly (0) | 2022.09.25 |