pwntools 간단 사용법

컴컴한해커·2025년 1월 19일

시스템 해킹

목록 보기
1/6

📌 pwntools 간단 사용법

📢 process & remote

process : 익스플로잇을 로컬 바이너리(응용 프로그램)를 대상으로 할 때 사용하는 함수
remote : 원격 서버를 대상으로 사용하는 함수

from pwn import *
p = process('./test')	# test 바이너리 파일을 대상으로 익스플로잇 수행
p = remote('example.com',31337)	# 'example.com'의 31337 포트로 실행 중인 프로세스를 대상으로 익스플로잇

📢 send

send : 데이터를 프로세스에 전송하기 위해 사용

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

p.send(b'A')	#./test에 b'A'를 입력
p.sendline(b'A)	#./test에 b'A' + b'\n'을 입력
p.sendafter(b'hello',b'A')	#./test가 b'hello'를 출력하면, b'A'를 입력
p.sendlineafter(b'hello',b'A')	#./test가 b'hello'를 출력하면, b'A'+b'\n'을 입력

📢 recv

recv : 프로세스에서 데이터를 받기 위해 사용

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

data = p.recv(1024)	# p가 출력하는 데이터를 최대 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

Little Endian --> Bing Endian : unpacking
Big Endian --> Little Endian : packing

from pwn import *

s32 = 0x41424344

print(p32(s32))
# 결과 : b'DCBA' : Little -> Big

s32 = b"ABCD"

print(hex(u32(s32)))
# 결과 : 0x4847464544434241 : Big -> Little

📢 interactive

interactive : 익스플로잇의 특정 상황에서 직접 입력을 주면서 출력을 확인하고 싶을 때 사용

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

📢 ELF

ELF : 리눅스 운영체제의 실행 파일 포맷인 ELF 헤더의 정보를 참조

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에 저장
binsh = next(e.search(b'/bin/sh'))	#./test에서 '/bin/sh'의 주소를 찾아서 binsh에 저장

📢 context.log

context.log_level 변수로 레벨을 조절하여 context.log에 로그 작성

from pwn import *
context.log_level = 'error'	# error만 출력
context.log_level = 'debug' # 프로세스와 익스플로잇간에 오가는 모든 데이터를 화면에 출력
context.log_level = 'info' # 비교적 중요한 정보들만 출력 --> 중요함의 기준이 뭘까?

📢 context.arch

코드를 어셈블, 디스어셈블 기능을 대상 컴퓨터 구조에 맞게 지정

from pwn import *
context.arch = "amd64"
context.arch = "i386"
context.arch = "arm"

📢 shellcraft

shellcraft : 자주 사용되는 shellcode를 쉽게 꺼내 쓸 수 있게 해줌

from pwn import *
context.arch = "amd64"

code = shellcraft.sh()	# shell을 실행하는 shell code
print(code)

# 결과
# $ python3 shellcraft.py
#     /* execve(path='/bin///sh', argv=['sh'], # envp=0) */
#     /* push b'/bin///sh\x00' */
#     push 0x68
#     mov rax, 0x732f2f2f6e69622f
#     ...
#     syscall

📢 asm

asm : 어셈블 기능( 어셈블리어 -> 기계어)

from pwn import *
context.arch = "amd64"

code = shellcraft.sh()
code = asm(code)	# shell code를 기계어로 어셈블
print(code)	

# 결과
# $ python3 asm.py
# b'jhH\xb8/bin///sPH\x89\xe7hri\x01\x01\x814$\x01\x01\x01\x011\xf6Vj\x08^H\x01\xe6VH\x89\xe61\xd2j;X\x0f\x05'

📢 fmtstr_payload()

fmtstr_payload : format string bug를 사용할 때 따로 페이로드 작성을 할 필요 없이 이 함수를 사용하면 바로 제작된다.
단, 항상 된다는 보장은 없으니 맹신하지는 말 것. format string bug 페이로드도 작성할 줄 알아야 한다.

from pwn import *

payload = fmtstr_payload(오프셋 인자, { 주소, 덮을 값})

📢 Canary Leak

Canary = u64(b'\x00' + p.recv(7))

이외 더 많은 함수들을 보고 싶으면
https://docs.pwntools.com/en/stable/globals.html
에서 찾아볼 것

0개의 댓글