[Dreamhack] pwngdb & pwntools

securitykss·2022년 10월 25일
0

이 글은 https://dreamhack.io/lecture/courses/55, https://dreamhack.io/lecture/courses/59 을 토대로 작성한 글입니다.

1. Introduction

개발자들은 디버거(Debugger)를 통해서 프로그램을 실행할 때 어떤 문제(혹은 Bug)가 있는지 확인해서 버그(Bug)가 발생한 부분을 고친다.
이러한 디버거(Debugger)는 해커의 입장에서 버그(Bug)를 찾고, 즉, 취약점을 찾고, 그에 맞는 취약점 공격(Exploit) 코드를 작성을 한다.

리눅스 환경에서의 디버거(Debugger)gdb(GNU debugger)가 있다.
gdb 는 시간이 지남에 따라 pwndbg, gdb-peda, gef 같은 더 보기 편한 gdb들이 등장했다.

이번 시간에는 이런 gdb 중에서도 pwndbg에 대해서 알아보자.

또한, 취약점 공격(Exploit)을 더 편하게 도와주는 tool인 Pwntools에 대해 소개하려고 한다. (Python 환경)

2. pwngdb

2.1 gdb 설정

gdb는 여러 종류의 gdb가 있다고 언급했다.

그렇다면 이런 gdb의 설정을 어떻게 할까?

리눅스는 실행파일의 형식을 ELF(Executable and Linkable Format)으로 규정한다.

vim 편집기로 gdbinit의 설정을 바꾸어 주면 된다.

위와 같이 경로를 설정하고, 어떤 gdb를 쓸 것인지 설정해 주면 된다. 아무것도 설정하지 않는다면 기본 gdb를 쓰게 된다.

2.2 명령어

gdb 실행

gdb [filename]을 하면 gdb 실행이 된다.
gdb -q [filename]을 하면 gdb 실행 시 버전 정보 등을 출력하지 않게 해준다.

start

start는 elf파일의 main에 breakpoint(중단점)을 걸고 실행을 한다.

main에 break가 걸린 모습을 확인 할 수 있다.

r(run)

run은 elf파일을 실행한다. 만약 breakpoint(중단점)이 있다면 머무른다.

b(break) [function] or [address]

break는 breakpoint(중단점)을 생성해 준다.

c(continue)

continue는 중단된 프로그램을 계속 실행시킨다. 만약, 프로그램 실행중에 다시 breakpoint(중단점)이 있다면, 그 breakpoint(중단점)까지 실행한다.

disassemble [function] or [address]

disassemble은 함수 혹은, 특정 주소를 disassemble 해준다.
disassemble 외에 실행중에는 u, nearpc을 사용하여 disassemble을 할 수 있다.

ni(next into) [n]

프로그램 실행 중, breakpoint(중단점)에 도달하면, ni는 한 줄씩 실행한다. n을 명시 하면, n 줄을 실행한다.
만약 실행 중에 함수 호출을 한다면, 함수 안으로 들어가지 않는다.

si(step into) [n]

프로그램 실행 중, breakpoint(중단점)에 도달하면, si는 한 줄씩 실행한다. n을 명시 하면, n 줄을 실행한다.
만약 실행 중에 함수 호출을 한다면, 함수 안으로 들어간다.

finish

프로그램 실행 중, si로 함수 안에 들어 갔을 경우, 함수를 끝내고 싶을 때, finish로 함수를 끝낼 수 있다.

delete [n]

n을 설정 하면 특정 breakpoint(중단점)만 삭제하고, 설정하지 않는다면 전체 breakpoint(중단점)을 삭제한다.

x/[n][option] [register] or [address]

주소 혹은 레지스터에 어떤 값, 혹은 어떤 string이 저장되어 있는지 확인해 준다.
[n]은 몇 개를 볼 것인지 정해주고, [option]으로는 x(hex), d(decimal), s(string) 등 여러 [option]이 있다.

info regi(register) [regi name]

[regi name]에 아무 것도 넣지 않는다면, 전체 레지스터를 보여주고, [regi name]에 특정 레지스터를 넣어준다면, 특정 레지스터 값만 확인한다.

tele(telescope)

메모리 덤프 기능 중 하나이다. 메모리 값들을 보여주고, 메모리가 참조하고 있는 주소를 재귀적으로 탐색해서 값을 보여준다.

vmmap

가삼 메모리의 레이아웃을 보여준다. 파일이 매핑된 영역일 경우, 해당 파일의 경로까지 보여준다.

q(quit)

gdb를 종료한다.

2.3 pwndbg 장점

breakpoint에 도착하면 Register, Disasemble, Stack, Backtrace를 한번에 보여줘 분석하기 편하다.

3. Pwntools

3.1 python3 & pwntools

pwtools은 python 환경에서 사용한다.

python3와 pwntools 설치 방법을 알아보자.

python3 설치: 'apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential'

pwntools 설치: python3 -m pip install --upgrade pip

                           python3 -m pip install --upgrade pwntools

3.2 pwntools 사용법

from pwn import *

pwntools을 import 시켜 pwntools의 함수들을 사용할 수 있게 한다.

process

로컬 바이너리를 대상으로 할 때 사용하는 함수이다.

사용법

from pwn import *
p = process('./[filename]')

로컬 파일 시스템에 있는 [filename]을 실행한다.

remote

원격 서버를 대상으로 할 때 사용하는 함수이다.

사용법

from pwn import *
p = remote('[server]',[port])

[server]에 열려있는 [port]에 연결을 한다.

send

send는 데이터를 프로세스에 전송하기 위해 사용한다.

사용법

from pwn import *
p = process('./ex')
p.send('A')                                        // ./ex에 'A'입력
p.sendline('A')                                  // ./ex에 'A' + '\n'을 입력
p.sendafter('hello', 'A')                    // ./ex가 'hello'를 출력하면 'A' 입력
p.sendlineafter('hello', 'A')              // ./ex가 'hello'를 출력하면 'A' + '\n'입력

recv

recv는 프로세스에서 데이터를 받기 위해 사용한다.

사용법

from pwn import *
p = process('./ex')
data = p.recv(1024)                             //p가 출력하는 데이터를 최대 1024바이트까지 받아서 data에 저장
data = p.recvline()                               //p가 출력하는 데이터를 개행문자를 만날 때까지 받아서 data에 저장
data = p.recvn(5)                                 //p가 출력하는 데이터를 5바이트만 받아서 data에 저장
data = p.recvuntil('hello')                   //p가 출력하는 데이터를 'hello'가 출력될 때까지 받아서 data에 저장
data = p.recvall()                                 //p가 출력하는 데이터를 프로세스가 종료될 받아서 data에 저장

packing

데이터를 리틀 엔디안 방식으로 값 패킹
p8,p16,p32,p64는 각각 1,2,4,8 바이트를 패킹한다.

사용법

s64 = 0x4142434445464748
print(p64(s64))

결과: b'HGFEDCBA'

unpacking

데이터를 리틀 엔디안 방식으로 값 언패킹
u8,u16,u32,u64는 각각 1,2,4,8 바이트를 언패킹한다.

사용법

s64 = "ABCDEFGH"
print(hex(u64(s64)))

결과: 0x4847464544434241

interactive

셸을 획득했거나, 익스플로잇의 특정 상황에 직접 입력을 주면서 출력을 확인하고 싶을 때 사용하는 함수

사용법

from pwn import *
p = process('./test')
p.interactive()

ELF

elf 헤더에는 여러 정봐 존재한다. pwntools의 ELF를 사용하여 쉽게 참조 가능하다.

사용법

e = ELF('./ex') 으로 선언
e.plt, e.got, e.bss, e.symbols, e.search, e.read, e.write 등 여러 데이터들을 참조하여 익스플로잇을 좀 더 쉽게 할 수 있다.
ELF 사용법은 문제를 풀면서 익혀보자.

context.log

익스플로잇에 버그를 확인할 수 있게 해준다.

사용법

from pwn import *
context.log_level = 'error'        // 에러만 출력
context.log_level = 'debug'     // 대상 프로세스와 익스플로잇간에 오가는 모든 데이터를 화면에 출력
context.log_level = 'info'         // 비교적 중요한 정보들만 출력

context.arch

[Dreamhack] 1. Background: 2 - Computer Architecture(https://velog.io/@securitykss/Dreamhack-1.-Background-2-Computer-Architecture)에서
여러 종류의 Architecture가 있다고 언급한 적이 있다.
pwntools에서는 공격 대상의 Architecture 정보를 직접 지정할 수 있게 한다.

사용법

from pwn import *
context.arch = "amd64"      // x86-64 아키텍처
context.arch = "i386"          // x86 아키텍처
context.arch = "arm"          // arm 아키텍처

shellcraft

shellcraft는 어떤 시스템 콜을 사용할지 정하면 shellcode를 작성해주는 함수이다.
shellcraft는 익스플로잇에서 자주 사용하는 것 중 하나이며, 편하게 익스플로잇 코드를 작성할 수 있게 해준다.

사용법

sh1 = shellcraft.sh() // shell을 실행하는 shellcode
sh2 = shellcraft.open() // open을 실행하는 shellcode
sh3 = shellcraft.read() // read를 실행하는 shellcode
sh4 = shellcraft.write() // write를 실행하는 shellcode

이 외에도 여러 shellcraft의 기능들이 있다.

asm

asm은 어셈블 기능을 하는 함수이다.

사용법

결과

4. Conclusion

pwngdb: 취약점을 찾게 도와주는 디버거.

disassemble, run, start, break, ni, si 등 여러 명령어가 존재.

pwntools: 취약점을 발견하면, 그에 따른 익스플로잇 코드를 작성. 그 익스플로잇을 좀 더 쉽게 해주는 tool.

remote, process, send, recv, shellcraft 등 여러 함수 존재

마치며

여기까지 pwndbg, pwntools에 대한 설명 및 사용법에 대해 간단하게 알아 보았다.

이 외에도 여러 명령어 및 사용법들이 있다.

다음 시간에는 shellcode에 대해 알아보자.

Reference

https://dreamhack.io/lecture/courses/55
https://dreamhack.io/lecture/courses/59
https://velog.io/@2rlo/pwntools-%EC%82%AC%EC%9A%A9%EB%B2%95

profile
보안 공부를 하는 학생입니다.

0개의 댓글