1use std::collections::HashMap;
2
3use crate::memory::Region;
4use crate::regex::Regex;
5use object::{
6 coff::{CoffHeader, SymbolTable},
7 pe::{self, ImageDosHeader, ImageNtHeaders32, ImageNtHeaders64},
8 read::pe::{
9 DataDirectories, DelayLoadImportTable, ExportTable, ImageNtHeaders, ImageOptionalHeader,
10 ImageThunkData, ImportTable, ImportThunkList, ResourceDirectory,
11 ResourceDirectoryEntryData, ResourceNameOrId, RichHeaderInfo,
12 },
13 FileKind, LittleEndian as LE, StringTable,
14};
15
16use super::{
17 EvalContext, Module, ModuleData, ModuleDataMap, ScanContext, StaticValue, Type, Value,
18};
19
20mod debug;
21mod ord;
22#[cfg(feature = "authenticode")]
23mod signatures;
24pub mod utils;
25mod version_info;
26
27const MAX_PE_SECTIONS: usize = 96;
28const MAX_PE_IMPORTS: usize = 16384;
29const MAX_PE_EXPORTS: usize = 16384;
30const MAX_EXPORT_NAME_LENGTH: usize = 512;
31const MAX_IMPORT_DLL_NAME_LENGTH: usize = 256;
32const MAX_RESOURCES: usize = 65536;
33const MAX_NB_DATA_DIRECTORIES: usize = 32768;
34const MAX_NB_VERSION_INFOS: usize = 32768;
35
36#[derive(Debug)]
38pub struct Pe;
39
40#[repr(u8)]
41enum ImportType {
42 Standard = 0b0001,
43 Delayed = 0b0010,
44}
45
46impl Module for Pe {
47 fn get_name(&self) -> &'static str {
48 "pe"
49 }
50
51 fn get_static_values(&self) -> HashMap<&'static str, StaticValue> {
52 #[allow(clippy::cast_possible_wrap)]
53 #[allow(clippy::large_stack_arrays)]
54 HashMap::from([
55 (
56 "MACHINE_UNKNOWN",
57 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_UNKNOWN.into()),
58 ),
59 (
60 "MACHINE_AM33",
61 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_AM33.into()),
62 ),
63 (
64 "MACHINE_AMD64",
65 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_AMD64.into()),
66 ),
67 (
68 "MACHINE_ARM",
69 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_ARM.into()),
70 ),
71 (
72 "MACHINE_ARMNT",
73 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_ARMNT.into()),
74 ),
75 (
76 "MACHINE_ARM64",
77 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_ARM64.into()),
78 ),
79 (
80 "MACHINE_EBC",
81 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_EBC.into()),
82 ),
83 (
84 "MACHINE_I386",
85 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_I386.into()),
86 ),
87 (
88 "MACHINE_IA64",
89 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_IA64.into()),
90 ),
91 (
92 "MACHINE_M32R",
93 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_M32R.into()),
94 ),
95 (
96 "MACHINE_MIPS16",
97 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_MIPS16.into()),
98 ),
99 (
100 "MACHINE_MIPSFPU",
101 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_MIPSFPU.into()),
102 ),
103 (
104 "MACHINE_MIPSFPU16",
105 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_MIPSFPU16.into()),
106 ),
107 (
108 "MACHINE_POWERPC",
109 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_POWERPC.into()),
110 ),
111 (
112 "MACHINE_POWERPCFP",
113 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_POWERPCFP.into()),
114 ),
115 (
116 "MACHINE_R4000",
117 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_R4000.into()),
118 ),
119 (
120 "MACHINE_SH3",
121 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_SH3.into()),
122 ),
123 (
124 "MACHINE_SH3DSP",
125 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_SH3DSP.into()),
126 ),
127 (
128 "MACHINE_SH4",
129 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_SH4.into()),
130 ),
131 (
132 "MACHINE_SH5",
133 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_SH5.into()),
134 ),
135 (
136 "MACHINE_THUMB",
137 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_THUMB.into()),
138 ),
139 (
140 "MACHINE_WCEMIPSV2",
141 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_WCEMIPSV2.into()),
142 ),
143 (
144 "MACHINE_TARGET_HOST",
145 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_TARGET_HOST.into()),
146 ),
147 (
148 "MACHINE_R3000",
149 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_R3000.into()),
150 ),
151 (
152 "MACHINE_R10000",
153 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_R10000.into()),
154 ),
155 (
156 "MACHINE_ALPHA",
157 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_ALPHA.into()),
158 ),
159 (
160 "MACHINE_SH3E",
161 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_SH3E.into()),
162 ),
163 (
164 "MACHINE_ALPHA64",
165 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_ALPHA64.into()),
166 ),
167 (
168 "MACHINE_AXP64",
169 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_AXP64.into()),
170 ),
171 (
172 "MACHINE_TRICORE",
173 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_TRICORE.into()),
174 ),
175 (
176 "MACHINE_CEF",
177 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_CEF.into()),
178 ),
179 (
180 "MACHINE_CEE",
181 StaticValue::Integer(pe::IMAGE_FILE_MACHINE_CEE.into()),
182 ),
183 (
184 "SUBSYSTEM_UNKNOWN",
185 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_UNKNOWN.into()),
186 ),
187 (
188 "SUBSYSTEM_NATIVE",
189 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_NATIVE.into()),
190 ),
191 (
192 "SUBSYSTEM_WINDOWS_GUI",
193 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_WINDOWS_GUI.into()),
194 ),
195 (
196 "SUBSYSTEM_WINDOWS_CUI",
197 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_WINDOWS_CUI.into()),
198 ),
199 (
200 "SUBSYSTEM_OS2_CUI",
201 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_OS2_CUI.into()),
202 ),
203 (
204 "SUBSYSTEM_POSIX_CUI",
205 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_POSIX_CUI.into()),
206 ),
207 (
208 "SUBSYSTEM_NATIVE_WINDOWS",
209 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_NATIVE_WINDOWS.into()),
210 ),
211 (
212 "SUBSYSTEM_WINDOWS_CE_GUI",
213 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI.into()),
214 ),
215 (
216 "SUBSYSTEM_EFI_APPLICATION",
217 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_EFI_APPLICATION.into()),
218 ),
219 (
220 "SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER",
221 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER.into()),
222 ),
223 (
224 "SUBSYSTEM_EFI_RUNTIME_DRIVER",
225 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER.into()),
226 ),
227 (
228 "SUBSYSTEM_EFI_ROM_IMAGE",
229 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_EFI_ROM.into()),
230 ),
231 (
232 "SUBSYSTEM_XBOX",
233 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_XBOX.into()),
234 ),
235 (
236 "SUBSYSTEM_WINDOWS_BOOT_APPLICATION",
237 StaticValue::Integer(pe::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION.into()),
238 ),
239 (
240 "HIGH_ENTROPY_VA",
241 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA.into()),
242 ),
243 (
244 "DYNAMIC_BASE",
245 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE.into()),
246 ),
247 (
248 "FORCE_INTEGRITY",
249 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY.into()),
250 ),
251 (
252 "NX_COMPAT",
253 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_NX_COMPAT.into()),
254 ),
255 (
256 "NO_ISOLATION",
257 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_NO_ISOLATION.into()),
258 ),
259 (
260 "NO_SEH",
261 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_NO_SEH.into()),
262 ),
263 (
264 "NO_BIND",
265 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_NO_BIND.into()),
266 ),
267 (
268 "APPCONTAINER",
269 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_APPCONTAINER.into()),
270 ),
271 (
272 "WDM_DRIVER",
273 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_WDM_DRIVER.into()),
274 ),
275 (
276 "GUARD_CF",
277 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_GUARD_CF.into()),
278 ),
279 (
280 "TERMINAL_SERVER_AWARE",
281 StaticValue::Integer(pe::IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE.into()),
282 ),
283 (
284 "RELOCS_STRIPPED",
285 StaticValue::Integer(pe::IMAGE_FILE_RELOCS_STRIPPED.into()),
286 ),
287 (
288 "EXECUTABLE_IMAGE",
289 StaticValue::Integer(pe::IMAGE_FILE_EXECUTABLE_IMAGE.into()),
290 ),
291 (
292 "LINE_NUMS_STRIPPED",
293 StaticValue::Integer(pe::IMAGE_FILE_LINE_NUMS_STRIPPED.into()),
294 ),
295 (
296 "LOCAL_SYMS_STRIPPED",
297 StaticValue::Integer(pe::IMAGE_FILE_LOCAL_SYMS_STRIPPED.into()),
298 ),
299 (
300 "AGGRESIVE_WS_TRIM",
301 StaticValue::Integer(pe::IMAGE_FILE_AGGRESIVE_WS_TRIM.into()),
302 ),
303 (
304 "LARGE_ADDRESS_AWARE",
305 StaticValue::Integer(pe::IMAGE_FILE_LARGE_ADDRESS_AWARE.into()),
306 ),
307 (
308 "BYTES_REVERSED_LO",
309 StaticValue::Integer(pe::IMAGE_FILE_BYTES_REVERSED_LO.into()),
310 ),
311 (
312 "MACHINE_32BIT",
313 StaticValue::Integer(pe::IMAGE_FILE_32BIT_MACHINE.into()),
314 ),
315 (
316 "DEBUG_STRIPPED",
317 StaticValue::Integer(pe::IMAGE_FILE_DEBUG_STRIPPED.into()),
318 ),
319 (
320 "REMOVABLE_RUN_FROM_SWAP",
321 StaticValue::Integer(pe::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP.into()),
322 ),
323 (
324 "NET_RUN_FROM_SWAP",
325 StaticValue::Integer(pe::IMAGE_FILE_NET_RUN_FROM_SWAP.into()),
326 ),
327 ("SYSTEM", StaticValue::Integer(pe::IMAGE_FILE_SYSTEM.into())),
328 ("DLL", StaticValue::Integer(pe::IMAGE_FILE_DLL.into())),
329 (
330 "UP_SYSTEM_ONLY",
331 StaticValue::Integer(pe::IMAGE_FILE_UP_SYSTEM_ONLY.into()),
332 ),
333 (
334 "BYTES_REVERSED_HI",
335 StaticValue::Integer(pe::IMAGE_FILE_BYTES_REVERSED_HI.into()),
336 ),
337 (
338 "IMAGE_DIRECTORY_ENTRY_EXPORT",
339 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_EXPORT as i64),
340 ),
341 (
342 "IMAGE_DIRECTORY_ENTRY_IMPORT",
343 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_IMPORT as i64),
344 ),
345 (
346 "IMAGE_DIRECTORY_ENTRY_RESOURCE",
347 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_RESOURCE as i64),
348 ),
349 (
350 "IMAGE_DIRECTORY_ENTRY_EXCEPTION",
351 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_EXCEPTION as i64),
352 ),
353 (
354 "IMAGE_DIRECTORY_ENTRY_SECURITY",
355 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_SECURITY as i64),
356 ),
357 (
358 "IMAGE_DIRECTORY_ENTRY_BASERELOC",
359 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_BASERELOC as i64),
360 ),
361 (
362 "IMAGE_DIRECTORY_ENTRY_DEBUG",
363 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_DEBUG as i64),
364 ),
365 (
366 "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE",
367 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_ARCHITECTURE as i64),
368 ),
369 (
370 "IMAGE_DIRECTORY_ENTRY_COPYRIGHT",
371 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_ARCHITECTURE as i64),
372 ),
373 (
374 "IMAGE_DIRECTORY_ENTRY_GLOBALPTR",
375 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_GLOBALPTR as i64),
376 ),
377 (
378 "IMAGE_DIRECTORY_ENTRY_TLS",
379 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_TLS as i64),
380 ),
381 (
382 "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG",
383 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG as i64),
384 ),
385 (
386 "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
387 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT as i64),
388 ),
389 (
390 "IMAGE_DIRECTORY_ENTRY_IAT",
391 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_IAT as i64),
392 ),
393 (
394 "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT",
395 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT as i64),
396 ),
397 (
398 "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
399 StaticValue::Integer(pe::IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as i64),
400 ),
401 (
402 "IMAGE_NT_OPTIONAL_HDR32_MAGIC",
403 StaticValue::Integer(pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC.into()),
404 ),
405 (
406 "IMAGE_NT_OPTIONAL_HDR64_MAGIC",
407 StaticValue::Integer(pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC.into()),
408 ),
409 (
410 "IMAGE_ROM_OPTIONAL_HDR_MAGIC",
411 StaticValue::Integer(pe::IMAGE_ROM_OPTIONAL_HDR_MAGIC.into()),
412 ),
413 (
414 "SECTION_NO_PAD",
415 StaticValue::Integer(pe::IMAGE_SCN_TYPE_NO_PAD.into()),
416 ),
417 (
418 "SECTION_CNT_CODE",
419 StaticValue::Integer(pe::IMAGE_SCN_CNT_CODE.into()),
420 ),
421 (
422 "SECTION_CNT_INITIALIZED_DATA",
423 StaticValue::Integer(pe::IMAGE_SCN_CNT_INITIALIZED_DATA.into()),
424 ),
425 (
426 "SECTION_CNT_UNINITIALIZED_DATA",
427 StaticValue::Integer(pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA.into()),
428 ),
429 (
430 "SECTION_LNK_OTHER",
431 StaticValue::Integer(pe::IMAGE_SCN_LNK_OTHER.into()),
432 ),
433 (
434 "SECTION_LNK_INFO",
435 StaticValue::Integer(pe::IMAGE_SCN_LNK_INFO.into()),
436 ),
437 (
438 "SECTION_LNK_REMOVE",
439 StaticValue::Integer(pe::IMAGE_SCN_LNK_REMOVE.into()),
440 ),
441 (
442 "SECTION_LNK_COMDAT",
443 StaticValue::Integer(pe::IMAGE_SCN_LNK_COMDAT.into()),
444 ),
445 (
446 "SECTION_NO_DEFER_SPEC_EXC",
447 StaticValue::Integer(pe::IMAGE_SCN_NO_DEFER_SPEC_EXC.into()),
448 ),
449 (
450 "SECTION_GPREL",
451 StaticValue::Integer(pe::IMAGE_SCN_GPREL.into()),
452 ),
453 (
454 "SECTION_MEM_FARDATA",
455 StaticValue::Integer(pe::IMAGE_SCN_MEM_FARDATA.into()),
456 ),
457 (
458 "SECTION_MEM_PURGEABLE",
459 StaticValue::Integer(pe::IMAGE_SCN_MEM_PURGEABLE.into()),
460 ),
461 (
462 "SECTION_MEM_16BIT",
463 StaticValue::Integer(pe::IMAGE_SCN_MEM_16BIT.into()),
464 ),
465 (
466 "SECTION_MEM_LOCKED",
467 StaticValue::Integer(pe::IMAGE_SCN_MEM_LOCKED.into()),
468 ),
469 (
470 "SECTION_MEM_PRELOAD",
471 StaticValue::Integer(pe::IMAGE_SCN_MEM_PRELOAD.into()),
472 ),
473 (
474 "SECTION_ALIGN_1BYTES",
475 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_1BYTES.into()),
476 ),
477 (
478 "SECTION_ALIGN_2BYTES",
479 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_2BYTES.into()),
480 ),
481 (
482 "SECTION_ALIGN_4BYTES",
483 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_4BYTES.into()),
484 ),
485 (
486 "SECTION_ALIGN_8BYTES",
487 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_8BYTES.into()),
488 ),
489 (
490 "SECTION_ALIGN_16BYTES",
491 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_16BYTES.into()),
492 ),
493 (
494 "SECTION_ALIGN_32BYTES",
495 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_32BYTES.into()),
496 ),
497 (
498 "SECTION_ALIGN_64BYTES",
499 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_64BYTES.into()),
500 ),
501 (
502 "SECTION_ALIGN_128BYTES",
503 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_128BYTES.into()),
504 ),
505 (
506 "SECTION_ALIGN_256BYTES",
507 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_256BYTES.into()),
508 ),
509 (
510 "SECTION_ALIGN_512BYTES",
511 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_512BYTES.into()),
512 ),
513 (
514 "SECTION_ALIGN_1024BYTES",
515 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_1024BYTES.into()),
516 ),
517 (
518 "SECTION_ALIGN_2048BYTES",
519 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_2048BYTES.into()),
520 ),
521 (
522 "SECTION_ALIGN_4096BYTES",
523 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_4096BYTES.into()),
524 ),
525 (
526 "SECTION_ALIGN_8192BYTES",
527 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_8192BYTES.into()),
528 ),
529 (
530 "SECTION_ALIGN_MASK",
531 StaticValue::Integer(pe::IMAGE_SCN_ALIGN_MASK.into()),
532 ),
533 (
534 "SECTION_LNK_NRELOC_OVFL",
535 StaticValue::Integer(pe::IMAGE_SCN_LNK_NRELOC_OVFL.into()),
536 ),
537 (
538 "SECTION_MEM_DISCARDABLE",
539 StaticValue::Integer(pe::IMAGE_SCN_MEM_DISCARDABLE.into()),
540 ),
541 (
542 "SECTION_MEM_NOT_CACHED",
543 StaticValue::Integer(pe::IMAGE_SCN_MEM_NOT_CACHED.into()),
544 ),
545 (
546 "SECTION_MEM_NOT_PAGED",
547 StaticValue::Integer(pe::IMAGE_SCN_MEM_NOT_PAGED.into()),
548 ),
549 (
550 "SECTION_MEM_SHARED",
551 StaticValue::Integer(pe::IMAGE_SCN_MEM_SHARED.into()),
552 ),
553 (
554 "SECTION_MEM_EXECUTE",
555 StaticValue::Integer(pe::IMAGE_SCN_MEM_EXECUTE.into()),
556 ),
557 (
558 "SECTION_MEM_READ",
559 StaticValue::Integer(pe::IMAGE_SCN_MEM_READ.into()),
560 ),
561 (
562 "SECTION_MEM_WRITE",
563 StaticValue::Integer(pe::IMAGE_SCN_MEM_WRITE.into()),
564 ),
565 (
566 "SECTION_SCALE_INDEX",
567 StaticValue::Integer(pe::IMAGE_SCN_SCALE_INDEX.into()),
568 ),
569 (
570 "RESOURCE_TYPE_CURSOR",
571 StaticValue::Integer(pe::RT_CURSOR.into()),
572 ),
573 (
574 "RESOURCE_TYPE_BITMAP",
575 StaticValue::Integer(pe::RT_BITMAP.into()),
576 ),
577 (
578 "RESOURCE_TYPE_ICON",
579 StaticValue::Integer(pe::RT_ICON.into()),
580 ),
581 (
582 "RESOURCE_TYPE_MENU",
583 StaticValue::Integer(pe::RT_MENU.into()),
584 ),
585 (
586 "RESOURCE_TYPE_DIALOG",
587 StaticValue::Integer(pe::RT_DIALOG.into()),
588 ),
589 (
590 "RESOURCE_TYPE_STRING",
591 StaticValue::Integer(pe::RT_STRING.into()),
592 ),
593 (
594 "RESOURCE_TYPE_FONTDIR",
595 StaticValue::Integer(pe::RT_FONTDIR.into()),
596 ),
597 (
598 "RESOURCE_TYPE_FONT",
599 StaticValue::Integer(pe::RT_FONT.into()),
600 ),
601 (
602 "RESOURCE_TYPE_ACCELERATOR",
603 StaticValue::Integer(pe::RT_ACCELERATOR.into()),
604 ),
605 (
606 "RESOURCE_TYPE_RCDATA",
607 StaticValue::Integer(pe::RT_RCDATA.into()),
608 ),
609 (
610 "RESOURCE_TYPE_MESSAGETABLE",
611 StaticValue::Integer(pe::RT_MESSAGETABLE.into()),
612 ),
613 (
614 "RESOURCE_TYPE_GROUP_CURSOR",
615 StaticValue::Integer(pe::RT_GROUP_CURSOR.into()),
616 ),
617 (
618 "RESOURCE_TYPE_GROUP_ICON",
619 StaticValue::Integer(pe::RT_GROUP_ICON.into()),
620 ),
621 (
622 "RESOURCE_TYPE_VERSION",
623 StaticValue::Integer(pe::RT_VERSION.into()),
624 ),
625 (
626 "RESOURCE_TYPE_DLGINCLUDE",
627 StaticValue::Integer(pe::RT_DLGINCLUDE.into()),
628 ),
629 (
630 "RESOURCE_TYPE_PLUGPLAY",
631 StaticValue::Integer(pe::RT_PLUGPLAY.into()),
632 ),
633 ("RESOURCE_TYPE_VXD", StaticValue::Integer(pe::RT_VXD.into())),
634 (
635 "RESOURCE_TYPE_ANICURSOR",
636 StaticValue::Integer(pe::RT_ANICURSOR.into()),
637 ),
638 (
639 "RESOURCE_TYPE_ANIICON",
640 StaticValue::Integer(pe::RT_ANIICON.into()),
641 ),
642 (
643 "RESOURCE_TYPE_HTML",
644 StaticValue::Integer(pe::RT_HTML.into()),
645 ),
646 (
647 "RESOURCE_TYPE_MANIFEST",
648 StaticValue::Integer(pe::RT_MANIFEST.into()),
649 ),
650 (
651 "IMAGE_DEBUG_TYPE_UNKNOWN",
652 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_UNKNOWN.into()),
653 ),
654 (
655 "IMAGE_DEBUG_TYPE_COFF",
656 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_COFF.into()),
657 ),
658 (
659 "IMAGE_DEBUG_TYPE_CODEVIEW",
660 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_CODEVIEW.into()),
661 ),
662 (
663 "IMAGE_DEBUG_TYPE_FPO",
664 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_FPO.into()),
665 ),
666 (
667 "IMAGE_DEBUG_TYPE_MISC",
668 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_MISC.into()),
669 ),
670 (
671 "IMAGE_DEBUG_TYPE_EXCEPTION",
672 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_EXCEPTION.into()),
673 ),
674 (
675 "IMAGE_DEBUG_TYPE_FIXUP",
676 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_FIXUP.into()),
677 ),
678 (
679 "IMAGE_DEBUG_TYPE_OMAP_TO_SRC",
680 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_OMAP_TO_SRC.into()),
681 ),
682 (
683 "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC",
684 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC.into()),
685 ),
686 (
687 "IMAGE_DEBUG_TYPE_BORLAND",
688 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_BORLAND.into()),
689 ),
690 (
691 "IMAGE_DEBUG_TYPE_RESERVED10",
692 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_RESERVED10.into()),
693 ),
694 (
695 "IMAGE_DEBUG_TYPE_CLSID",
696 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_CLSID.into()),
697 ),
698 (
699 "IMAGE_DEBUG_TYPE_VC_FEATURE",
700 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_VC_FEATURE.into()),
701 ),
702 (
703 "IMAGE_DEBUG_TYPE_POGO",
704 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_POGO.into()),
705 ),
706 (
707 "IMAGE_DEBUG_TYPE_ILTCG",
708 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_ILTCG.into()),
709 ),
710 (
711 "IMAGE_DEBUG_TYPE_MPX",
712 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_MPX.into()),
713 ),
714 (
715 "IMAGE_DEBUG_TYPE_REPRO",
716 StaticValue::Integer(pe::IMAGE_DEBUG_TYPE_REPRO.into()),
717 ),
718 (
719 "IMPORT_DELAYED",
720 StaticValue::Integer((ImportType::Delayed as u8).into()),
721 ),
722 (
723 "IMPORT_STANDARD",
724 StaticValue::Integer((ImportType::Standard as u8).into()),
725 ),
726 ("IMPORT_ANY", StaticValue::Integer(!0)),
727 (
728 "section_index",
729 StaticValue::function(
730 Self::section_index,
731 vec![vec![Type::Bytes], vec![Type::Integer]],
732 Type::Integer,
733 ),
734 ),
735 (
736 "exports",
737 StaticValue::function(
738 Self::exports,
739 vec![vec![Type::Bytes], vec![Type::Integer], vec![Type::Regex]],
740 Type::Integer,
741 ),
742 ),
743 (
744 "exports_index",
745 StaticValue::function(
746 Self::exports_index,
747 vec![vec![Type::Bytes], vec![Type::Integer], vec![Type::Regex]],
748 Type::Integer,
749 ),
750 ),
751 (
752 "imports",
753 StaticValue::function(
754 Self::imports,
755 vec![
756 vec![Type::Bytes, Type::Bytes],
757 vec![Type::Bytes, Type::Integer],
758 vec![Type::Bytes],
759 vec![Type::Regex, Type::Regex],
760 vec![Type::Integer, Type::Bytes, Type::Bytes],
761 vec![Type::Integer, Type::Bytes, Type::Integer],
762 vec![Type::Integer, Type::Bytes],
763 vec![Type::Integer, Type::Regex, Type::Regex],
764 ],
765 Type::Integer,
766 ),
767 ),
768 (
769 "import_rva",
770 StaticValue::function(
771 Self::import_rva,
772 vec![
773 vec![Type::Bytes, Type::Bytes],
774 vec![Type::Bytes, Type::Integer],
775 ],
776 Type::Integer,
777 ),
778 ),
779 (
780 "delayed_import_rva",
781 StaticValue::function(
782 Self::delayed_import_rva,
783 vec![
784 vec![Type::Bytes, Type::Bytes],
785 vec![Type::Bytes, Type::Integer],
786 ],
787 Type::Integer,
788 ),
789 ),
790 (
791 "locale",
792 StaticValue::function(Self::locale, vec![vec![Type::Integer]], Type::Integer),
793 ),
794 (
795 "language",
796 StaticValue::function(Self::language, vec![vec![Type::Integer]], Type::Integer),
797 ),
798 (
799 "is_dll",
800 StaticValue::function(Self::is_dll, vec![], Type::Integer),
801 ),
802 (
803 "is_32bit",
804 StaticValue::function(Self::is_32bit, vec![], Type::Integer),
805 ),
806 (
807 "is_64bit",
808 StaticValue::function(Self::is_64bit, vec![], Type::Integer),
809 ),
810 (
811 "calculate_checksum",
812 StaticValue::function(Self::calculate_checksum, vec![], Type::Integer),
813 ),
814 #[cfg(feature = "hash")]
815 (
816 "imphash",
817 StaticValue::function(Self::imphash, vec![], Type::Bytes),
818 ),
819 (
820 "rva_to_offset",
821 StaticValue::function(
822 Self::rva_to_offset,
823 vec![vec![Type::Integer]],
824 Type::Integer,
825 ),
826 ),
827 ])
828 }
829
830 fn get_dynamic_types(&self) -> HashMap<&'static str, Type> {
831 [
832 ("is_pe", Type::Integer),
833 ("machine", Type::Integer),
835 ("number_of_sections", Type::Integer),
836 ("timestamp", Type::Integer),
837 ("pointer_to_symbol_table", Type::Integer),
838 ("number_of_symbols", Type::Integer),
839 ("size_of_optional_header", Type::Integer),
840 ("characteristics", Type::Integer),
841 ("entry_point", Type::Integer),
843 ("entry_point_raw", Type::Integer),
844 ("image_base", Type::Integer),
845 ("number_of_rva_and_sizes", Type::Integer),
846 ("number_of_version_infos", Type::Integer),
847 ("version_info", Type::dict(Type::Bytes)),
849 (
850 "version_info_list",
851 Type::array(Type::object([("key", Type::Bytes), ("value", Type::Bytes)])),
852 ),
853 ("opthdr_magic", Type::Integer),
855 ("size_of_code", Type::Integer),
856 ("size_of_initialized_data", Type::Integer),
857 ("size_of_uninitialized_data", Type::Integer),
858 ("base_of_code", Type::Integer),
859 ("base_of_data", Type::Integer),
860 ("section_alignment", Type::Integer),
861 ("file_alignment", Type::Integer),
862 (
863 "linker_version",
864 Type::object([("major", Type::Integer), ("minor", Type::Integer)]),
865 ),
866 (
867 "os_version",
868 Type::object([("major", Type::Integer), ("minor", Type::Integer)]),
869 ),
870 (
871 "image_version",
872 Type::object([("major", Type::Integer), ("minor", Type::Integer)]),
873 ),
874 (
875 "subsystem_version",
876 Type::object([("major", Type::Integer), ("minor", Type::Integer)]),
877 ),
878 ("win32_version_value", Type::Integer),
879 ("size_of_image", Type::Integer),
880 ("size_of_headers", Type::Integer),
881 ("checksum", Type::Integer),
882 ("subsystem", Type::Integer),
883 ("dll_characteristics", Type::Integer),
884 ("size_of_stack_reserve", Type::Integer),
885 ("size_of_stack_commit", Type::Integer),
886 ("size_of_heap_reserve", Type::Integer),
887 ("size_of_heap_commit", Type::Integer),
888 ("loader_flags", Type::Integer),
889 (
891 "data_directories",
892 Type::array(Type::object([
893 ("virtual_address", Type::Integer),
894 ("size", Type::Integer),
895 ])),
896 ),
897 (
898 "sections",
899 Type::array(Type::object([
900 ("name", Type::Bytes),
901 ("full_name", Type::Bytes),
902 ("characteristics", Type::Integer),
903 ("virtual_address", Type::Integer),
904 ("virtual_size", Type::Integer),
905 ("raw_data_offset", Type::Integer),
906 ("raw_data_size", Type::Integer),
907 ("pointer_to_relocations", Type::Integer),
908 ("pointer_to_line_numbers", Type::Integer),
909 ("number_of_relocations", Type::Integer),
910 ("number_of_line_numbers", Type::Integer),
911 ])),
912 ),
913 (
914 "overlay",
915 Type::object([("offset", Type::Integer), ("size", Type::Integer)]),
916 ),
917 (
918 "rich_signature",
919 Type::object([
920 ("offset", Type::Integer),
921 ("length", Type::Integer),
922 ("key", Type::Integer),
923 ("raw_data", Type::Bytes),
924 ("clear_data", Type::Bytes),
925 ("version_data", Type::Bytes),
926 (
927 "version",
928 Type::function(
929 vec![vec![Type::Integer], vec![Type::Integer, Type::Integer]],
930 Type::Integer,
931 ),
932 ),
933 (
934 "toolid",
935 Type::function(
936 vec![vec![Type::Integer], vec![Type::Integer, Type::Integer]],
937 Type::Integer,
938 ),
939 ),
940 ]),
941 ),
942 ("number_of_imports", Type::Integer),
943 ("number_of_imported_functions", Type::Integer),
944 ("number_of_delayed_imports", Type::Integer),
945 ("number_of_delayed_imported_functions", Type::Integer),
946 ("number_of_exports", Type::Integer),
947 ("dll_name", Type::Bytes),
949 ("export_timestamp", Type::Integer),
950 (
951 "export_details",
952 Type::array(Type::object([
953 ("offset", Type::Integer),
954 ("name", Type::Bytes),
955 ("forward_name", Type::Bytes),
956 ("ordinal", Type::Integer),
957 ("rva", Type::Integer),
958 ])),
959 ),
960 (
961 "import_details",
962 Type::array(Type::object([
963 ("library_name", Type::Bytes),
964 ("number_of_functions", Type::Integer),
965 (
966 "functions",
967 Type::array(Type::object([
968 ("name", Type::Bytes),
969 ("ordinal", Type::Integer),
970 ("rva", Type::Integer),
971 ])),
972 ),
973 ])),
974 ),
975 (
976 "delayed_import_details",
977 Type::array(Type::object([
978 ("library_name", Type::Bytes),
979 ("number_of_functions", Type::Integer),
980 (
981 "functions",
982 Type::array(Type::object([
983 ("name", Type::Bytes),
984 ("ordinal", Type::Integer),
985 ("rva", Type::Integer),
986 ])),
987 ),
988 ])),
989 ),
990 ("resource_timestamp", Type::Integer),
991 (
992 "resource_version",
993 Type::object([("major", Type::Integer), ("minor", Type::Integer)]),
994 ),
995 (
996 "resources",
997 Type::array(Type::object([
998 ("rva", Type::Integer),
999 ("offset", Type::Integer),
1000 ("length", Type::Integer),
1001 ("type", Type::Integer),
1002 ("id", Type::Integer),
1003 ("language", Type::Integer),
1004 ("type_string", Type::Bytes),
1005 ("name_string", Type::Bytes),
1006 ("language_string", Type::Bytes),
1007 ])),
1008 ),
1009 ("number_of_resources", Type::Integer),
1010 ("pdb_path", Type::Bytes),
1011 #[cfg(feature = "authenticode")]
1012 ("number_of_signatures", Type::Integer),
1013 #[cfg(feature = "authenticode")]
1014 ("is_signed", Type::Integer),
1015 #[cfg(feature = "authenticode")]
1016 (
1017 "signatures",
1018 Type::array(Type::object([
1019 ("thumbprint", Type::Bytes),
1020 ("issuer", Type::Bytes),
1021 ("subject", Type::Bytes),
1022 ("version", Type::Integer),
1023 ("algorithm", Type::Bytes),
1024 ("algorithm_oid", Type::Bytes),
1025 ("serial", Type::Bytes),
1026 ("not_before", Type::Integer),
1027 ("not_after", Type::Integer),
1028 ("verified", Type::Integer),
1029 ("digest_alg", Type::Bytes),
1030 ("digest", Type::Bytes),
1031 ("file_digest", Type::Bytes),
1032 ("number_of_certificates", Type::Integer),
1033 (
1034 "certificates",
1035 Type::array(Type::object([
1036 ("thumbprint", Type::Bytes),
1037 ("issuer", Type::Bytes),
1038 ("subject", Type::Bytes),
1039 ("version", Type::Integer),
1040 ("algorithm", Type::Bytes),
1041 ("algorithm_oid", Type::Bytes),
1042 ("serial", Type::Bytes),
1043 ("not_before", Type::Integer),
1044 ("not_after", Type::Integer),
1045 ])),
1046 ),
1047 (
1048 "signer_info",
1049 Type::object([
1050 ("program_name", Type::Bytes),
1051 ("digest", Type::Bytes),
1052 ("digest_alg", Type::Bytes),
1053 ("length_of_chain", Type::Integer),
1054 (
1055 "chain",
1056 Type::array(Type::object([
1057 ("thumbprint", Type::Bytes),
1058 ("issuer", Type::Bytes),
1059 ("subject", Type::Bytes),
1060 ("version", Type::Integer),
1061 ("algorithm", Type::Bytes),
1062 ("algorithm_oid", Type::Bytes),
1063 ("serial", Type::Bytes),
1064 ("not_before", Type::Integer),
1065 ("not_after", Type::Integer),
1066 ])),
1067 ),
1068 ]),
1069 ),
1070 ("number_of_countersignatures", Type::Integer),
1071 (
1072 "countersignatures",
1073 Type::array(Type::object([
1074 ("verified", Type::Integer),
1075 ("sign_time", Type::Integer),
1076 ("digest", Type::Bytes),
1077 ("digest_alg", Type::Bytes),
1078 ("length_of_chain", Type::Integer),
1079 (
1080 "chain",
1081 Type::array(Type::object([
1082 ("thumbprint", Type::Bytes),
1083 ("issuer", Type::Bytes),
1084 ("subject", Type::Bytes),
1085 ("version", Type::Integer),
1086 ("algorithm", Type::Bytes),
1087 ("algorithm_oid", Type::Bytes),
1088 ("serial", Type::Bytes),
1089 ("not_before", Type::Integer),
1090 ("not_after", Type::Integer),
1091 ])),
1092 ),
1093 ])),
1094 ),
1095 (
1096 "valid_on",
1097 Type::function(vec![vec![Type::Integer]], Type::Integer),
1098 ),
1099 ])),
1100 ),
1101 ]
1102 .into()
1103 }
1104
1105 fn setup_new_scan(&self, data_map: &mut ModuleDataMap) {
1106 data_map.insert::<Self>(Data::default());
1107 }
1108
1109 fn get_dynamic_values(&self, ctx: &mut ScanContext, out: &mut HashMap<&'static str, Value>) {
1110 let Some(data) = ctx.module_data.get_mut::<Self>() else {
1111 return;
1112 };
1113
1114 if data.found_pe {
1115 return;
1117 }
1118
1119 let res = match FileKind::parse(ctx.region.mem) {
1120 Ok(FileKind::Pe32) => {
1121 data.is_32bit = true;
1122 parse_file::<ImageNtHeaders32>(ctx.region, ctx.process_memory, data)
1123 }
1124 Ok(FileKind::Pe64) => {
1125 data.is_32bit = false;
1126 parse_file::<ImageNtHeaders64>(ctx.region, ctx.process_memory, data)
1127 }
1128 _ => None,
1129 };
1130
1131 match res {
1132 Some(values) => {
1133 *out = values;
1134 data.found_pe = true;
1135 }
1136 None => *out = [("is_pe", 0.into())].into(),
1137 }
1138 }
1139}
1140
1141impl ModuleData for Pe {
1142 type PrivateData = Data;
1143 type UserData = ();
1144}
1145
1146fn parse_file<HEADERS: ImageNtHeaders>(
1147 region: &Region,
1148 process_memory: bool,
1149 data: &mut Data,
1150) -> Option<HashMap<&'static str, Value>> {
1151 let dos_header = ImageDosHeader::parse(region.mem).ok()?;
1152 let mut offset = dos_header.nt_headers_offset().into();
1153 let (nt_headers, data_dirs) = HEADERS::parse(region.mem, &mut offset).ok()?;
1154
1155 let sections = utils::SectionTable::new(nt_headers, region.mem, offset);
1156
1157 let hdr = nt_headers.file_header();
1158 let characteristics = hdr.characteristics.get(LE);
1159
1160 if process_memory && (characteristics & pe::IMAGE_FILE_DLL) != 0 {
1161 return None;
1162 }
1163
1164 let symbols = hdr.symbols(region.mem).ok();
1165
1166 let opt_hdr = nt_headers.optional_header();
1167 let ep = opt_hdr.address_of_entry_point();
1168
1169 data.is_dll = characteristics & pe::IMAGE_FILE_DLL;
1171
1172 let entrypoint: Value = if process_memory {
1173 let ep: Option<usize> = ep.try_into().ok();
1174 ep.and_then(|ep| ep.checked_add(region.start)).into()
1175 } else {
1176 sections
1177 .as_ref()
1178 .and_then(|sections| utils::va_to_file_offset(region.mem, sections, ep))
1179 .map_or(-1, i64::from)
1180 .into()
1181 };
1182
1183 let mut map: HashMap<_, _> = [
1184 ("is_pe", Value::Integer(1)),
1185 ("machine", hdr.machine.get(LE).into()),
1187 ("number_of_sections", hdr.number_of_sections.get(LE).into()),
1188 ("timestamp", hdr.time_date_stamp.get(LE).into()),
1189 (
1190 "pointer_to_symbol_table",
1191 hdr.pointer_to_symbol_table.get(LE).into(),
1192 ),
1193 ("number_of_symbols", hdr.number_of_symbols.get(LE).into()),
1194 (
1195 "size_of_optional_header",
1196 hdr.size_of_optional_header.get(LE).into(),
1197 ),
1198 ("characteristics", characteristics.into()),
1199 ("entry_point", entrypoint),
1201 ("entry_point_raw", ep.into()),
1202 ("image_base", opt_hdr.image_base().into()),
1203 (
1204 "number_of_rva_and_sizes",
1205 opt_hdr.number_of_rva_and_sizes().into(),
1206 ),
1207 ("opthdr_magic", opt_hdr.magic().into()),
1209 ("size_of_code", opt_hdr.size_of_code().into()),
1210 (
1211 "size_of_initialized_data",
1212 opt_hdr.size_of_initialized_data().into(),
1213 ),
1214 (
1215 "size_of_uninitialized_data",
1216 opt_hdr.size_of_uninitialized_data().into(),
1217 ),
1218 ("base_of_code", opt_hdr.base_of_code().into()),
1219 ("base_of_data", opt_hdr.base_of_data().into()),
1220 ("section_alignment", opt_hdr.section_alignment().into()),
1221 ("file_alignment", opt_hdr.file_alignment().into()),
1222 (
1223 "linker_version",
1224 Value::object([
1225 ("major", opt_hdr.major_linker_version().into()),
1226 ("minor", opt_hdr.minor_linker_version().into()),
1227 ]),
1228 ),
1229 (
1230 "os_version",
1231 Value::object([
1232 ("major", opt_hdr.major_operating_system_version().into()),
1233 ("minor", opt_hdr.minor_operating_system_version().into()),
1234 ]),
1235 ),
1236 (
1237 "image_version",
1238 Value::object([
1239 ("major", opt_hdr.major_image_version().into()),
1240 ("minor", opt_hdr.minor_image_version().into()),
1241 ]),
1242 ),
1243 (
1244 "subsystem_version",
1245 Value::object([
1246 ("major", opt_hdr.major_subsystem_version().into()),
1247 ("minor", opt_hdr.minor_subsystem_version().into()),
1248 ]),
1249 ),
1250 ("win32_version_value", opt_hdr.win32_version_value().into()),
1251 ("size_of_image", opt_hdr.size_of_image().into()),
1252 ("size_of_headers", opt_hdr.size_of_headers().into()),
1253 ("checksum", opt_hdr.check_sum().into()),
1254 ("subsystem", opt_hdr.subsystem().into()),
1255 ("dll_characteristics", opt_hdr.dll_characteristics().into()),
1256 (
1257 "size_of_stack_reserve",
1258 opt_hdr.size_of_stack_reserve().into(),
1259 ),
1260 (
1261 "size_of_stack_commit",
1262 opt_hdr.size_of_stack_commit().into(),
1263 ),
1264 (
1265 "size_of_heap_reserve",
1266 opt_hdr.size_of_heap_reserve().into(),
1267 ),
1268 ("size_of_heap_commit", opt_hdr.size_of_heap_commit().into()),
1269 ("loader_flags", opt_hdr.loader_flags().into()),
1270 ("data_directories", data_directories(data_dirs)),
1272 (
1273 "sections",
1274 sections.as_ref().map_or(Value::Undefined, |sections| {
1275 sections_to_value(sections, symbols.as_ref().map(SymbolTable::strings), data)
1276 }),
1277 ),
1278 (
1279 "overlay",
1280 sections
1281 .as_ref()
1282 .map_or(Value::Undefined, |sections| overlay(sections, region.mem)),
1283 ),
1284 (
1285 "pdb_path",
1286 sections
1287 .as_ref()
1288 .and_then(|sections| debug::pdb_path(&data_dirs, region.mem, sections))
1289 .unwrap_or(Value::Undefined),
1290 ),
1291 (
1292 "rich_signature",
1293 RichHeaderInfo::parse(region.mem, dos_header.nt_headers_offset().into()).map_or_else(
1294 || {
1295 Value::object([
1298 ("version", Value::function(Pe::rich_signature_version)),
1299 ("toolid", Value::function(Pe::rich_signature_toolid)),
1300 ])
1301 },
1302 |info| rich_signature(info, region, data),
1303 ),
1304 ),
1305 ("number_of_version_infos", 0.into()),
1306 ]
1307 .into();
1308
1309 if let Some(sections) = sections.as_ref() {
1310 add_imports::<HEADERS>(&data_dirs, region.mem, sections, data, &mut map);
1311 add_delay_load_imports::<HEADERS>(&data_dirs, region.mem, sections, data, &mut map);
1312 add_exports(&data_dirs, region.mem, sections, data, &mut map);
1313 add_resources(&data_dirs, region.mem, sections, data, &mut map);
1314 }
1315
1316 #[cfg(feature = "authenticode")]
1317 if let Some((signatures, is_signed)) = signatures::get_signatures(&data_dirs, region.mem) {
1318 let _r = map.insert("number_of_signatures", signatures.len().into());
1319 let _r = map.insert("is_signed", is_signed);
1320 let _r = map.insert("signatures", Value::Array(signatures));
1321 } else {
1322 let _r = map.insert("number_of_signatures", Value::Integer(0));
1323 let _r = map.insert("is_signed", Value::Integer(0));
1324 }
1325
1326 Some(map)
1327}
1328
1329fn rich_signature(info: RichHeaderInfo, region: &Region, data: &mut Data) -> Value {
1330 data.rich_entries = info
1331 .unmasked_entries()
1332 .map(|entry| DataRichEntry {
1333 version: (entry.comp_id & 0xFFFF) as u16,
1334 toolid: (entry.comp_id >> 16) as u16,
1335 times: entry.count,
1336 })
1337 .collect();
1338
1339 let length = info.length.saturating_sub(8);
1340
1341 let raw = if info.offset + length <= region.mem.len() {
1342 Some(region.mem[info.offset..(info.offset + length)].to_vec())
1343 } else {
1344 None
1345 };
1346 let xor_key_bytes = info.xor_key.to_le_bytes();
1347 let clear = raw.clone().map(|mut clear| {
1349 for (b, k) in clear.iter_mut().zip(xor_key_bytes.iter().cycle()) {
1350 *b ^= k;
1351 }
1352 clear
1353 });
1354
1355 let mut version = Vec::new();
1356 for entry in info.unmasked_entries() {
1357 version.extend(entry.comp_id.to_le_bytes().as_slice());
1358 }
1359
1360 Value::object([
1361 ("offset", (region.start + info.offset).into()),
1362 ("length", length.into()),
1363 ("key", info.xor_key.into()),
1364 ("raw_data", raw.into()),
1365 ("clear_data", clear.into()),
1366 ("version_data", version.into()),
1367 ("version", Value::function(Pe::rich_signature_version)),
1368 ("toolid", Value::function(Pe::rich_signature_toolid)),
1369 ])
1370}
1371
1372fn add_imports<Pe: ImageNtHeaders>(
1373 data_dirs: &DataDirectories,
1374 mem: &[u8],
1375 sections: &utils::SectionTable,
1376 data: &mut Data,
1377 out: &mut HashMap<&'static str, Value>,
1378) {
1379 let mut imports = Vec::new();
1380 let mut nb_functions_total = 0;
1381
1382 let table = data_dirs
1383 .get(pe::IMAGE_DIRECTORY_ENTRY_IMPORT)
1384 .and_then(|dir| {
1385 let import_va = dir.virtual_address.get(LE);
1386 let (section_data, section_va) = sections.get_section_containing(mem, import_va)?;
1387 Some(ImportTable::new(section_data, section_va, import_va))
1388 });
1389 let descriptors = table.as_ref().and_then(|table| table.descriptors().ok());
1390 if let (Some(table), Some(mut descriptors)) = (table, descriptors) {
1391 while let Ok(Some(import_desc)) = descriptors.next() {
1392 let library = match table.name(import_desc.name.get(LE)) {
1393 Ok(name) => name.to_vec(),
1394 Err(_) => continue,
1395 };
1396 if library.len() >= MAX_IMPORT_DLL_NAME_LENGTH || !dll_name_is_valid(&library) {
1397 continue;
1398 }
1399
1400 let mut data_functions = Vec::new();
1401 let import_thunk_list = table
1402 .thunks(import_desc.original_first_thunk.get(LE))
1403 .or_else(|_| table.thunks(import_desc.first_thunk.get(LE)));
1404 let functions = import_thunk_list.ok().map(|mut thunks| {
1405 import_functions::<Pe, _>(
1406 &mut thunks,
1407 &library,
1408 |hint| table.hint_name(hint).map(|(_, name)| name.to_vec()),
1409 import_desc.first_thunk.get(LE),
1410 data.is_32bit,
1411 &mut data_functions,
1412 &mut nb_functions_total,
1413 )
1414 });
1415 if functions.as_ref().map_or(true, Vec::is_empty) {
1416 continue;
1417 }
1418
1419 data.imports.push(DataImport {
1420 dll_name: library.clone(),
1421 functions: data_functions,
1422 });
1423
1424 imports.push(Value::object([
1425 ("library_name", library.into()),
1426 (
1427 "number_of_functions",
1428 functions.as_ref().map(Vec::len).into(),
1429 ),
1430 (
1431 "functions",
1432 functions.map_or(Value::Undefined, Value::Array),
1433 ),
1434 ]));
1435 if imports.len() >= MAX_PE_IMPORTS {
1436 break;
1437 }
1438 }
1439 }
1440
1441 out.extend([
1442 ("number_of_imported_functions", nb_functions_total.into()),
1443 ("number_of_imports", imports.len().into()),
1444 ("import_details", Value::Array(imports)),
1445 ]);
1446}
1447
1448fn import_functions<Pe: ImageNtHeaders, F>(
1449 thunks: &mut ImportThunkList,
1450 dll_name: &[u8],
1451 hint_name: F,
1452 mut rva: u32,
1453 is_32: bool,
1454 data_functions: &mut Vec<DataFunction>,
1455 nb_functions_total: &mut usize,
1456) -> Vec<Value>
1457where
1458 F: Fn(u32) -> object::Result<Vec<u8>>,
1459{
1460 let mut functions = Vec::new();
1462 while let Ok(Some(thunk)) = thunks.next::<Pe>() {
1463 if *nb_functions_total >= MAX_PE_IMPORTS {
1464 break;
1465 }
1466
1467 if add_thunk::<Pe, _>(
1468 thunk,
1469 dll_name,
1470 rva,
1471 is_32,
1472 &hint_name,
1473 &mut functions,
1474 data_functions,
1475 ) {
1476 *nb_functions_total += 1;
1477 }
1478 rva += if is_32 { 4 } else { 8 };
1479 }
1480 functions
1481}
1482
1483fn add_thunk<Pe: ImageNtHeaders, F>(
1484 thunk: Pe::ImageThunkData,
1485 dll_name: &[u8],
1486 rva: u32,
1487 is_32: bool,
1488 hint_name: F,
1489 functions: &mut Vec<Value>,
1490 data_functions: &mut Vec<DataFunction>,
1491) -> bool
1492where
1493 F: Fn(u32) -> object::Result<Vec<u8>>,
1494{
1495 if thunk.is_ordinal() {
1496 let raw = if is_32 {
1497 thunk.raw() & 0x7FFF_FFFF
1498 } else {
1499 thunk.raw() & 0x7FFF_FFFF_FFFF_FFFF
1500 };
1501
1502 let Ok(ordinal) = u16::try_from(raw) else {
1503 return false;
1505 };
1506 let name = ord::ord_lookup(dll_name, ordinal);
1507
1508 data_functions.push(DataFunction {
1509 name: name.clone(),
1510 ordinal: Some(ordinal),
1511 rva,
1512 });
1513
1514 functions.push(Value::object([
1515 ("name", name.into()),
1516 ("ordinal", ordinal.into()),
1517 ("rva", rva.into()),
1518 ]));
1519 true
1520 } else {
1521 let Ok(name) = hint_name(thunk.address()) else {
1522 return false;
1523 };
1524
1525 if !is_import_name_valid(&name) {
1526 return false;
1527 }
1528
1529 data_functions.push(DataFunction {
1530 name: name.clone(),
1531 ordinal: None,
1532 rva,
1533 });
1534 functions.push(Value::object([("name", name.into()), ("rva", rva.into())]));
1535 true
1536 }
1537}
1538
1539fn is_import_name_valid(name: &[u8]) -> bool {
1542 if name.is_empty() {
1543 false
1544 } else {
1545 name.iter().all(|b| {
1546 b.is_ascii_alphanumeric()
1547 || [b'.', b'_', b'?', b'@', b'$', b'(', b')', b'<', b'>'].contains(b)
1548 })
1549 }
1550}
1551
1552fn add_delay_load_imports<Pe: ImageNtHeaders>(
1553 data_dirs: &DataDirectories,
1554 mem: &[u8],
1555 sections: &utils::SectionTable,
1556 data: &mut Data,
1557 out: &mut HashMap<&'static str, Value>,
1558) {
1559 let mut imports = Vec::new();
1560 let mut nb_functions_total = 0;
1561
1562 let table = data_dirs
1563 .get(pe::IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT)
1564 .and_then(|dir| {
1565 let import_va = dir.virtual_address.get(LE);
1566 let (section_data, section_va) = sections.get_section_containing(mem, import_va)?;
1567 Some(DelayLoadImportTable::new(
1568 section_data,
1569 section_va,
1570 import_va,
1571 ))
1572 });
1573 let descriptors = table.as_ref().and_then(|table| table.descriptors().ok());
1574 if let (Some(table), Some(mut descriptors)) = (table, descriptors) {
1575 while let Ok(Some(import_desc)) = descriptors.next() {
1576 let library = match table.name(import_desc.dll_name_rva.get(LE)) {
1577 Ok(name) => name.to_vec(),
1578 Err(_) => continue,
1579 };
1580 if !dll_name_is_valid(&library) {
1581 continue;
1582 }
1583
1584 let mut data_functions = Vec::new();
1585 let functions = table
1586 .thunks(import_desc.import_name_table_rva.get(LE))
1587 .ok()
1588 .map(|mut thunks| {
1589 import_functions::<Pe, _>(
1590 &mut thunks,
1591 &library,
1592 |hint| table.hint_name(hint).map(|(_, name)| name.to_vec()),
1593 import_desc.import_address_table_rva.get(LE),
1594 data.is_32bit,
1595 &mut data_functions,
1596 &mut nb_functions_total,
1597 )
1598 });
1599
1600 data.delayed_imports.push(DataImport {
1601 dll_name: library.clone(),
1602 functions: data_functions,
1603 });
1604
1605 imports.push(Value::object([
1606 ("library_name", library.into()),
1607 (
1608 "number_of_functions",
1609 functions.as_ref().map(Vec::len).into(),
1610 ),
1611 (
1612 "functions",
1613 functions.map_or(Value::Undefined, Value::Array),
1614 ),
1615 ]));
1616 if imports.len() >= MAX_PE_IMPORTS {
1617 break;
1618 }
1619 }
1620 }
1621
1622 out.extend([
1623 (
1624 "number_of_delayed_imported_functions",
1625 nb_functions_total.into(),
1626 ),
1627 ("number_of_delayed_imports", imports.len().into()),
1628 ("delayed_import_details", Value::Array(imports)),
1629 ]);
1630}
1631
1632fn dll_name_is_valid(dll_name: &[u8]) -> bool {
1633 dll_name.iter().all(|c| {
1634 *c >= b' '
1635 && *c <= 0x7e
1636 && *c != b'\"'
1637 && *c != b'*'
1638 && *c != b'<'
1639 && *c != b'>'
1640 && *c != b'?'
1641 && *c != b'|'
1642 })
1643}
1644
1645fn add_exports(
1646 data_dirs: &DataDirectories,
1647 mem: &[u8],
1648 sections: &utils::SectionTable,
1649 data: &mut Data,
1650 out: &mut HashMap<&'static str, Value>,
1651) {
1652 let export_table = data_dirs
1653 .get(pe::IMAGE_DIRECTORY_ENTRY_EXPORT)
1654 .and_then(|dir| {
1655 let export_va = dir.virtual_address.get(LE);
1656 let export_data = sections.get_dir_data(mem, *dir)?;
1657 ExportTable::parse(export_data, export_va).ok()
1658 });
1659
1660 if let Some(table) = export_table {
1661 let ordinal_base = table.ordinal_base() as usize;
1662 let addresses = table.addresses();
1663 let mut details: Vec<_> = addresses
1664 .iter()
1665 .take(MAX_PE_EXPORTS)
1666 .enumerate()
1667 .map(|(i, address)| {
1668 let address = address.get(LE);
1669 let forward_name = table.forward_string(address).ok().flatten().map(|forward| {
1670 if forward.len() > MAX_EXPORT_NAME_LENGTH {
1671 forward[..MAX_EXPORT_NAME_LENGTH].to_vec()
1672 } else {
1673 forward.to_vec()
1674 }
1675 });
1676
1677 data.exports.push(DataExport {
1678 name: None,
1679 ordinal: ordinal_base + i,
1680 });
1681
1682 Value::object([
1683 ("ordinal", (ordinal_base + i).into()),
1684 (
1685 "offset",
1686 match forward_name {
1687 Some(_) => Value::Undefined,
1688 None => match utils::va_to_file_offset(mem, sections, address) {
1690 Some(v) => v.into(),
1691 None => Value::Undefined,
1692 },
1693 },
1694 ),
1695 ("forward_name", forward_name.into()),
1696 ("rva", address.into()),
1697 ])
1698 })
1699 .collect();
1700
1701 for (name_pointer, ordinal_index) in table.name_iter() {
1703 let Ok(mut name) = table.name_from_pointer(name_pointer) else {
1704 continue;
1705 };
1706 if name.len() > MAX_EXPORT_NAME_LENGTH {
1707 name = &name[..MAX_EXPORT_NAME_LENGTH];
1708 }
1709 let ordinal_index = usize::from(ordinal_index);
1710
1711 if let Some(Value::Object(map)) = details.get_mut(ordinal_index) {
1712 let _r = map.insert("name", Value::bytes(name));
1713 }
1714 if let Some(export) = data.exports.get_mut(ordinal_index) {
1715 export.name = Some(name.to_vec());
1716 }
1717 }
1718
1719 let dir = table.directory();
1720 out.extend([
1721 ("export_timestamp", dir.time_date_stamp.get(LE).into()),
1722 (
1723 "dll_name",
1724 table
1725 .name_from_pointer(dir.name.get(LE))
1726 .ok()
1727 .map(<[u8]>::to_vec)
1728 .into(),
1729 ),
1730 ("number_of_exports", details.len().into()),
1731 ("export_details", Value::Array(details)),
1732 ]);
1733 } else {
1734 let _r = out.insert("number_of_exports", Value::Integer(0));
1735 }
1736}
1737
1738fn data_directories(dirs: DataDirectories) -> Value {
1739 Value::Array(
1740 dirs.iter()
1741 .take(MAX_NB_DATA_DIRECTORIES)
1742 .map(|dir| {
1743 Value::object([
1744 ("virtual_address", dir.virtual_address.get(LE).into()),
1745 ("size", dir.size.get(LE).into()),
1746 ])
1747 })
1748 .collect(),
1749 )
1750}
1751
1752fn sections_to_value(
1753 sections: &utils::SectionTable,
1754 strings: Option<StringTable>,
1755 data: &mut Data,
1756) -> Value {
1757 Value::Array(
1758 sections
1759 .iter()
1760 .take(MAX_PE_SECTIONS)
1761 .map(|section| {
1762 let mut name = section.name.as_slice();
1763 if let Some(last_non_zero_pos) = name
1764 .iter()
1765 .enumerate()
1766 .rev()
1767 .find_map(|(i, v)| (*v != 0).then_some(i))
1768 {
1769 name = &name[..=last_non_zero_pos];
1770 }
1771 let full_name = match (strings, section.name_offset()) {
1772 (Some(strings), Ok(Some(offset))) => strings.get(offset).ok(),
1775 (_, Ok(None)) => Some(name),
1777 (_, _) => None,
1778 };
1779 let raw_data_offset = i64::from(section.pointer_to_raw_data.get(LE));
1780 let raw_data_size = i64::from(section.size_of_raw_data.get(LE));
1781 let virtual_address = i64::from(section.virtual_address.get(LE));
1782 let virtual_size = i64::from(section.virtual_size.get(LE));
1783
1784 data.sections.push(DataSection {
1785 name: name.to_vec(),
1786 raw_data_offset,
1787 raw_data_size,
1788 virtual_address,
1789 virtual_size,
1790 });
1791
1792 Value::object([
1793 ("name", name.to_vec().into()),
1794 ("full_name", full_name.map(<[u8]>::to_vec).into()),
1795 ("characteristics", section.characteristics.get(LE).into()),
1796 ("virtual_address", virtual_address.into()),
1797 ("virtual_size", virtual_size.into()),
1798 ("raw_data_size", raw_data_size.into()),
1799 ("raw_data_offset", raw_data_offset.into()),
1800 (
1801 "pointer_to_relocations",
1802 section.pointer_to_relocations.get(LE).into(),
1803 ),
1804 (
1805 "pointer_to_line_numbers",
1806 section.pointer_to_linenumbers.get(LE).into(),
1807 ),
1808 (
1809 "number_of_relocations",
1810 section.number_of_relocations.get(LE).into(),
1811 ),
1812 (
1813 "number_of_line_numbers",
1814 section.number_of_linenumbers.get(LE).into(),
1815 ),
1816 ])
1817 })
1818 .collect(),
1819 )
1820}
1821
1822fn overlay(sections: &utils::SectionTable, mem: &[u8]) -> Value {
1823 let offset = sections.max_section_file_offset();
1824
1825 if offset < mem.len() as u64 {
1826 Value::object([
1827 ("offset", offset.into()),
1828 ("size", (mem.len() as u64 - offset).into()),
1829 ])
1830 } else {
1831 Value::object([("offset", 0.into()), ("size", 0.into())])
1832 }
1833}
1834
1835fn add_resources(
1836 data_dirs: &DataDirectories,
1837 mem: &[u8],
1838 sections: &utils::SectionTable,
1839 data: &mut Data,
1840 out: &mut HashMap<&'static str, Value>,
1841) {
1842 let mut infos = Vec::new();
1843
1844 let resource_dir = data_dirs
1845 .get(pe::IMAGE_DIRECTORY_ENTRY_RESOURCE)
1846 .and_then(|dir| {
1847 let rsrc_data = sections.get_dir_data(mem, *dir)?;
1848 Some(ResourceDirectory::new(rsrc_data))
1849 });
1850
1851 let root = resource_dir.as_ref().and_then(|dir| dir.root().ok());
1852 if let (Some(dir), Some(root)) = (resource_dir, root) {
1853 let mut resources = Vec::new();
1854
1855 'outer: for entry in root.entries {
1856 if entry.offset_to_data_or_directory.get(LE) == 0 {
1858 continue;
1859 }
1860
1861 let ty = entry.name_or_id.get(LE);
1863 let ty_name = match entry.name_or_id() {
1864 ResourceNameOrId::Name(name) => name.raw_data(dir).ok(),
1865 ResourceNameOrId::Id(_) => None,
1866 };
1867
1868 let Ok(ResourceDirectoryEntryData::Table(table)) = entry.data(dir) else {
1869 continue;
1870 };
1871 for entry in table.entries {
1872 let id = entry.name_or_id.get(LE);
1874 let id_name = resource_entry_name(*entry, dir);
1875
1876 let Ok(ResourceDirectoryEntryData::Table(table)) = entry.data(dir) else {
1877 continue;
1878 };
1879 for entry in table.entries {
1880 let lang = entry.name_or_id.get(LE);
1882 let lang_name = match entry.name_or_id() {
1883 ResourceNameOrId::Name(name) => name.raw_data(dir).ok(),
1884 ResourceNameOrId::Id(_) => None,
1885 };
1886
1887 if let Ok(ResourceDirectoryEntryData::Data(entry_data)) = entry.data(dir) {
1888 let size = entry_data.size.get(LE);
1893 if size == 0 || size > 0x3FFF_FFFF {
1894 continue;
1895 }
1896
1897 let rva = entry_data.offset_to_data.get(LE);
1898 let offset = utils::va_to_file_offset(mem, sections, rva);
1899 if ty == u32::from(pe::RT_VERSION) {
1900 if let Some(offset) = offset {
1901 version_info::read_version_info(mem, offset as usize, &mut infos);
1902 }
1903 }
1904
1905 data.resource_languages.push(lang);
1906
1907 resources.push(Value::object([
1908 ("rva", rva.into()),
1909 ("length", entry_data.size.get(LE).into()),
1910 ("offset", offset.into()),
1911 ("type_string", ty_name.map(<[u8]>::to_vec).into()),
1912 (
1913 "type",
1914 match ty_name {
1915 Some(_) => Value::Undefined,
1916 None => ty.into(),
1917 },
1918 ),
1919 ("name_string", id_name.map(<[u8]>::to_vec).into()),
1920 (
1921 "id",
1922 match id_name {
1923 Some(_) => Value::Undefined,
1924 None => id.into(),
1925 },
1926 ),
1927 ("language_string", lang_name.map(<[u8]>::to_vec).into()),
1928 (
1929 "language",
1930 match lang_name {
1931 Some(_) => Value::Undefined,
1932 None => lang.into(),
1933 },
1934 ),
1935 ]));
1936 if resources.len() >= MAX_RESOURCES {
1937 break 'outer;
1938 }
1939 }
1940 }
1941 }
1942 }
1943
1944 out.extend([
1945 ("number_of_resources", resources.len().into()),
1946 (
1947 "resource_timestamp",
1948 root.header.time_date_stamp.get(LE).into(),
1949 ),
1950 (
1951 "resource_version",
1952 Value::object([
1953 ("major", root.header.major_version.get(LE).into()),
1954 ("minor", root.header.minor_version.get(LE).into()),
1955 ]),
1956 ),
1957 ("resources", Value::Array(resources)),
1958 ]);
1959 } else {
1960 let _r = out.insert("number_of_resources", Value::Integer(0));
1961 }
1962
1963 out.extend([
1964 ("number_of_version_infos", infos.len().into()),
1965 (
1966 "version_info",
1967 Value::Dictionary(
1968 infos
1969 .iter()
1970 .map(|info| (info.key.clone(), info.value.clone().into()))
1971 .collect(),
1972 ),
1973 ),
1974 (
1975 "version_info_list",
1976 Value::Array(
1977 infos
1978 .into_iter()
1979 .map(|info| {
1980 Value::object([("key", info.key.into()), ("value", info.value.into())])
1981 })
1982 .collect(),
1983 ),
1984 ),
1985 ]);
1986}
1987
1988fn resource_entry_name(
1989 entry: pe::ImageResourceDirectoryEntry,
1990 dir: ResourceDirectory,
1991) -> Option<&[u8]> {
1992 match entry.name_or_id() {
1993 ResourceNameOrId::Name(resource_name) => match resource_name.raw_data(dir) {
1994 Ok(name) if name.len() <= 1000 => Some(name),
1995 _ => None,
1996 },
1997 ResourceNameOrId::Id(_) => None,
1998 }
1999}
2000
2001fn bool_to_int_value(b: bool) -> Value {
2002 Value::Integer(b.into())
2003}
2004
2005impl Pe {
2006 fn calculate_checksum(ctx: &mut EvalContext, _: Vec<Value>) -> Option<Value> {
2007 let mem = ctx.mem.get_direct()?;
2008
2009 let dos_header = ImageDosHeader::parse(mem).ok()?;
2012 let csum_offset = dos_header.nt_headers_offset() + 64 + 24;
2016
2017 let mut csum: u64 = 0;
2019 let mut idx = 0;
2020 let mut cursor = mem;
2021 while cursor.len() >= 4 {
2022 if idx != csum_offset {
2023 let dword = u32::from_le_bytes([cursor[0], cursor[1], cursor[2], cursor[3]]);
2024
2025 csum += u64::from(dword);
2026 if csum > 0xFFFF_FFFF {
2027 csum = (csum & 0xFFFF_FFFF) + (csum >> 32);
2028 }
2029 }
2030
2031 cursor = &cursor[4..];
2032 idx += 4;
2033 }
2034
2035 let dword = match cursor {
2037 [a] => u32::from_le_bytes([*a, 0, 0, 0]),
2038 [a, b] => u32::from_le_bytes([*a, *b, 0, 0]),
2039 [a, b, c] => u32::from_le_bytes([*a, *b, *c, 0]),
2040 _ => 0,
2041 };
2042 csum += u64::from(dword);
2043 if csum > 0xFFFF_FFFF {
2044 csum = (csum & 0xFFFF_FFFF) + (csum >> 32);
2045 }
2046
2047 let mut csum = (csum & 0xFFFF) + (csum >> 16);
2049 csum += csum >> 16;
2050 csum &= 0xFFFF;
2051
2052 #[allow(clippy::cast_possible_truncation)]
2054 Some((csum as usize).wrapping_add(mem.len()).into())
2055 }
2056
2057 fn section_index(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2058 let mut args = args.into_iter();
2059 let arg = args.next()?;
2060
2061 let data = ctx.module_data.get::<Self>()?;
2062
2063 match arg {
2064 Value::Bytes(section_name) => data
2065 .sections
2066 .iter()
2067 .position(|sec| sec.name == section_name)
2068 .map(Into::into),
2069 Value::Integer(addr) => {
2070 let index = if ctx.process_memory {
2071 data.sections.iter().position(|sec| {
2072 addr >= sec.virtual_address && addr - sec.virtual_address < sec.virtual_size
2073 })?
2074 } else {
2075 data.sections.iter().position(|sec| {
2076 addr >= sec.raw_data_offset
2077 && addr - sec.raw_data_offset < sec.raw_data_size
2078 })?
2079 };
2080
2081 Some(index.into())
2082 }
2083 _ => None,
2084 }
2085 }
2086
2087 fn exports(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2088 let mut args = args.into_iter();
2089 let arg = args.next()?;
2090
2091 let data = ctx.module_data.get::<Self>()?;
2092
2093 let res = match arg {
2094 Value::Bytes(function_name) => data.exports.iter().any(|export| {
2095 export
2096 .name
2097 .as_ref()
2098 .is_some_and(|name| name.eq_ignore_ascii_case(&function_name))
2099 }),
2100 Value::Integer(ordinal) => match usize::try_from(ordinal) {
2101 Ok(ord) => data.exports.iter().any(|export| export.ordinal == ord),
2102 Err(_) => false,
2103 },
2104 Value::Regex(function_name_regex) => data.exports.iter().any(|export| {
2105 export
2106 .name
2107 .as_ref()
2108 .is_some_and(|name| function_name_regex.is_match(name))
2109 }),
2110 _ => return None,
2111 };
2112
2113 Some(bool_to_int_value(res))
2114 }
2115
2116 fn exports_index(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2117 let mut args = args.into_iter();
2118 let arg = args.next()?;
2119
2120 let data = ctx.module_data.get::<Self>()?;
2121 if data.exports.is_empty() {
2123 return None;
2124 }
2125
2126 let res = match arg {
2127 Value::Bytes(function_name) => data.exports.iter().position(|export| {
2128 export
2129 .name
2130 .as_ref()
2131 .is_some_and(|name| name.eq_ignore_ascii_case(&function_name))
2132 })?,
2133 Value::Integer(ordinal) => {
2134 let ordinal = usize::try_from(ordinal).ok()?;
2135 if ordinal == 0 || ordinal > data.exports.len() {
2136 return None;
2137 }
2138
2139 data.exports
2140 .iter()
2141 .position(|export| export.ordinal == ordinal)?
2142 }
2143 Value::Regex(function_name_regex) => data.exports.iter().position(|export| {
2144 export
2145 .name
2146 .as_ref()
2147 .is_some_and(|name| function_name_regex.is_match(name))
2148 })?,
2149 _ => return None,
2150 };
2151
2152 Some(res.into())
2153 }
2154
2155 fn imports(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2156 let mut args = args.into_iter();
2157 let first = args.next()?;
2158 let second = args.next();
2159 let third = args.next();
2160
2161 let data = ctx.module_data.get::<Self>()?;
2162
2163 match (first, second, third) {
2164 (Value::Bytes(dll_name), Some(Value::Bytes(function_name)), None) => {
2165 Some(bool_to_int_value(
2166 data.find_function(&dll_name, &function_name, false)
2167 .is_some(),
2168 ))
2169 }
2170 (Value::Bytes(dll_name), Some(Value::Integer(ordinal)), None) => {
2171 Some(bool_to_int_value(
2172 data.find_function_ordinal(&dll_name, ordinal, false)
2173 .is_some(),
2174 ))
2175 }
2176 (Value::Bytes(dll_name), None, None) => {
2177 Some(data.nb_functions(&dll_name, false).into())
2178 }
2179 (Value::Regex(dll_name), Some(Value::Regex(function_name)), None) => Some(
2180 data.nb_functions_regex(&dll_name, &function_name, false)
2181 .into(),
2182 ),
2183 (
2184 Value::Integer(flags),
2185 Some(Value::Bytes(dll_name)),
2186 Some(Value::Bytes(function_name)),
2187 ) => {
2188 if flags & (ImportType::Standard as i64) != 0
2189 && data
2190 .find_function(&dll_name, &function_name, false)
2191 .is_some()
2192 {
2193 return Some(Value::Integer(1));
2194 }
2195 if flags & (ImportType::Delayed as i64) != 0
2196 && data
2197 .find_function(&dll_name, &function_name, true)
2198 .is_some()
2199 {
2200 return Some(Value::Integer(1));
2201 }
2202
2203 Some(Value::Integer(0))
2204 }
2205 (
2206 Value::Integer(flags),
2207 Some(Value::Bytes(dll_name)),
2208 Some(Value::Integer(ordinal)),
2209 ) => {
2210 if flags & (ImportType::Standard as i64) != 0
2211 && data
2212 .find_function_ordinal(&dll_name, ordinal, false)
2213 .is_some()
2214 {
2215 return Some(Value::Integer(1));
2216 }
2217 if flags & (ImportType::Delayed as i64) != 0
2218 && data
2219 .find_function_ordinal(&dll_name, ordinal, true)
2220 .is_some()
2221 {
2222 return Some(Value::Integer(1));
2223 }
2224
2225 Some(Value::Integer(0))
2226 }
2227 (Value::Integer(flags), Some(Value::Bytes(dll_name)), None) => {
2228 let mut res = 0;
2229 if flags & (ImportType::Standard as i64) != 0 {
2230 res += data.nb_functions(&dll_name, false);
2231 }
2232 if flags & (ImportType::Delayed as i64) != 0 {
2233 res += data.nb_functions(&dll_name, true);
2234 }
2235 Some(res.into())
2236 }
2237 (
2238 Value::Integer(flags),
2239 Some(Value::Regex(dll_name)),
2240 Some(Value::Regex(function_name)),
2241 ) => {
2242 let mut res = 0;
2243 if flags & (ImportType::Standard as i64) != 0 {
2244 res += data.nb_functions_regex(&dll_name, &function_name, false);
2245 }
2246 if flags & (ImportType::Delayed as i64) != 0 {
2247 res += data.nb_functions_regex(&dll_name, &function_name, true);
2248 }
2249 Some(res.into())
2250 }
2251 _ => None,
2252 }
2253 }
2254
2255 fn import_rva(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2256 let mut args = args.into_iter();
2257 let first = args.next()?;
2258 let second = args.next()?;
2259
2260 let data = ctx.module_data.get::<Self>()?;
2261
2262 match (first, second) {
2263 (Value::Bytes(dll_name), Value::Bytes(function_name)) => data
2264 .find_function(&dll_name, &function_name, false)
2265 .map(|v| v.rva.into()),
2266 (Value::Bytes(dll_name), Value::Integer(ordinal)) => data
2267 .find_function_ordinal(&dll_name, ordinal, false)
2268 .map(|v| v.rva.into()),
2269 _ => None,
2270 }
2271 }
2272
2273 fn delayed_import_rva(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2274 let mut args = args.into_iter();
2275 let first = args.next()?;
2276 let second = args.next()?;
2277
2278 let data = ctx.module_data.get::<Self>()?;
2279
2280 match (first, second) {
2281 (Value::Bytes(dll_name), Value::Bytes(function_name)) => data
2282 .find_function(&dll_name, &function_name, true)
2283 .map(|v| v.rva.into()),
2284 (Value::Bytes(dll_name), Value::Integer(ordinal)) => data
2285 .find_function_ordinal(&dll_name, ordinal, true)
2286 .map(|v| v.rva.into()),
2287 _ => None,
2288 }
2289 }
2290
2291 fn locale(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2292 let mut args = args.into_iter();
2293 let locale: i64 = args.next()?.try_into().ok()?;
2294
2295 let data = ctx.module_data.get::<Self>()?;
2296 Some(bool_to_int_value(
2297 data.resource_languages
2298 .iter()
2299 .any(|language| i64::from(language & 0xFFFF) == locale),
2300 ))
2301 }
2302
2303 fn language(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2304 let mut args = args.into_iter();
2305 let lang: i64 = args.next()?.try_into().ok()?;
2306
2307 let data = ctx.module_data.get::<Self>()?;
2308 Some(bool_to_int_value(
2309 data.resource_languages
2310 .iter()
2311 .any(|language| i64::from(language & 0xFF) == lang),
2312 ))
2313 }
2314
2315 fn is_dll(ctx: &mut EvalContext, _: Vec<Value>) -> Option<Value> {
2316 let data = ctx.module_data.get::<Self>()?;
2317 Some(data.is_dll.into())
2318 }
2319
2320 fn is_32bit(ctx: &mut EvalContext, _: Vec<Value>) -> Option<Value> {
2321 let data = ctx.module_data.get::<Self>()?;
2322 Some(bool_to_int_value(data.is_32bit))
2323 }
2324
2325 fn is_64bit(ctx: &mut EvalContext, _: Vec<Value>) -> Option<Value> {
2326 let data = ctx.module_data.get::<Self>()?;
2327 Some(bool_to_int_value(!data.is_32bit))
2328 }
2329
2330 fn rich_signature_version(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2331 let mut args = args.into_iter();
2332 let first = args.next()?;
2333 let second = args.next();
2334
2335 let data = ctx.module_data.get::<Self>()?;
2336
2337 let res = match (first, second) {
2338 (Value::Integer(version), Some(Value::Integer(toolid))) => {
2339 data.count_rich_entries(Some(version), Some(toolid))
2340 }
2341 (Value::Integer(version), None) => data.count_rich_entries(Some(version), None),
2342 _ => return None,
2343 };
2344
2345 Some(res.into())
2346 }
2347
2348 fn rich_signature_toolid(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2349 let mut args = args.into_iter();
2350 let first = args.next()?;
2351 let second = args.next();
2352
2353 let data = ctx.module_data.get::<Self>()?;
2354
2355 let res = match (first, second) {
2356 (Value::Integer(toolid), Some(Value::Integer(version))) => {
2357 data.count_rich_entries(Some(version), Some(toolid))
2358 }
2359 (Value::Integer(toolid), None) => data.count_rich_entries(None, Some(toolid)),
2360 _ => return None,
2361 };
2362
2363 Some(res.into())
2364 }
2365
2366 #[cfg(feature = "hash")]
2367 fn imphash(ctx: &mut EvalContext, _: Vec<Value>) -> Option<Value> {
2368 use md5::{Digest, Md5};
2369
2370 let data = ctx.module_data.get::<Self>()?;
2371
2372 let mut hasher = Md5::new();
2373 let mut first = true;
2374 for dll in &data.imports {
2375 let mut dll_name = dll.dll_name.to_ascii_lowercase();
2376 if dll_name.ends_with(b".ocx")
2377 || dll_name.ends_with(b".sys")
2378 || dll_name.ends_with(b".dll")
2379 {
2380 dll_name.truncate(dll_name.len() - 4);
2381 }
2382
2383 for fun in &dll.functions {
2384 let fun_name = fun.name.to_ascii_lowercase();
2385
2386 if !first {
2387 hasher.update([b',']);
2388 }
2389 hasher.update(&dll_name);
2390 hasher.update([b'.']);
2391 hasher.update(fun_name);
2392 first = false;
2393 }
2394 }
2395
2396 Some(Value::Bytes(super::hex_encode(hasher.finalize())))
2397 }
2398
2399 fn rva_to_offset(ctx: &mut EvalContext, args: Vec<Value>) -> Option<Value> {
2400 let rva: i64 = args.into_iter().next()?.try_into().ok()?;
2401 let rva: u32 = rva.try_into().ok()?;
2402
2403 let mem = ctx.mem.get_direct()?;
2405
2406 let dos_header = ImageDosHeader::parse(mem).ok()?;
2410 let mut offset = dos_header.nt_headers_offset().into();
2411 let section_table = match FileKind::parse(mem) {
2412 Ok(FileKind::Pe32) => {
2413 let (nt_headers, _) = ImageNtHeaders32::parse(mem, &mut offset).ok()?;
2414 utils::SectionTable::new(nt_headers, mem, offset)?
2415 }
2416 Ok(FileKind::Pe64) => {
2417 let (nt_headers, _) = ImageNtHeaders64::parse(mem, &mut offset).ok()?;
2418 utils::SectionTable::new(nt_headers, mem, offset)?
2419 }
2420 _ => return None,
2421 };
2422
2423 utils::va_to_file_offset(mem, §ion_table, rva).map(Into::into)
2424 }
2425}
2426
2427#[derive(Default)]
2428pub struct Data {
2429 imports: Vec<DataImport>,
2430 delayed_imports: Vec<DataImport>,
2431 exports: Vec<DataExport>,
2432 sections: Vec<DataSection>,
2433 rich_entries: Vec<DataRichEntry>,
2434 resource_languages: Vec<u32>,
2435 is_32bit: bool,
2436 is_dll: u16,
2437 found_pe: bool,
2438}
2439
2440struct DataImport {
2441 dll_name: Vec<u8>,
2442 functions: Vec<DataFunction>,
2443}
2444
2445struct DataExport {
2446 name: Option<Vec<u8>>,
2447 ordinal: usize,
2448}
2449
2450struct DataFunction {
2451 name: Vec<u8>,
2452 ordinal: Option<u16>,
2453 rva: u32,
2454}
2455
2456struct DataSection {
2457 name: Vec<u8>,
2458 raw_data_offset: i64,
2459 raw_data_size: i64,
2460 virtual_address: i64,
2461 virtual_size: i64,
2462}
2463
2464struct DataRichEntry {
2465 version: u16,
2466 toolid: u16,
2467 times: u32,
2468}
2469
2470impl Data {
2471 fn get_imports(&self, delayed: bool) -> &[DataImport] {
2472 if delayed {
2473 &self.delayed_imports
2474 } else {
2475 &self.imports
2476 }
2477 }
2478
2479 fn find_function(
2480 &self,
2481 dll_name: &[u8],
2482 fun_name: &[u8],
2483 delayed: bool,
2484 ) -> Option<&DataFunction> {
2485 self.get_imports(delayed)
2486 .iter()
2487 .find(|imp| imp.dll_name.eq_ignore_ascii_case(dll_name))
2488 .and_then(|imp| {
2489 imp.functions
2490 .iter()
2491 .find(|f| f.name.eq_ignore_ascii_case(fun_name))
2492 })
2493 }
2494
2495 fn find_function_ordinal(
2496 &self,
2497 dll_name: &[u8],
2498 ordinal: i64,
2499 delayed: bool,
2500 ) -> Option<&DataFunction> {
2501 self.get_imports(delayed)
2502 .iter()
2503 .find(|imp| imp.dll_name.eq_ignore_ascii_case(dll_name))
2504 .and_then(|imp| {
2505 imp.functions.iter().find(|f| match f.ordinal {
2506 Some(v) => i64::from(v) == ordinal,
2507 None => false,
2508 })
2509 })
2510 }
2511
2512 fn nb_functions(&self, dll_name: &[u8], delayed: bool) -> usize {
2513 self.get_imports(delayed)
2514 .iter()
2515 .find(|imp| imp.dll_name.eq_ignore_ascii_case(dll_name))
2516 .map_or(0, |imp| imp.functions.len())
2517 }
2518
2519 fn nb_functions_regex(&self, dll_regex: &Regex, fun_regex: &Regex, delayed: bool) -> u32 {
2520 let mut nb_matches = 0;
2521
2522 for imp in self.get_imports(delayed) {
2523 if !dll_regex.is_match(&imp.dll_name) {
2524 continue;
2525 }
2526 for fun in &imp.functions {
2527 if fun_regex.is_match(&fun.name) {
2528 nb_matches += 1;
2529 }
2530 }
2531 }
2532 nb_matches
2533 }
2534
2535 fn count_rich_entries(&self, version: Option<i64>, toolid: Option<i64>) -> u64 {
2536 let version = match version {
2537 Some(v) => match u16::try_from(v) {
2538 Ok(v) => Some(v),
2539 Err(_) => return 0,
2540 },
2541 None => None,
2542 };
2543 let toolid = match toolid {
2544 Some(v) => match u16::try_from(v) {
2545 Ok(v) => Some(v),
2546 Err(_) => return 0,
2547 },
2548 None => None,
2549 };
2550
2551 self.rich_entries
2552 .iter()
2553 .map(|entry| {
2554 let mut matched = true;
2555 if let Some(v) = version {
2556 matched = matched && v == entry.version;
2557 }
2558 if let Some(t) = toolid {
2559 matched = matched && t == entry.toolid;
2560 }
2561
2562 if matched {
2563 u64::from(entry.times)
2564 } else {
2565 0
2566 }
2567 })
2568 .sum()
2569 }
2570}