#!/home/username/project/venv/bin/python
를 주고 스크립트에 실행 권한을 주면 항상 venv 가상 환경의 python으로 실행되어 python 깨짐 없이 pwntools를 사용할 수 있다.
process()
로컬 프로그램을 실행하여 통신할 때 사용하는 함수로, 인자로 통신할 프로그램의 경로를 전달하면 해당 프로그램과 연결을 맺어줌
from pwn import *
p = process("./binary")
pwnlib.tubes class를 반환하고 해당 클래스에는 데이터를 통신하는데 필요한 여러 멤버 함수들이 있다.
추가적으로, 프로그램에 인자를 전달하고 환경 변수도 설정할 수 있다.
from pwn import *
p = process(["./binary", "arg"], env={"LD_PRELOAD":"./libc.so.6"})
remote()
프로그램이 아닌, host의 domain 또는 IP 주소와 port 번호를 인자로 받아 원격 서버에 통신할 때 사용되는 함수이다. process와 같이 pwnlib.tubes 클래스를 반환 값으로 받는다.
from pwn import *
r - remote("ctf.kr", 1337)
마찬가지로 인자를 넣어줄 수 있는데, typ 인자로 통신 프로토콜을 바꿀 수 있다.
ssh()
SSH 서버에 접속하여 통신하기 위한 함수로,
사용자 이름, host ip, port 번호, 사용자 비밀번호를 인자로 전달해주어야 한다.
recv(), send()
생성된 pwnlib.tubes 클래스를 통해, 데이터를 수신, 송신하기 위해 사용한다. 해당 함수들은 데이터를 bytes 형태로 수신/송신한다.
recv의 경우 인자로 받을 byte수를 지정할 수 있다. 그만큼의 데이터를 받지 못하게 되면, 당장 받을 수 있는 만큼 수신한 후 함수를 종료하게 된다.
send의 경우, bytes 형태를 인자로 받아 전송하며, sendafter 또는 sendlineafter 함수는 인자로 전달된 데이터가 나올 때까지 데이터를 수신하고 그 이후 데이터를 전송한다.
inetractive()
터미널에서 사용자가 실시간으로 데이터를 수신하고 전송할 수 있게 하는 함수이다. 터미널을 통해 프로세스에 사용자가 원하는 입력 값을 표준 입력으로 전달할 수 있게 되고 프로세스의 출력도 실시간으로 터미널에 표시되어 마치 터미널에서 직접 프로그램을 실행시켜 조작하는 것과 비슷한 효과를 준다.
ctrl + D 를 통해 프로세스와의 연결을 끊어 통신을 종료할 수 있다.
close()
pwnlib.tubes 클래스 객체 내부 자원을 정리하고 연결을 종료할 때 사용한다. 단, interactive를 호출한 경우 함수 종료될 때 연결이 같이 종료되기에 close를 추가적으로 호출할 일은 없다.
conetxt.log_level
로그 출력의 상세한 정도를 설정할 수 있는데,
'debug' : 송수신 데이터, 내부 변수 등 모두 출력
'error' : 에러 메시지만 출력
'info' : 디폴트 설정이며, 일반적인 상태 메시지가 출력된다.
Packing
시스템 해킹에서는 정수 값을 bytes 클래스로 변환하거나 그 반대의 행위가 자주 필요하기에 pwntools에서 관련 기능을 제공한다.
p64() : 숫자를 bytes 클래스로 패킹 (64bit)
u64() : bytes 클래스를 숫자로 언패킹 (64bit)
little endian을 기반으로 동작하며, 인자로 endian을 설정해주어야 big endian으로 사용이 가능하다.
from pwn import *
s32 = 0x41424344
print(p32(s32))
b'DCBA'
기타
gdb.attach()process(), remote()로 생성한 객체 또는 프로세스의 pid를 인자로 넣으면 gdb 디버거를 프로세스에 붙여 디버깅을 수행할 수 있는 상태가 된다.pause()context.arch 및 asmcontext.arch = "amd64" #x86-64 arch 아키텍처를 설정하였다면 asm(), disasm()으로 어셈블과 디스어셈블을 수행할 수 있다. code = asm('mov eax, 0')
asm_code = disasm(code)ELFpwnlib.elf.elf.ELF를 반환한다.e = ELF("./example")
print(hex(e.symbols['write']))
print(hex(e.symbols.write)) symbols는 doctdict 클래스로, dictionary처럼 사용할수도, 객체 속성처럼 사용할 수도 있다. 위 클래스에서 제공하는 주소는 가상 주소이다. PIE가 설정되어 있다면 상대 가상 주소를 제공한다.linux 환경에서 존재하는 다양한 바이너리 보호 기법을 파악할 때 사용하는 도구이다. 총 4개의 기법에 대해서 적용 여부를 파악할 수 있다.
그 외로 바이너리의 아키텍처, 파일 경로, RWX가 가능한 segment 정보, 즉 읽기 쓰기 실행 권한이 모두 허용된 메모리 영역이 있는지를 알려준다.
RWX flag를 가진 세그먼트는 shellcode 삽입의 타깃이 되기도 하기에 보안 상 취약점이 될 수 있다.