From b9b5cb4f0d26a2b8145acebc8ddba9643648517d Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Wed, 8 Oct 2025 18:38:59 +0000 Subject: [PATCH] Add content from: Crafting a Full Exploit RCE from a Crash in Autodesk Revit R... --- .../stack-pivoting-ebp2ret-ebp-chaining.md | 31 +++++++ .../office-file-analysis.md | 89 ++++++++++++++++++- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md index dafc5af1c..77a9eac5b 100644 --- a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md +++ b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md @@ -229,6 +229,36 @@ A robust pivot strategy used in many CTFs/exploits: 2) Return into a pivot gadget (`leave ; ret`, `pop rsp`, `xchg rax, rsp ; ret`) to move RSP to that region. 3) Continue with the staged chain (e.g., leak libc, call `mprotect`, then `read` shellcode, then jump to it). +### Windows: Destructor-loop weird-machine pivots (Revit RFA case study) + +Client-side parsers sometimes implement destructor loops that indirectly call a function pointer derived from attacker-controlled object fields. If each iteration offers exactly one indirect call (a “one-gadget” machine), you can convert this into a reliable stack pivot and ROP entry. + +Observed in Autodesk Revit RFA deserialization (CVE-2025-5037): + +- Crafted objects of type `AString` place a pointer to attacker bytes at offset 0. +- The destructor loop effectively executes one gadget per object: + +```asm +rcx = [rbx] ; object pointer (AString*) +rax = [rcx] ; pointer to controlled buffer +call qword ptr [rax] ; execute [rax] once per object +``` + +Two practical pivots: + +- Windows 10 (32-bit heap addrs): misaligned “monster gadget” that contains `8B E0` → `mov esp, eax`, eventually `ret`, to pivot from the call primitive to a heap-based ROP chain. +- Windows 11 (full 64-bit addrs): use two objects to drive a constrained weird-machine pivot: + - Gadget 1: `push rax ; pop rbp ; ret` (move original rax into rbp) + - Gadget 2: `leave ; ... ; ret` (becomes `mov rsp, rbp ; pop rbp ; ret`), pivoting into the first object’s buffer, where a conventional ROP chain follows. + +Tips for Windows x64 after the pivot: + +- Respect the 0x20-byte shadow space and maintain 16-byte alignment before `call` sites. It’s often convenient to place literals above the return address and use a gadget like `lea rcx, [rsp+0x20] ; call rax` followed by `pop rax ; ret` to pass stack addresses without corrupting control flow. +- Non-ASLR helper modules (if present) provide stable gadget pools and imports such as `LoadLibraryW`/`GetProcAddress` to dynamically resolve targets like `ucrtbase!system`. +- Creating missing gadgets via a writable thunk: if a promising sequence ends in a `call` through a writable function pointer (e.g., DLL import thunk or function pointer in .data), overwrite that pointer with a benign single-step like `pop rax ; ret`. The sequence then behaves like it ended with `ret` (e.g., `mov rdx, rsi ; mov rcx, rdi ; ret`), which is invaluable to load Windows x64 arg registers without clobbering others. + +For full chain construction and gadget examples, see the reference below. + ## Modern mitigations that break stack pivoting (CET/Shadow Stack) Modern x86 CPUs and OSes increasingly deploy **CET Shadow Stack (SHSTK)**. With SHSTK enabled, `ret` compares the return address on the normal stack with a hardware-protected shadow stack; any mismatch raises a Control-Protection fault and kills the process. Therefore, techniques like EBP2Ret/leave;ret-based pivots will crash as soon as the first `ret` is executed from a pivoted stack. @@ -304,5 +334,6 @@ Also in the following page you can see the equivalent of **Ret2esp in ARM64**: - 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP. - Linux kernel documentation: Control-flow Enforcement Technology (CET) Shadow Stack — details on SHSTK, `nousershstk`, `/proc/$PID/status` flags, and enabling via `arch_prctl`. https://www.kernel.org/doc/html/next/x86/shstk.html - Microsoft Learn: Kernel Mode Hardware-enforced Stack Protection (CET shadow stacks on Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection +- [Crafting a Full Exploit RCE from a Crash in Autodesk Revit RFA File Parsing (ZDI blog)](https://www.thezdi.com/blog/2025/10/6/crafting-a-full-exploit-rce-from-a-crash-in-autodesk-revit-rfa-file-parsing) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md index b32d4206d..5354b00ea 100644 --- a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md @@ -18,7 +18,90 @@ sudo pip3 install -U oletools olevba -c /path/to/document #Extract macros ``` +--- + +## OLE Compound File exploitation: Autodesk Revit RFA – ECC recomputation and controlled gzip + +Revit RFA models are stored as an [OLE Compound File](https://learn.microsoft.com/en-us/windows/win32/stg/istorage-compound-file-implementation) (aka CFBF). The serialized model is under storage/stream: + +- Storage: `Global` +- Stream: `Latest` → `Global\Latest` + +Key layout of `Global\Latest` (observed on Revit 2025): + +- Header +- GZIP-compressed payload (the actual serialized object graph) +- Zero padding +- Error-Correcting Code (ECC) trailer + +Revit will auto-repair small perturbations to the stream using the ECC trailer and will reject streams that don’t match the ECC. Therefore, naïvely editing the compressed bytes won’t persist: your changes are either reverted or the file is rejected. To ensure byte-accurate control over what the deserializer sees you must: + +- Recompress with a Revit-compatible gzip implementation (so the compressed bytes Revit produces/accepts match what it expects). +- Recompute the ECC trailer over the padded stream so Revit will accept the modified stream without auto-repairing it. + +Practical workflow for patching/fuzzing RFA contents: + +1) Expand the OLE compound document + +```bash +# Expand RFA into a folder tree (storages → folders, streams → files) +CompoundFileTool /e model.rfa /o rfa_out +# rfa_out/Global/Latest is the serialized stream of interest +``` + +2) Edit Global\Latest with gzip/ECC discipline + +- Deconstruct `Global/Latest`: keep the header, gunzip the payload, mutate bytes, then gzip back using Revit-compatible deflate parameters. +- Preserve zero-padding and recompute the ECC trailer so the new bytes are accepted by Revit. +- If you need deterministic byte-for-byte reproduction, build a minimal wrapper around Revit’s DLLs to invoke its gzip/gunzip paths and ECC computation (as demonstrated in research), or re-use any available helper that replicates these semantics. + +3) Rebuild the OLE compound document + +```bash +# Repack the folder tree back into an OLE file +CompoundFileTool /c rfa_out /o model_patched.rfa +``` + +Notes: + +- CompoundFileTool writes storages/streams to the filesystem with escaping for characters invalid in NTFS names; the stream path you want is exactly `Global/Latest` in the output tree. +- When delivering mass attacks via ecosystem plugins that fetch RFAs from cloud storage, ensure your patched RFA passes Revit’s integrity checks locally first (gzip/ECC correct) before attempting network injection. + +Exploitation insight (to guide what bytes to place in the gzip payload): + +- The Revit deserializer reads a 16-bit class index and constructs an object. Certain types are non‑polymorphic and lack vtables; abusing destructor handling yields a type confusion where the engine executes an indirect call through an attacker-controlled pointer. +- Picking `AString` (class index `0x1F`) places an attacker-controlled heap pointer at object offset 0. During the destructor loop, Revit effectively executes: + +```asm +rcx = [rbx] ; object pointer (e.g., AString*) +rax = [rcx] ; attacker-controlled pointer to AString buffer +call qword ptr [rax] ; one attacker-chosen gadget per object +``` + +- Place multiple such objects in the serialized graph so each iteration of the destructor loop executes one gadget (“weird machine”), and arrange a stack pivot into a conventional x64 ROP chain. + +See Windows x64 pivot/gadget building details here: + +{{#ref}} +../../../binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md +{{#endref}} + +and general ROP guidance here: + +{{#ref}} +../../../binary-exploitation/rop-return-oriented-programing/README.md +{{#endref}} + +Tooling: + +- CompoundFileTool (OSS) to expand/rebuild OLE compound files: https://github.com/thezdi/CompoundFileTool +- IDA Pro + WinDBG TTD for reverse/taint; disable page heap with TTD to keep traces compact. +- A local proxy (e.g., Fiddler) can simulate supply-chain delivery by swapping RFAs in plugin traffic for testing. + +## References + +- [Crafting a Full Exploit RCE from a Crash in Autodesk Revit RFA File Parsing (ZDI blog)](https://www.thezdi.com/blog/2025/10/6/crafting-a-full-exploit-rce-from-a-crash-in-autodesk-revit-rfa-file-parsing) +- [CompoundFileTool (GitHub)](https://github.com/thezdi/CompoundFileTool) +- [OLE Compound File (CFBF) docs](https://learn.microsoft.com/en-us/windows/win32/stg/istorage-compound-file-implementation) + {{#include ../../../banners/hacktricks-training.md}} - - -