Process Hacker
peprp.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * PE viewer
4  *
5  * Copyright (C) 2010-2011 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <peview.h>
24 #include <cpysave.h>
25 #include <verify.h>
26 #include <shlobj.h>
27 
28 #define PVM_CHECKSUM_DONE (WM_APP + 1)
29 #define PVM_VERIFY_DONE (WM_APP + 2)
30 
31 INT_PTR CALLBACK PvpPeGeneralDlgProc(
32  _In_ HWND hwndDlg,
33  _In_ UINT uMsg,
34  _In_ WPARAM wParam,
35  _In_ LPARAM lParam
36  );
37 
38 INT_PTR CALLBACK PvpPeImportsDlgProc(
39  _In_ HWND hwndDlg,
40  _In_ UINT uMsg,
41  _In_ WPARAM wParam,
42  _In_ LPARAM lParam
43  );
44 
45 INT_PTR CALLBACK PvpPeExportsDlgProc(
46  _In_ HWND hwndDlg,
47  _In_ UINT uMsg,
48  _In_ WPARAM wParam,
49  _In_ LPARAM lParam
50  );
51 
52 INT_PTR CALLBACK PvpPeLoadConfigDlgProc(
53  _In_ HWND hwndDlg,
54  _In_ UINT uMsg,
55  _In_ WPARAM wParam,
56  _In_ LPARAM lParam
57  );
58 
59 INT_PTR CALLBACK PvpPeClrDlgProc(
60  _In_ HWND hwndDlg,
61  _In_ UINT uMsg,
62  _In_ WPARAM wParam,
63  _In_ LPARAM lParam
64  );
65 
67 PIMAGE_COR20_HEADER PvImageCor20Header;
68 
73 
75  VOID
76  )
77 {
78  NTSTATUS status;
79  PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) };
80  PROPSHEETPAGE propSheetPage;
81  HPROPSHEETPAGE pages[5];
84  PIMAGE_DATA_DIRECTORY entry;
85 
86  status = PhLoadMappedImage(PvFileName->Buffer, NULL, TRUE, &PvMappedImage);
87 
88  if (!NT_SUCCESS(status))
89  {
90  PhShowStatus(NULL, L"Unable to load the PE file", status, 0);
91  return;
92  }
93 
94  propSheetHeader.dwFlags =
95  PSH_NOAPPLYNOW |
96  PSH_NOCONTEXTHELP |
97  PSH_PROPTITLE;
98  propSheetHeader.hwndParent = NULL;
99  propSheetHeader.pszCaption = PvFileName->Buffer;
100  propSheetHeader.nPages = 0;
101  propSheetHeader.nStartPage = 0;
102  propSheetHeader.phpage = pages;
103 
104  // General page
105  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
106  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
107  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PEGENERAL);
108  propSheetPage.pfnDlgProc = PvpPeGeneralDlgProc;
109  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
110 
111  // Imports page
112  if ((NT_SUCCESS(PhGetMappedImageImports(&imports, &PvMappedImage)) && imports.NumberOfDlls != 0) ||
113  (NT_SUCCESS(PhGetMappedImageDelayImports(&imports, &PvMappedImage)) && imports.NumberOfDlls != 0))
114  {
115  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
116  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
117  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PEIMPORTS);
118  propSheetPage.pfnDlgProc = PvpPeImportsDlgProc;
119  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
120  }
121 
122  // Exports page
123  if (NT_SUCCESS(PhGetMappedImageExports(&exports, &PvMappedImage)) && exports.NumberOfEntries != 0)
124  {
125  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
126  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
127  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PEEXPORTS);
128  propSheetPage.pfnDlgProc = PvpPeExportsDlgProc;
129  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
130  }
131 
132  // Load Config page
133  if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &entry)) && entry->VirtualAddress)
134  {
135  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
136  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
137  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PELOADCONFIG);
138  propSheetPage.pfnDlgProc = PvpPeLoadConfigDlgProc;
139  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
140  }
141 
142  // CLR page
143  if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &entry)) &&
144  entry->VirtualAddress &&
145  (PvImageCor20Header = PhMappedImageRvaToVa(&PvMappedImage, entry->VirtualAddress, NULL)))
146  {
147  status = STATUS_SUCCESS;
148 
149  __try
150  {
151  PhProbeAddress(PvImageCor20Header, sizeof(IMAGE_COR20_HEADER),
152  PvMappedImage.ViewBase, PvMappedImage.Size, 4);
153  }
154  __except (EXCEPTION_EXECUTE_HANDLER)
155  {
156  status = GetExceptionCode();
157  }
158 
159  if (NT_SUCCESS(status))
160  {
161  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
162  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
163  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_PECLR);
164  propSheetPage.pfnDlgProc = PvpPeClrDlgProc;
165  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
166  }
167  }
168 
169  PropertySheet(&propSheetHeader);
170 
171  PhUnloadMappedImage(&PvMappedImage);
172 }
173 
174 static NTSTATUS CheckSumImageThreadStart(
175  _In_ PVOID Parameter
176  )
177 {
178  HWND windowHandle;
179  ULONG checkSum;
180 
181  windowHandle = Parameter;
182  checkSum = PhCheckSumMappedImage(&PvMappedImage);
183 
184  PostMessage(
185  windowHandle,
187  checkSum,
188  0
189  );
190 
191  return STATUS_SUCCESS;
192 }
193 
195  _In_ PPH_STRING FileName,
196  _In_ ULONG Flags,
197  _In_opt_ HWND hWnd,
198  _Out_opt_ PPH_STRING *SignerName
199  )
200 {
201  static PH_STRINGREF codeIntegrityFileName = PH_STRINGREF_INIT(L"\\AppxMetadata\\CodeIntegrity.cat");
202 
203  VERIFY_RESULT result;
204  PH_VERIFY_FILE_INFO info;
205  PPH_STRING windowsAppsPath;
206  PPH_STRING additionalCatalogFileName = NULL;
207  PCERT_CONTEXT *signatures;
208  ULONG numberOfSignatures;
209 
210  memset(&info, 0, sizeof(PH_VERIFY_FILE_INFO));
211  info.FileName = FileName->Buffer;
212  info.Flags = Flags;
213  info.hWnd = hWnd;
214 
215  windowsAppsPath = PhGetKnownLocation(CSIDL_PROGRAM_FILES, L"\\WindowsApps\\");
216 
217  if (windowsAppsPath)
218  {
219  if (PhStartsWithStringRef(&FileName->sr, &windowsAppsPath->sr, TRUE))
220  {
221  PH_STRINGREF remainingFileName;
222  ULONG_PTR indexOfBackslash;
223  PH_STRINGREF baseFileName;
224 
225  remainingFileName = FileName->sr;
226  PhSkipStringRef(&remainingFileName, windowsAppsPath->Length);
227  indexOfBackslash = PhFindCharInStringRef(&remainingFileName, '\\', FALSE);
228 
229  if (indexOfBackslash != -1)
230  {
231  baseFileName.Buffer = FileName->Buffer;
232  baseFileName.Length = windowsAppsPath->Length + indexOfBackslash * sizeof(WCHAR);
233  additionalCatalogFileName = PhConcatStringRef2(&baseFileName, &codeIntegrityFileName);
234  }
235  }
236 
237  PhDereferenceObject(windowsAppsPath);
238  }
239 
240  if (additionalCatalogFileName)
241  {
242  info.NumberOfCatalogFileNames = 1;
243  info.CatalogFileNames = &additionalCatalogFileName->Buffer;
244  }
245 
246  if (!NT_SUCCESS(PhVerifyFileEx(&info, &result, &signatures, &numberOfSignatures)))
247  {
248  result = VrNoSignature;
249  signatures = NULL;
250  numberOfSignatures = 0;
251  }
252 
253  if (additionalCatalogFileName)
254  PhDereferenceObject(additionalCatalogFileName);
255 
256  if (SignerName)
257  {
258  if (numberOfSignatures != 0)
259  *SignerName = PhGetSignerNameFromCertificate(signatures[0]);
260  else
261  *SignerName = NULL;
262  }
263 
264  PhFreeVerifySignatures(signatures, numberOfSignatures);
265 
266  return result;
267 }
268 
269 static NTSTATUS VerifyImageThreadStart(
270  _In_ PVOID Parameter
271  )
272 {
273  HWND windowHandle;
274 
275  windowHandle = Parameter;
277  PostMessage(windowHandle, PVM_VERIFY_DONE, 0, 0);
278 
279  return STATUS_SUCCESS;
280 }
281 
282 FORCEINLINE PWSTR PvpGetStringOrNa(
283  _In_ PPH_STRING String
284  )
285 {
286  if (String)
287  return String->Buffer;
288  else
289  return L"N/A";
290 }
291 
292 INT_PTR CALLBACK PvpPeGeneralDlgProc(
293  _In_ HWND hwndDlg,
294  _In_ UINT uMsg,
295  _In_ WPARAM wParam,
296  _In_ LPARAM lParam
297  )
298 {
299  switch (uMsg)
300  {
301  case WM_INITDIALOG:
302  {
303  HWND lvHandle;
304  ULONG i;
305  PPH_STRING string;
306  PWSTR type;
307  PH_STRING_BUILDER stringBuilder;
308 
309  PhCenterWindow(GetParent(hwndDlg), NULL);
310 
311  // File version information
312 
313  {
314  PhInitializeImageVersionInfo(&PvImageVersionInfo, PvFileName->Buffer);
315 
316  if (ExtractIconEx(
318  0,
320  NULL,
321  1
322  ) == 0)
323  {
325  }
326 
327  SendMessage(GetDlgItem(hwndDlg, IDC_FILEICON), STM_SETICON, (WPARAM)PvImageLargeIcon, 0);
328 
329  SetDlgItemText(hwndDlg, IDC_NAME, PvpGetStringOrNa(PvImageVersionInfo.FileDescription));
330  string = PhConcatStrings2(L"(Verifying...) ", PvpGetStringOrNa(PvImageVersionInfo.CompanyName));
331  SetDlgItemText(hwndDlg, IDC_COMPANYNAME, string->Buffer);
332  PhDereferenceObject(string);
333  SetDlgItemText(hwndDlg, IDC_VERSION, PvpGetStringOrNa(PvImageVersionInfo.FileVersion));
334 
335  PhQueueItemGlobalWorkQueue(VerifyImageThreadStart, hwndDlg);
336  }
337 
338  // PE properties
339 
340  switch (PvMappedImage.NtHeaders->FileHeader.Machine)
341  {
342  case IMAGE_FILE_MACHINE_I386:
343  type = L"i386";
344  break;
345  case IMAGE_FILE_MACHINE_AMD64:
346  type = L"AMD64";
347  break;
348  case IMAGE_FILE_MACHINE_IA64:
349  type = L"IA64";
350  break;
351  case IMAGE_FILE_MACHINE_ARMNT:
352  type = L"ARM Thumb-2";
353  break;
354  default:
355  type = L"Unknown";
356  break;
357  }
358 
359  SetDlgItemText(hwndDlg, IDC_TARGETMACHINE, type);
360 
361  {
362  LARGE_INTEGER time;
363  SYSTEMTIME systemTime;
364 
365  RtlSecondsSince1970ToTime(PvMappedImage.NtHeaders->FileHeader.TimeDateStamp, &time);
366  PhLargeIntegerToLocalSystemTime(&systemTime, &time);
367 
368  string = PhFormatDateTime(&systemTime);
369  SetDlgItemText(hwndDlg, IDC_TIMESTAMP, string->Buffer);
370  PhDereferenceObject(string);
371  }
372 
373  if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
374  {
375  string = PhFormatString(L"0x%Ix", PvMappedImage.NtHeaders->OptionalHeader.ImageBase);
376  }
377  else
378  {
379  string = PhFormatString(L"0x%I64x", ((PIMAGE_OPTIONAL_HEADER64)&PvMappedImage.NtHeaders->OptionalHeader)->ImageBase);
380  }
381 
382  SetDlgItemText(hwndDlg, IDC_IMAGEBASE, string->Buffer);
383  PhDereferenceObject(string);
384 
385  string = PhFormatString(L"0x%Ix (verifying...)", PvMappedImage.NtHeaders->OptionalHeader.CheckSum); // same for 32-bit and 64-bit images
386  SetDlgItemText(hwndDlg, IDC_CHECKSUM, string->Buffer);
387  PhDereferenceObject(string);
388 
389  PhQueueItemGlobalWorkQueue(CheckSumImageThreadStart, hwndDlg);
390 
391  switch (PvMappedImage.NtHeaders->OptionalHeader.Subsystem)
392  {
393  case IMAGE_SUBSYSTEM_NATIVE:
394  type = L"Native";
395  break;
396  case IMAGE_SUBSYSTEM_WINDOWS_GUI:
397  type = L"Windows GUI";
398  break;
399  case IMAGE_SUBSYSTEM_WINDOWS_CUI:
400  type = L"Windows CUI";
401  break;
402  case IMAGE_SUBSYSTEM_OS2_CUI:
403  type = L"OS/2 CUI";
404  break;
405  case IMAGE_SUBSYSTEM_POSIX_CUI:
406  type = L"POSIX CUI";
407  break;
408  case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
409  type = L"Windows CE CUI";
410  break;
411  case IMAGE_SUBSYSTEM_EFI_APPLICATION:
412  type = L"EFI Application";
413  break;
414  case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
415  type = L"EFI Boot Service Driver";
416  break;
417  case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
418  type = L"EFI Runtime Driver";
419  break;
420  case IMAGE_SUBSYSTEM_EFI_ROM:
421  type = L"EFI ROM";
422  break;
423  case IMAGE_SUBSYSTEM_XBOX:
424  type = L"Xbox";
425  break;
426  case IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
427  type = L"Windows Boot Application";
428  break;
429  default:
430  type = L"Unknown";
431  break;
432  }
433 
434  SetDlgItemText(hwndDlg, IDC_SUBSYSTEM, type);
435 
436  string = PhFormatString(
437  L"%u.%u",
438  PvMappedImage.NtHeaders->OptionalHeader.MajorSubsystemVersion, // same for 32-bit and 64-bit images
439  PvMappedImage.NtHeaders->OptionalHeader.MinorSubsystemVersion
440  );
441  SetDlgItemText(hwndDlg, IDC_SUBSYSTEMVERSION, string->Buffer);
442  PhDereferenceObject(string);
443 
444  PhInitializeStringBuilder(&stringBuilder, 10);
445 
446  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
447  PhAppendStringBuilder2(&stringBuilder, L"Executable, ");
448  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
449  PhAppendStringBuilder2(&stringBuilder, L"DLL, ");
450  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
451  PhAppendStringBuilder2(&stringBuilder, L"Large address aware, ");
452  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
453  PhAppendStringBuilder2(&stringBuilder, L"Removable run from swap, ");
454  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP)
455  PhAppendStringBuilder2(&stringBuilder, L"Net run from swap, ");
456  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_SYSTEM)
457  PhAppendStringBuilder2(&stringBuilder, L"System, ");
458  if (PvMappedImage.NtHeaders->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
459  PhAppendStringBuilder2(&stringBuilder, L"Uni-processor only, ");
460 
461  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA)
462  PhAppendStringBuilder2(&stringBuilder, L"High entropy VA, ");
463  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
464  PhAppendStringBuilder2(&stringBuilder, L"Dynamic base, ");
465  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY)
466  PhAppendStringBuilder2(&stringBuilder, L"Force integrity check, ");
467  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
468  PhAppendStringBuilder2(&stringBuilder, L"NX compatible, ");
469  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_ISOLATION)
470  PhAppendStringBuilder2(&stringBuilder, L"No isolation, ");
471  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH)
472  PhAppendStringBuilder2(&stringBuilder, L"No SEH, ");
473  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_BIND)
474  PhAppendStringBuilder2(&stringBuilder, L"Do not bind, ");
475  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_APPCONTAINER)
476  PhAppendStringBuilder2(&stringBuilder, L"AppContainer, ");
477  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WDM_DRIVER)
478  PhAppendStringBuilder2(&stringBuilder, L"WDM driver, ");
479  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF)
480  PhAppendStringBuilder2(&stringBuilder, L"Control Flow Guard, ");
481  if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
482  PhAppendStringBuilder2(&stringBuilder, L"Terminal server aware, ");
483 
484  if (PhEndsWithString2(stringBuilder.String, L", ", FALSE))
485  PhRemoveEndStringBuilder(&stringBuilder, 2);
486 
487  SetDlgItemText(hwndDlg, IDC_CHARACTERISTICS, stringBuilder.String->Buffer);
488  PhDeleteStringBuilder(&stringBuilder);
489 
490  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
491  PhSetListViewStyle(lvHandle, FALSE, TRUE);
492  PhSetControlTheme(lvHandle, L"explorer");
493  PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 80, L"Name");
494  PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"VA");
495  PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 80, L"Size");
496 
497  for (i = 0; i < PvMappedImage.NumberOfSections; i++)
498  {
499  INT lvItemIndex;
500  WCHAR sectionName[9];
501  WCHAR pointer[PH_PTR_STR_LEN_1];
502 
503  if (PhCopyStringZFromBytes(PvMappedImage.Sections[i].Name,
504  IMAGE_SIZEOF_SHORT_NAME, sectionName, 9, NULL))
505  {
506  lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, sectionName, NULL);
507 
508  PhPrintPointer(pointer, (PVOID)PvMappedImage.Sections[i].VirtualAddress);
509  PhSetListViewSubItem(lvHandle, lvItemIndex, 1, pointer);
510 
511  PhPrintPointer(pointer, (PVOID)PvMappedImage.Sections[i].SizeOfRawData);
512  PhSetListViewSubItem(lvHandle, lvItemIndex, 2, pointer);
513  }
514  }
515  }
516  break;
517  case PVM_CHECKSUM_DONE:
518  {
519  PPH_STRING string;
520  ULONG headerCheckSum;
521  ULONG realCheckSum;
522 
523  headerCheckSum = PvMappedImage.NtHeaders->OptionalHeader.CheckSum; // same for 32-bit and 64-bit images
524  realCheckSum = (ULONG)wParam;
525 
526  if (headerCheckSum == 0)
527  {
528  // Some executables, like .NET ones, don't have a check sum.
529  string = PhFormatString(L"0x0 (real 0x%Ix)", realCheckSum);
530  SetDlgItemText(hwndDlg, IDC_CHECKSUM, string->Buffer);
531  PhDereferenceObject(string);
532  }
533  else if (headerCheckSum == realCheckSum)
534  {
535  string = PhFormatString(L"0x%Ix (correct)", headerCheckSum);
536  SetDlgItemText(hwndDlg, IDC_CHECKSUM, string->Buffer);
537  PhDereferenceObject(string);
538  }
539  else
540  {
541  string = PhFormatString(L"0x%Ix (incorrect, real 0x%Ix)", headerCheckSum, realCheckSum);
542  SetDlgItemText(hwndDlg, IDC_CHECKSUM, string->Buffer);
543  PhDereferenceObject(string);
544  }
545  }
546  break;
547  case PVM_VERIFY_DONE:
548  {
549  PPH_STRING string;
550 
552  {
553  if (PvImageSignerName)
554  {
555  string = PhFormatString(L"<a>(Verified) %s</a>", PvImageSignerName->Buffer);
556  SetDlgItemText(hwndDlg, IDC_COMPANYNAME_LINK, string->Buffer);
557  PhDereferenceObject(string);
558  ShowWindow(GetDlgItem(hwndDlg, IDC_COMPANYNAME), SW_HIDE);
559  ShowWindow(GetDlgItem(hwndDlg, IDC_COMPANYNAME_LINK), SW_SHOW);
560  }
561  else
562  {
563  string = PhConcatStrings2(L"(Verified) ", PhGetStringOrEmpty(PvImageVersionInfo.CompanyName));
564  SetDlgItemText(hwndDlg, IDC_COMPANYNAME, string->Buffer);
565  PhDereferenceObject(string);
566  }
567  }
568  else if (PvImageVerifyResult != VrUnknown)
569  {
570  string = PhConcatStrings2(L"(UNVERIFIED) ", PhGetStringOrEmpty(PvImageVersionInfo.CompanyName));
571  SetDlgItemText(hwndDlg, IDC_COMPANYNAME, string->Buffer);
572  PhDereferenceObject(string);
573  }
574  else
575  {
576  SetDlgItemText(hwndDlg, IDC_COMPANYNAME, PvpGetStringOrNa(PvImageVersionInfo.CompanyName));
577  }
578  }
579  break;
580  case WM_NOTIFY:
581  {
582  LPNMHDR header = (LPNMHDR)lParam;
583 
584  switch (header->code)
585  {
586  case NM_CLICK:
587  {
588  switch (header->idFrom)
589  {
591  {
593  }
594  break;
595  }
596  }
597  break;
598  }
599 
600  PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
601  }
602  break;
603  }
604 
605  return FALSE;
606 }
607 
609  _In_ HWND ListViewHandle,
610  _In_ PPH_MAPPED_IMAGE_IMPORTS Imports,
611  _In_ BOOLEAN DelayImports
612  )
613 {
614  PH_MAPPED_IMAGE_IMPORT_DLL importDll;
615  PH_MAPPED_IMAGE_IMPORT_ENTRY importEntry;
616  ULONG i;
617  ULONG j;
618 
619  for (i = 0; i < Imports->NumberOfDlls; i++)
620  {
621  if (NT_SUCCESS(PhGetMappedImageImportDll(Imports, i, &importDll)))
622  {
623  for (j = 0; j < importDll.NumberOfEntries; j++)
624  {
625  if (NT_SUCCESS(PhGetMappedImageImportEntry(&importDll, j, &importEntry)))
626  {
627  INT lvItemIndex;
628  PPH_STRING name;
629  WCHAR number[PH_INT32_STR_LEN_1];
630 
631  if (!DelayImports)
632  name = PhZeroExtendToUtf16(importDll.Name);
633  else
634  name = PhFormatString(L"%S (Delay)", importDll.Name);
635 
636  lvItemIndex = PhAddListViewItem(ListViewHandle, MAXINT, name->Buffer, NULL);
637  PhDereferenceObject(name);
638 
639  if (importEntry.Name)
640  {
641  name = PhZeroExtendToUtf16(importEntry.Name);
642  PhSetListViewSubItem(ListViewHandle, lvItemIndex, 1, name->Buffer);
643  PhDereferenceObject(name);
644 
645  PhPrintUInt32(number, importEntry.NameHint);
646  PhSetListViewSubItem(ListViewHandle, lvItemIndex, 2, number);
647  }
648  else
649  {
650  name = PhFormatString(L"(Ordinal %u)", importEntry.Ordinal);
651  PhSetListViewSubItem(ListViewHandle, lvItemIndex, 1, name->Buffer);
652  PhDereferenceObject(name);
653  }
654  }
655  }
656  }
657  }
658 }
659 
660 INT_PTR CALLBACK PvpPeImportsDlgProc(
661  _In_ HWND hwndDlg,
662  _In_ UINT uMsg,
663  _In_ WPARAM wParam,
664  _In_ LPARAM lParam
665  )
666 {
667  switch (uMsg)
668  {
669  case WM_INITDIALOG:
670  {
671  ULONG fallbackColumns[] = { 0, 1, 2 };
672  HWND lvHandle;
673  PH_MAPPED_IMAGE_IMPORTS imports;
674 
675  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
676  PhSetListViewStyle(lvHandle, FALSE, TRUE);
677  PhSetControlTheme(lvHandle, L"explorer");
678  PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 130, L"DLL");
679  PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 210, L"Name");
680  PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 50, L"Hint");
681  PhSetExtendedListView(lvHandle);
682  ExtendedListView_AddFallbackColumns(lvHandle, 3, fallbackColumns);
683 
684  if (NT_SUCCESS(PhGetMappedImageImports(&imports, &PvMappedImage)))
685  {
686  PvpProcessImports(lvHandle, &imports, FALSE);
687  }
688 
689  if (NT_SUCCESS(PhGetMappedImageDelayImports(&imports, &PvMappedImage)))
690  {
691  PvpProcessImports(lvHandle, &imports, TRUE);
692  }
693 
694  ExtendedListView_SortItems(lvHandle);
695  }
696  break;
697  case WM_NOTIFY:
698  {
699  PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
700  }
701  break;
702  }
703 
704  return FALSE;
705 }
706 
707 INT_PTR CALLBACK PvpPeExportsDlgProc(
708  _In_ HWND hwndDlg,
709  _In_ UINT uMsg,
710  _In_ WPARAM wParam,
711  _In_ LPARAM lParam
712  )
713 {
714  switch (uMsg)
715  {
716  case WM_INITDIALOG:
717  {
718  HWND lvHandle;
719  PH_MAPPED_IMAGE_EXPORTS exports;
720  PH_MAPPED_IMAGE_EXPORT_ENTRY exportEntry;
721  PH_MAPPED_IMAGE_EXPORT_FUNCTION exportFunction;
722  ULONG i;
723 
724  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
725  PhSetListViewStyle(lvHandle, FALSE, TRUE);
726  PhSetControlTheme(lvHandle, L"explorer");
727  PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 220, L"Name");
728  PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 50, L"Ordinal");
729  PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 120, L"VA");
730  PhSetExtendedListView(lvHandle);
731 
732  if (NT_SUCCESS(PhGetMappedImageExports(&exports, &PvMappedImage)))
733  {
734  for (i = 0; i < exports.NumberOfEntries; i++)
735  {
736  if (
737  NT_SUCCESS(PhGetMappedImageExportEntry(&exports, i, &exportEntry)) &&
738  NT_SUCCESS(PhGetMappedImageExportFunction(&exports, NULL, exportEntry.Ordinal, &exportFunction))
739  )
740  {
741  INT lvItemIndex;
742  PPH_STRING name;
743  WCHAR number[PH_INT32_STR_LEN_1];
744  WCHAR pointer[PH_PTR_STR_LEN_1];
745 
746  if (exportEntry.Name)
747  {
748  name = PhZeroExtendToUtf16(exportEntry.Name);
749  lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, name->Buffer, NULL);
750  PhDereferenceObject(name);
751  }
752  else
753  {
754  lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, L"(unnamed)", NULL);
755  }
756 
757  PhPrintUInt32(number, exportEntry.Ordinal);
758  PhSetListViewSubItem(lvHandle, lvItemIndex, 1, number);
759 
760  if (!exportFunction.ForwardedName)
761  {
762  if ((ULONG_PTR)exportFunction.Function >= (ULONG_PTR)PvMappedImage.ViewBase)
763  PhPrintPointer(pointer, PTR_SUB_OFFSET(exportFunction.Function, PvMappedImage.ViewBase));
764  else
765  PhPrintPointer(pointer, exportFunction.Function);
766 
767  PhSetListViewSubItem(lvHandle, lvItemIndex, 2, pointer);
768  }
769  else
770  {
771  name = PhZeroExtendToUtf16(exportFunction.ForwardedName);
772  PhSetListViewSubItem(lvHandle, lvItemIndex, 2, name->Buffer);
773  PhDereferenceObject(name);
774  }
775  }
776  }
777  }
778 
779  ExtendedListView_SortItems(lvHandle);
780  }
781  break;
782  case WM_NOTIFY:
783  {
784  PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
785  }
786  break;
787  }
788 
789  return FALSE;
790 }
791 
792 INT_PTR CALLBACK PvpPeLoadConfigDlgProc(
793  _In_ HWND hwndDlg,
794  _In_ UINT uMsg,
795  _In_ WPARAM wParam,
796  _In_ LPARAM lParam
797  )
798 {
799  switch (uMsg)
800  {
801  case WM_INITDIALOG:
802  {
803  PH_AUTO_POOL autoPool;
804  HWND lvHandle;
805  PIMAGE_LOAD_CONFIG_DIRECTORY32 config32;
806  PIMAGE_LOAD_CONFIG_DIRECTORY64 config64;
807  PPH_STRING string;
808 
809  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
810  PhSetListViewStyle(lvHandle, FALSE, TRUE);
811  PhSetControlTheme(lvHandle, L"explorer");
812  PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 220, L"Name");
813  PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 170, L"Value");
814 
815 #define ADD_VALUE(Name, Value) \
816  do { \
817  INT lvItemIndex; \
818  \
819  lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, Name, NULL); \
820  PhSetListViewSubItem(lvHandle, lvItemIndex, 1, Value); \
821  } while (0)
822 
823 #define ADD_VALUES(Config) \
824  do { \
825  { \
826  LARGE_INTEGER time; \
827  SYSTEMTIME systemTime; \
828  \
829  RtlSecondsSince1970ToTime((Config)->TimeDateStamp, &time); \
830  PhLargeIntegerToLocalSystemTime(&systemTime, &time); \
831  \
832  string = PhFormatDateTime(&systemTime); \
833  ADD_VALUE(L"Time stamp", string->Buffer); \
834  PhDereferenceObject(string); \
835  } \
836  \
837  ADD_VALUE(L"Version", PhaFormatString(L"%u.%u", (Config)->MajorVersion, (Config)->MinorVersion)->Buffer); \
838  ADD_VALUE(L"Global flags to clear", PhaFormatString(L"0x%x", (Config)->GlobalFlagsClear)->Buffer); \
839  ADD_VALUE(L"Global flags to set", PhaFormatString(L"0x%x", (Config)->GlobalFlagsSet)->Buffer); \
840  ADD_VALUE(L"Critical section default timeout", PhaFormatUInt64((Config)->CriticalSectionDefaultTimeout, TRUE)->Buffer); \
841  ADD_VALUE(L"De-commit free block threshold", PhaFormatUInt64((Config)->DeCommitFreeBlockThreshold, TRUE)->Buffer); \
842  ADD_VALUE(L"De-commit total free threshold", PhaFormatUInt64((Config)->DeCommitTotalFreeThreshold, TRUE)->Buffer); \
843  ADD_VALUE(L"LOCK prefix table", PhaFormatString(L"0x%Ix", (Config)->LockPrefixTable)->Buffer); \
844  ADD_VALUE(L"Maximum allocation size", PhaFormatString(L"0x%Ix", (Config)->MaximumAllocationSize)->Buffer); \
845  ADD_VALUE(L"Virtual memory threshold", PhaFormatString(L"0x%Ix", (Config)->VirtualMemoryThreshold)->Buffer); \
846  ADD_VALUE(L"Process affinity mask", PhaFormatString(L"0x%Ix", (Config)->ProcessAffinityMask)->Buffer); \
847  ADD_VALUE(L"Process heap flags", PhaFormatString(L"0x%Ix", (Config)->ProcessHeapFlags)->Buffer); \
848  ADD_VALUE(L"CSD version", PhaFormatString(L"%u", (Config)->CSDVersion)->Buffer); \
849  ADD_VALUE(L"Edit list", PhaFormatString(L"0x%Ix", (Config)->EditList)->Buffer); \
850  ADD_VALUE(L"Security cookie", PhaFormatString(L"0x%Ix", (Config)->SecurityCookie)->Buffer); \
851  ADD_VALUE(L"SEH handler table", PhaFormatString(L"0x%Ix", (Config)->SEHandlerTable)->Buffer); \
852  ADD_VALUE(L"SEH handler count", PhaFormatUInt64((Config)->SEHandlerCount, TRUE)->Buffer); \
853  } while (0)
854 
855  PhInitializeAutoPool(&autoPool);
856 
857  if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
858  {
859  if (NT_SUCCESS(PhGetMappedImageLoadConfig32(&PvMappedImage, &config32)))
860  {
861  ADD_VALUES(config32);
862  }
863  }
864  else
865  {
866  if (NT_SUCCESS(PhGetMappedImageLoadConfig64(&PvMappedImage, &config64)))
867  {
868  ADD_VALUES(config64);
869  }
870  }
871 
872  PhDeleteAutoPool(&autoPool);
873  }
874  break;
875  case WM_NOTIFY:
876  {
877  PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
878  }
879  break;
880  }
881 
882  return FALSE;
883 }
884 
885 INT_PTR CALLBACK PvpPeClrDlgProc(
886  _In_ HWND hwndDlg,
887  _In_ UINT uMsg,
888  _In_ WPARAM wParam,
889  _In_ LPARAM lParam
890  )
891 {
892  switch (uMsg)
893  {
894  case WM_INITDIALOG:
895  {
896  PH_STRING_BUILDER stringBuilder;
897  PPH_STRING string;
898  PVOID metaData;
899  ULONG versionStringLength;
900 
901  string = PhFormatString(L"%u.%u", PvImageCor20Header->MajorRuntimeVersion,
902  PvImageCor20Header->MinorRuntimeVersion);
903  SetDlgItemText(hwndDlg, IDC_RUNTIMEVERSION, string->Buffer);
904  PhDereferenceObject(string);
905 
906  PhInitializeStringBuilder(&stringBuilder, 256);
907 
908  if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_ILONLY)
909  PhAppendStringBuilder2(&stringBuilder, L"IL only, ");
910  if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_32BITREQUIRED)
911  PhAppendStringBuilder2(&stringBuilder, L"32-bit only, ");
912  if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_IL_LIBRARY)
913  PhAppendStringBuilder2(&stringBuilder, L"IL library, ");
914 
915  if (PvImageCor20Header->StrongNameSignature.VirtualAddress != 0 && PvImageCor20Header->StrongNameSignature.Size != 0)
916  {
917  if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_STRONGNAMESIGNED)
918  PhAppendStringBuilder2(&stringBuilder, L"Strong-name signed, ");
919  else
920  PhAppendStringBuilder2(&stringBuilder, L"Strong-name delay signed, ");
921  }
922 
923  if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT)
924  PhAppendStringBuilder2(&stringBuilder, L"Native entry-point, ");
925  if (PvImageCor20Header->Flags & COMIMAGE_FLAGS_TRACKDEBUGDATA)
926  PhAppendStringBuilder2(&stringBuilder, L"Track debug data, ");
927 
928  if (PhEndsWithString2(stringBuilder.String, L", ", FALSE))
929  PhRemoveEndStringBuilder(&stringBuilder, 2);
930 
931  SetDlgItemText(hwndDlg, IDC_FLAGS, stringBuilder.String->Buffer);
932  PhDeleteStringBuilder(&stringBuilder);
933 
934  metaData = PhMappedImageRvaToVa(&PvMappedImage, PvImageCor20Header->MetaData.VirtualAddress, NULL);
935 
936  if (metaData)
937  {
938  __try
939  {
940  PhProbeAddress(metaData, PvImageCor20Header->MetaData.Size, PvMappedImage.ViewBase, PvMappedImage.Size, 4);
941  }
942  __except (EXCEPTION_EXECUTE_HANDLER)
943  {
944  metaData = NULL;
945  }
946  }
947 
948  versionStringLength = 0;
949 
950  if (metaData)
951  {
952  // Skip 12 bytes.
953  // First 4 bytes contains the length of the version string.
954  // The version string follows.
955  versionStringLength = *(PULONG)((PCHAR)metaData + 12);
956 
957  // Make sure the length is valid.
958  if (versionStringLength >= 0x100)
959  versionStringLength = 0;
960  }
961 
962  if (versionStringLength != 0)
963  {
964  string = PhZeroExtendToUtf16Ex((PCHAR)metaData + 12 + 4, versionStringLength);
965  SetDlgItemText(hwndDlg, IDC_VERSIONSTRING, string->Buffer);
966  PhDereferenceObject(string);
967  }
968  else
969  {
970  SetDlgItemText(hwndDlg, IDC_VERSIONSTRING, L"N/A");
971  }
972  }
973  break;
974  case WM_NOTIFY:
975  {
976  LPNMHDR header = (LPNMHDR)lParam;
977 
978  switch (header->code)
979  {
980  case PSN_QUERYINITIALFOCUS:
981  {
982  SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_RUNTIMEVERSION));
983  }
984  return TRUE;
985  }
986  }
987  break;
988  }
989 
990  return FALSE;
991 }