mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Add content from: Crafting a Full Exploit RCE from a Crash in Autodesk Revit R...
This commit is contained in:
		
							parent
							
								
									425badfacc
								
							
						
					
					
						commit
						b9b5cb4f0d
					
				| @ -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}} | ||||
|  | ||||
| @ -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}} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user