pwntools 사용법


pwntools 설치

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


위와 같이 pwntools를 설치하면 python3 명령을 쳐서 from pwn import * 을 입력하고 엔터를 눌렀을 때 아무것도 나오지 않으면 잘 설치된 것이다.


process & remote

  • process 함수는 익스플로잇을 로컬 바이너리를 대상으로 할 때 사용하는 함수
  • remote 함수는 원격 서버를 대상으로 할 때 사용하는 함수
from pwn import *
p = process('./test')  
p = remote('example.com', 31337)  # example.com 사이트의 31337 포트 대상


send

  • 데이터를 프로세스에 전송하기 위해 사용
from pwn import *
p = process('./test')

p=send(b'A') #b'A' 입력
p=sendline(b'A') #b'A' 입력후 개행문자(엔터)
p=sendafter(b'hello', b'A') #hello를 출력하면 A입력
p=sendlineafter(b'hello', b'A') #hello를 출력하면 A와 개행문자 입력


recv

  • 데이터를 받기 위해 사용
  • recv(n)recvn(n) 의 차이점은 recv는 데이터를 n만큼 받지 못해도 오류가 발생하지 않지만 recvn은 인자의 n만큼 정확히 데이터를 받지 못하면 계속 기다림
from pwn import *
p = process('./test')

data = p.recv(1024) # 데이터를 최대 1024 바이트까지 받아서 data에 저장
data = p.recvline() # p가 출력하는 데이터를 개행문자를 만날 때까지 받아서 data 저장
data = p.recvn(5) # p가 출력하는 데이터를 5바이트만 받아서 data 저장
data = p.recvuntil(b'hello') # p가 b'hello'를 출력할 때까지 데이터를 수신하여 data 저장
data = p.recvall() # p가 출력하는 데이터를 프로세스가 종료될 때까지 받아서 data 저장


packing & unpacking

  • 익스플로잇을 작성하다 어떤 값을 리틀 엔디언의 바이트 배열로 변경하거나 역의 과정을 거쳐야 할 때 사용
from pwn import *

s32 = 0x41424344
s64 = 0x4142434445464748

print(p32(s32))
print(p64(s64))

s32 = b"ABCD"
s64 = b"ADBDEFGH"

print(hex(u32(s32)))
print(hex(u64(s64)))

image-20240404013328538


interactive

  • 셸을 획득했거나 익스플로잇의 특정 상황에 직접 입력을 주면서 출력을 확인하고 싶을 때 사용하는 함수
from pwn import *
p = process('./test')
p.interactive()


ELF

  • ELF 헤더에는 익스플로잇에 사용될 수 있는 각종 정보가 기록되어 있음
  • pwntools를 사용하면 이 정보들을 쉽게 참조할 수 있음
from pwn import *
e = ELF('./test')
puts_plt = e.plt['puts'] # ./test에서 puts()의 PLT주소를 찾아서 puts_plt에 저장
read_got = e.got['read'] # ./test에서 read()의 GOT주소를 찾아서 read_got에 저장


context.log

  • 익스플로잇에 버그가 발생하면 익스플로잇도 디버깅 해야 함
  • pwntools에는 디버그의 편의를 돕는 로깅 기능이 존재
  • 로그 레벨은 context.log_level 변수로 조절 가능
from pwn import *
context.log_level = 'error' # 에러만 출력
context.log_level = 'debug' # 대상 프로세스와 익스플로잇간에 오가는 모든 데이터를 화면에 출력
context.log_level = 'info' # 비교적 중요한 정보들만 출력


context.arch

  • pwntools는 셸코드를 생성하거나, 코드를 어셈블, 디스어셈블하는 기능 등을 가지고 있는데, 이들은 공격 대상 아키텍처에 영향을 받음
  • pwntools는 아키텍처 정보를 프로그래머가 지정할 수 있게 하며, 이 값에 따라 몇몇 함수들의 동작이 달라짐
from pwn import *
context.arch = "amd64" #x86-64
context.arch = "i386" #x86
context.arch = "arm"


shellcraft

  • pwntools에는 자주 사용되는 셸 코드들이 저장되어 있어, 공격에 필요한 셸 코드를 쉽게 꺼내 쓸 수 있음
  • 매우 편리한 기능이지만, 정적으로 생성된 셸 코드는 셸 코드가 실행될 때의 메모리 상태를 반영하지 못함
  • 프로그램에 따라 입력할 수 있는 셸 코드의 길이나 구성 가능한 문자 종류 제한 조건도 반영하기 어려움
  • 제약 조건이 존재하는 상황은 직접 작성하는 것이 좋음

  • 이 사이트에서 여러 종류의 셸 코드를 찾아볼 수 있음 https://docs.pwntools.com/en/stable/shellcraft/amd64.html

image-20240404014859411


asm

  • pwntools 도구는 어셈블 기능을 지원하는데, 이 기능을 사용할 때 아키텍처를 미리 지정해야 함

image-20240404042720175

댓글남기기