Add content from: Crafting a Full Exploit RCE from a Crash in Autodesk Revit R...

This commit is contained in:
HackTricks News Bot 2025-10-08 18:38:59 +00:00
parent 425badfacc
commit b9b5cb4f0d
2 changed files with 117 additions and 3 deletions

View File

@ -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 objects 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. Its 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}}

View File

@ -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 dont match the ECC. Therefore, naïvely editing the compressed bytes wont 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 Revits 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 Revits 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 nonpolymorphic 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}}