System Hacking/Basics

[시스템 해킹] pwntools 사용법

hanbunny 2025. 3. 7. 20:26

먼저 실습을 위한 test 파일을 만들어줌.

nano test.c // test.c 파일 생성

대충 이런 내용이 들어가 있음.

 

gcc -o test test.c -no-pie -g // test.c 파일 컴파일

 

process

로컬 실행 파일(지금은 test)을 실행하고 조작할 수 있도록 해주는 함수

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

 

remote

원격 서버를 대상으로 할 때 사용

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에 저장

 

 

packing & unpacking

숫자를 바이트 형식으로 변환하거나, 반대로 바이트 데이터를 숫자로 변환

nano pup.py // 실습할 pup.py 파일 생성

pup.py

 

출력 결과

 

interactive

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

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

 

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에 저장

 

context.log

익스플로잇에 버그가 발생하면 익스플로잇도 디버깅 해야한다. pwntools에는 디버그의 편의를 돕는 로깅 기능이 있고 로그 레벨은 context.log_level 변수로 조절가능.

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

 

context.arch

아키텍처 정보를 프로그래머가 지정

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

 

shellcraft

직접 셸 코드를 작성

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

 

asm

어셈블 기능( 아키텍처를 미리 지정해야함)

$ 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'