Post

Pwntools 사용법

pwntoosl는 CTF Framwork 및 Exploit development 라이브러리로 Python을 통해 사용할 수 있다. Wargame이나 CTF를 풀때 원격의 서버에 Raw Data(Exploit 등을 위한 hex 데이터나 Byte)를 전송할 때 주로 사용한다. 원격 뿐만 아니라 로컬의 Process에도 사용이 가능하다. pwntools 사용 시 보통 Python2 를 사용하지만, Python3도 지원이 가능하다. 문제풀이에 필요한 데이터를 받거나 보내기가 가능하며, Interactive Shell도 제공한다. Data Encodine/Decoding 등, 정말 많은 기능을 제공하는데 해당 포스팅에서는 기본적인 부분만 다룬다. —

Connection (Tubes)

Exploit을 위해 로컬이나 원격에 데이터를 송/수신을 해야한다. 이 때 대상에 따라 아래와 같이 객체로 생성하여 데이터 송/수신이 가능하다.

Local Process

로컬 프로세스에 연결하려면 process() 객체에 바이너리나 프로세스 명을 입력하여 생성한다.

1
2
3
4
5
from pwn import *

p = process('./prcess_name')
p.recvline()
# 'Hello, world\n'

Remote

remote() 를 통해 Host와 Port명을 입력하면 원격으로 연결이 가능하다.

1
2
3
4
5
6
from pwn import *

io = remote('google.com', 80)
io.send('GET /\r\n\r\n')
io.recvline()
# 'HTTP/1.0 200 OK\r\n'

SSH

ssh를 통해 프로세스에 접근할 수 있다. 아래와 같이 ssh() 통해 로그인 후 session을 통해 process에 접근이 가능하다.

1
2
3
4
5
6
7
from pwn import *

session = ssh('user', 'host', password='password')

sp = session.process('process')
sp.recvline()
# 'Hello, world!\n'

Serial Port

시리얼 포트도 지원을 한다.

1
2
3
from pwn import *

s = serialtube('/dev/ttyUSB0', baudrate=115200)

Basic IO

Receiving Data

  • recv(n) - n만큼 데이터를 수신한다.
  • recvline() - 개행을 만날 때 까지 데이터를 수신한다.
  • recvuntil(data) - 특정 데이터(문자열, 정수 등)을 만날 때 까지 데이터를 수신한다.
  • recvregex(pattern) - 정규표현식에 해당 하는 패턴을 만날 때 까지 데이터를 수신한다.
  • recvrepeat(timeout) - 타임아웃이 발생할 때 까지 데이터를 수신한다.
  • clear() - 버퍼에 있는 데이터를 제거한다.

Sending Data

  • send(data) - 데이터를 송신한다. 수신 측에서 Read() 함수를 사용할 경우 주로 사용한다.
  • sendline(data) - 데이터 끝에 개행(new line)을 포함시켜 데이터를 송신한다. 수신 측에서 scanf(), gets(), fget() 등을 사용할 때 사용한다.

Utility Functions

데이터를 변환하여 송/수신할 경우가 많기 때문에 아래와 같은 함수를 알고있으면 도움이 된다.

Packing/Unpacking

데이터(정수)를 16/32/64 bit로 Packing/Unpacking 해주는 함수로 Hex 데이터를 전달할 때 용이하다. endian이나 bits는 context에 정의가 가능하여 함수마다 매개변수로 지정하지 않고 환경변수처럼 사용이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pack(1234) # '\xd2\x04\x00\x00'
unpack('\xd2\x04\x00\x00') # 1234

# 32bit
p32(1234) # '\xd2\x04\x00\x00'
u32('\xd2\x04\x00\x00') # 1234

# 64bit
p64(1234) # '\xd2\x04\x00\x00\x00\x00\x00\x00'
u64('\xd2\x04\x00\x00\x00\x00\x00\x00') # 1234

# Endian
p32(1234, endian='big') # '\x00\x00\x04\xd2'
u32('\x00\x00\x04\xd2', endian='big') # 1234
u32('\x00\x00\x04\xd2') # 3523477504 / 엔디안 설정을 잘못할 경우 잘못된 값 출력

hex(unpack('AAAA')) # '0x41414141'

Hex

Hex Encoding과 Decoding 기능도 제공한다.

1
2
3
4
enhex('hello')
# '68656c6c6f'
unhex('776f726c64')
# 'world'

Base64

Base64 Encoding과 Decoding이 가능하다.

1
2
b64e('hello') # 'aGVsbG8='
b64d('aGVsbG8=') # 'hello'

Hashes

Hash같은 경우에 md5와 sha1등을 제공한다.

1
2
3
4
md5sumhex('hello') == '5d41402abc4b2a76b9719d911017c592'
# md5filehex()는 파일을 읽어서 해당 md5를 구한다.
md5filehex(File) == '5d41402abc4b2a76b9719d911017c592'
sha1sumhex('hello') == 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'

URL Encoding

1
urlencode("Hello, World!") == '%48%65%6c%6c%6f%2c%20%57%6f%72%6c%64%21'

참고

Github Repository : PWNTOOLS

Document : Docs - pwntools

This post is licensed under CC BY 4.0 by the author.