pwntools#
pwntools는 시스템 해킹 문제를 풀 때 자주 사용하는 Python 라이브러리예요.
프로그램을 실행하거나, 원격 서버에 연결하거나, 데이터를 주고받는 작업을 편하게 할 수 있게 도와줘요.
시스템 해킹 문제에서는 보통 프로그램에 특정 입력을 보내서 취약점을 발생시키고, 원하는 동작을 하도록 만들어야 해요. 이때 매번 직접 nc로 연결해서 입력을 넣는 것은 불편하기 때문에 pwntools를 사용해 자동화해요.
예를 들어 원격 서버에 연결할 때는 다음과 같이 사용할 수 있어요.
from pwn import *
p = remote("mizuki.guru", 1108) # nc mizuki.guru 1108
# Nothing special just netcat server? maybe?
p.recvuntil(b">")
p.sendline(b"hello")
print(p.recvline())
p.close()py로컬에 있는 바이너리를 실행할 때는 process()를 사용해요.
from pwn import *
p = process("./chall")
p.sendline(b"A" * 40)
print(p.recvall().decode())pypwntools에서 자주 사용하는 함수는 다음과 같아요.
p.send(data) # 데이터를 그대로 보냄
p.sendline(data) # 데이터 뒤에 개행을 붙여서 보냄
p.recv(n) # n바이트만큼 받음
p.recvline() # 한 줄을 받음
p.recvuntil(data) # 특정 문자열이 나올 때까지 받음
p.interactive() # 직접 터미널처럼 상호작용py또한 주소를 payload에 넣을 때는 p64() 같은 함수를 많이 사용해요.
64비트 환경에서는 주소를 little endian 형태로 넣어야 하는데, p64()가 이를 자동으로 처리해줘요.
payload = b"A" * 72
payload += p64(0x4011f6)py반대로 바이너리에서 나온 값을 정수로 바꿀 때는 u64()를 사용할 수 있어요.
leak = p.recv(8)
addr = u64(leak)py즉, pwntools는 exploit 코드를 작성할 때 반복적으로 필요한 연결, 송수신, 주소 변환 등을 쉽게 해주는 도구예요.
shellcode#
shellcode는 공격자가 원하는 동작을 하도록 만든 작은 기계어 코드예요.
이름에 shell이 들어가는 이유는 예전부터 /bin/sh 같은 쉘을 실행시키는 코드가 자주 사용되었기 때문이에요.
예를 들어 취약한 프로그램이 스택에 있는 데이터를 코드처럼 실행할 수 있다면, 공격자는 입력으로 shellcode를 넣고 실행 흐름을 그 위치로 돌려서 원하는 명령을 실행할 수 있어요.
하지만 일반적인 C 코드 형태로는 바로 실행할 수 없기 때문에, shellcode는 보통 바이트 형태로 작성돼요.
shellcode = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68"py이런 바이트들은 CPU가 직접 해석할 수 있는 명령어들이에요.
사람이 직접 전부 작성하기는 어렵기 때문에 pwntools에서는 shellcraft 기능을 제공해요.
from pwn import *
context.arch = "amd64"
shellcode = asm(shellcraft.sh())
print(shellcode)py여기서 shellcraft.sh()는 쉘을 실행하는 어셈블리 코드를 만들어주고, asm()은 그 어셈블리 코드를 실제 바이트 코드로 변환해줘요.
shellcode를 이용한 공격은 보통 다음과 같은 흐름으로 이루어져요.
- 버퍼에 shellcode를 넣어요.
- RET 주소를 shellcode가 있는 위치로 덮어요.
- 함수가 return될 때 shellcode가 실행돼요.
- 원하는 동작이 실행돼요.
예시 payload는 다음과 비슷한 형태가 될 수 있어요.
payload = shellcode
payload += b"A" * (offset - len(shellcode))
payload += p64(shellcode_address)py하지만 요즘 시스템에서는 shellcode 실행을 막기 위한 보호 기법들이 많이 적용되어 있어요. 대표적으로 NX가 있어요.
NX는 스택이나 힙 같은 메모리 영역을 실행 불가능하게 만드는 보호 기법이에요.
NX가 켜져 있으면 스택에 shellcode를 넣어도 코드로 실행할 수 없기 때문에, 단순한 shellcode 공격은 실패해요.
이런 경우에는 shellcode를 직접 실행하는 대신 ROP(Return Oriented Programming) 같은 다른 기법을 사용해야 해요.
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAg4c/dn4BitGH1/xNjKoKEp97I2b
eU57QXvkDBEdNNrEMAAAATYmxvZy5pbW55YS5uZy9wb3N0cwAAAAAAAAAGc2hhNTEyAAAA
UwAAAAtzc2gtZWQyNTUxOQAAAEA7jRLsrS71jpvJKR01y9xKqntdLudYQldbo/8RYjt1WI
EUkP8rxxY3JlGm85XF6IKuiFLZE+F/fxFTx2pBB6AA
-----END SSH SIGNATURE-----