process : 익스플로잇을 로컬 바이너리(응용 프로그램)를 대상으로 할 때 사용하는 함수
remote : 원격 서버를 대상으로 사용하는 함수
from pwn import *
p = process('./test') # test 바이너리 파일을 대상으로 익스플로잇 수행
p = remote('example.com',31337) # 'example.com'의 31337 포트로 실행 중인 프로세스를 대상으로 익스플로잇
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 : 프로세스에서 데이터를 받기 위해 사용
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에 저장
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 : 익스플로잇의 특정 상황에서 직접 입력을 주면서 출력을 확인하고 싶을 때 사용
from pwn import *
p = p.process('./test')
p.interactive()
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_level 변수로 레벨을 조절하여 context.log에 로그 작성
from pwn import *
context.log_level = 'error' # error만 출력
context.log_level = 'debug' # 프로세스와 익스플로잇간에 오가는 모든 데이터를 화면에 출력
context.log_level = 'info' # 비교적 중요한 정보들만 출력 --> 중요함의 기준이 뭘까?
코드를 어셈블, 디스어셈블 기능을 대상 컴퓨터 구조에 맞게 지정
from pwn import *
context.arch = "amd64"
context.arch = "i386"
context.arch = "arm"
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 : 어셈블 기능( 어셈블리어 -> 기계어)
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 : format string bug를 사용할 때 따로 페이로드 작성을 할 필요 없이 이 함수를 사용하면 바로 제작된다.
단, 항상 된다는 보장은 없으니 맹신하지는 말 것. format string bug 페이로드도 작성할 줄 알아야 한다.
from pwn import *
payload = fmtstr_payload(오프셋 인자, { 주소, 덮을 값})
Canary = u64(b'\x00' + p.recv(7))
이외 더 많은 함수들을 보고 싶으면
https://docs.pwntools.com/en/stable/globals.html
에서 찾아볼 것