-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathJclPeImage.pas
6939 lines (6386 loc) · 220 KB
/
JclPeImage.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{**************************************************************************************************}
{ }
{ Project JEDI Code Library (JCL) }
{ }
{ The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
{ you may not use this file except in compliance with the License. You may obtain a copy of the }
{ License at http://www.mozilla.org/MPL/ }
{ }
{ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
{ ANY KIND, either express or implied. See the License for the specific language governing rights }
{ and limitations under the License. }
{ }
{ The Original Code is JclPeImage.pas. }
{ }
{ The Initial Developer of the Original Code is Petr Vones. Portions created by Petr Vones are }
{ Copyright (C) Petr Vones. All Rights Reserved. }
{ }
{ Contributor(s): }
{ Marcel van Brakel }
{ Robert Marquardt (marquardt) }
{ Uwe Schuster (uschuster) }
{ Matthias Thoma (mthoma) }
{ Petr Vones (pvones) }
{ Hallvard Vassbotn }
{ Jean-Fabien Connault (cycocrew) }
{ }
{**************************************************************************************************}
{ }
{ This unit contains various classes and support routines to read the contents of portable }
{ executable (PE) files. You can use these classes to, for example examine the contents of the }
{ imports section of an executable. In addition the unit contains support for Borland specific }
{ structures and name unmangling. }
{ }
{**************************************************************************************************}
{ }
{ Last modified: $Date:: 2013-05-13 21:15:06 +0200 $ }
{ Revision: $Rev:: 5a26dc1cafb60f4dcaf1e677a6fb03cc30db43b3 $ }
{ Author: $Author:: Andreas Hausladen $ }
{ }
{**************************************************************************************************}
unit JclPeImage;
{$I jcl.inc}
{$I windowsonly.inc}
interface
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
{$IFDEF HAS_UNITSCOPE}
Winapi.Windows, System.Classes, System.SysUtils, System.TypInfo, System.Contnrs,
{$ELSE ~HAS_UNITSCOPE}
Windows, Classes, SysUtils, TypInfo, Contnrs,
{$ENDIF ~HAS_UNITSCOPE}
JclBase, JclDateTime, JclFileUtils, JclWin32;
type
// Smart name compare function
TJclSmartCompOption = (scSimpleCompare, scIgnoreCase);
TJclSmartCompOptions = set of TJclSmartCompOption;
function PeStripFunctionAW(const FunctionName: string): string;
function PeSmartFunctionNameSame(const ComparedName, FunctionName: string;
Options: TJclSmartCompOptions = []): Boolean;
type
// Base list
EJclPeImageError = class(EJclError);
TJclPeImage = class;
TJclPeImageClass = class of TJclPeImage;
TJclPeImageBaseList = class(TObjectList)
private
FImage: TJclPeImage;
public
constructor Create(AImage: TJclPeImage);
property Image: TJclPeImage read FImage;
end;
// Images cache
TJclPeImagesCache = class(TObject)
private
FList: TStringList;
function GetCount: Integer;
function GetImages(const FileName: TFileName): TJclPeImage;
protected
function GetPeImageClass: TJclPeImageClass; virtual;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
property Images[const FileName: TFileName]: TJclPeImage read GetImages; default;
property Count: Integer read GetCount;
end;
// Import section related classes
TJclPeImportSort = (isName, isOrdinal, isHint, isLibImport);
TJclPeImportLibSort = (ilName, ilIndex);
TJclPeImportKind = (ikImport, ikDelayImport, ikBoundImport);
TJclPeResolveCheck = (icNotChecked, icResolved, icUnresolved);
TJclPeLinkerProducer = (lrBorland, lrMicrosoft);
// lrBorland -> Delphi PE files
// lrMicrosoft -> MSVC and BCB PE files
TJclPeImportLibItem = class;
// Created from a IMAGE_THUNK_DATA64 or IMAGE_THUNK_DATA32 record
TJclPeImportFuncItem = class(TObject)
private
FOrdinal: Word; // word in 32/64
FHint: Word;
FImportLib: TJclPeImportLibItem;
FIndirectImportName: Boolean;
FName: string;
FResolveCheck: TJclPeResolveCheck;
function GetIsByOrdinal: Boolean;
protected
procedure SetName(const Value: string);
procedure SetIndirectImportName(const Value: string);
procedure SetResolveCheck(Value: TJclPeResolveCheck);
public
constructor Create(AImportLib: TJclPeImportLibItem; AOrdinal: Word;
AHint: Word; const AName: string);
property Ordinal: Word read FOrdinal;
property Hint: Word read FHint;
property ImportLib: TJclPeImportLibItem read FImportLib;
property IndirectImportName: Boolean read FIndirectImportName;
property IsByOrdinal: Boolean read GetIsByOrdinal;
property Name: string read FName;
property ResolveCheck: TJclPeResolveCheck read FResolveCheck;
end;
// Created from a IMAGE_IMPORT_DESCRIPTOR
TJclPeImportLibItem = class(TJclPeImageBaseList)
private
FImportDescriptor: Pointer;
FImportDirectoryIndex: Integer;
FImportKind: TJclPeImportKind;
FLastSortType: TJclPeImportSort;
FLastSortDescending: Boolean;
FName: string;
FSorted: Boolean;
FTotalResolveCheck: TJclPeResolveCheck;
FThunk: Pointer;
FThunkData: Pointer;
function GetCount: Integer;
function GetFileName: TFileName;
function GetItems(Index: Integer): TJclPeImportFuncItem;
function GetName: string;
function GetThunkData32: PImageThunkData32;
function GetThunkData64: PImageThunkData64;
protected
procedure CheckImports(ExportImage: TJclPeImage);
procedure CreateList;
procedure SetImportDirectoryIndex(Value: Integer);
procedure SetImportKind(Value: TJclPeImportKind);
procedure SetSorted(Value: Boolean);
procedure SetThunk(Value: Pointer);
public
constructor Create(AImage: TJclPeImage; AImportDescriptor: Pointer;
AImportKind: TJclPeImportKind; const AName: string; AThunk: Pointer);
procedure SortList(SortType: TJclPeImportSort; Descending: Boolean = False);
property Count: Integer read GetCount;
property FileName: TFileName read GetFileName;
property ImportDescriptor: Pointer read FImportDescriptor;
property ImportDirectoryIndex: Integer read FImportDirectoryIndex;
property ImportKind: TJclPeImportKind read FImportKind;
property Items[Index: Integer]: TJclPeImportFuncItem read GetItems; default;
property Name: string read GetName;
property OriginalName: string read FName;
// use the following properties
// property ThunkData: PImageThunkData
property ThunkData32: PImageThunkData32 read GetThunkData32;
property ThunkData64: PImageThunkData64 read GetThunkData64;
property TotalResolveCheck: TJclPeResolveCheck read FTotalResolveCheck;
end;
TJclPeImportList = class(TJclPeImageBaseList)
private
FAllItemsList: TList;
FFilterModuleName: string;
FLastAllSortType: TJclPeImportSort;
FLastAllSortDescending: Boolean;
FLinkerProducer: TJclPeLinkerProducer;
FParallelImportTable: array of Pointer;
FUniqueNamesList: TStringList;
function GetAllItemCount: Integer;
function GetAllItems(Index: Integer): TJclPeImportFuncItem;
function GetItems(Index: Integer): TJclPeImportLibItem;
function GetUniqueLibItemCount: Integer;
function GetUniqueLibItems(Index: Integer): TJclPeImportLibItem;
function GetUniqueLibNames(Index: Integer): string;
function GetUniqueLibItemFromName(const Name: string): TJclPeImportLibItem;
procedure SetFilterModuleName(const Value: string);
protected
procedure CreateList;
procedure RefreshAllItems;
public
constructor Create(AImage: TJclPeImage);
destructor Destroy; override;
procedure CheckImports(PeImageCache: TJclPeImagesCache = nil);
function MakeBorlandImportTableForMappedImage: Boolean;
function SmartFindName(const CompareName, LibName: string; Options: TJclSmartCompOptions = []): TJclPeImportFuncItem;
procedure SortAllItemsList(SortType: TJclPeImportSort; Descending: Boolean = False);
procedure SortList(SortType: TJclPeImportLibSort);
procedure TryGetNamesForOrdinalImports;
property AllItems[Index: Integer]: TJclPeImportFuncItem read GetAllItems;
property AllItemCount: Integer read GetAllItemCount;
property FilterModuleName: string read FFilterModuleName write SetFilterModuleName;
property Items[Index: Integer]: TJclPeImportLibItem read GetItems; default;
property LinkerProducer: TJclPeLinkerProducer read FLinkerProducer;
property UniqueLibItemCount: Integer read GetUniqueLibItemCount;
property UniqueLibItemFromName[const Name: string]: TJclPeImportLibItem read GetUniqueLibItemFromName;
property UniqueLibItems[Index: Integer]: TJclPeImportLibItem read GetUniqueLibItems;
property UniqueLibNames[Index: Integer]: string read GetUniqueLibNames;
end;
// Export section related classes
TJclPeExportSort = (esName, esOrdinal, esHint, esAddress, esForwarded, esAddrOrFwd, esSection);
TJclPeExportFuncList = class;
// Created from a IMAGE_EXPORT_DIRECTORY
TJclPeExportFuncItem = class(TObject)
private
FAddress: DWORD;
FExportList: TJclPeExportFuncList;
FForwardedName: string;
FForwardedDotPos: string;
FHint: Word;
FName: string;
FOrdinal: Word;
FResolveCheck: TJclPeResolveCheck;
function GetAddressOrForwardStr: string;
function GetForwardedFuncName: string;
function GetForwardedLibName: string;
function GetForwardedFuncOrdinal: DWORD;
function GetIsExportedVariable: Boolean;
function GetIsForwarded: Boolean;
function GetSectionName: string;
function GetMappedAddress: Pointer;
protected
procedure SetResolveCheck(Value: TJclPeResolveCheck);
public
constructor Create(AExportList: TJclPeExportFuncList; const AName, AForwardedName: string;
AAddress: DWORD; AHint: Word; AOrdinal: Word; AResolveCheck: TJclPeResolveCheck);
property Address: DWORD read FAddress;
property AddressOrForwardStr: string read GetAddressOrForwardStr;
property IsExportedVariable: Boolean read GetIsExportedVariable;
property IsForwarded: Boolean read GetIsForwarded;
property ForwardedName: string read FForwardedName;
property ForwardedLibName: string read GetForwardedLibName;
property ForwardedFuncOrdinal: DWORD read GetForwardedFuncOrdinal;
property ForwardedFuncName: string read GetForwardedFuncName;
property Hint: Word read FHint;
property MappedAddress: Pointer read GetMappedAddress;
property Name: string read FName;
property Ordinal: Word read FOrdinal;
property ResolveCheck: TJclPeResolveCheck read FResolveCheck;
property SectionName: string read GetSectionName;
end;
TJclPeExportFuncList = class(TJclPeImageBaseList)
private
FAnyForwards: Boolean;
FBase: DWORD;
FExportDir: PImageExportDirectory;
FForwardedLibsList: TStringList;
FFunctionCount: DWORD;
FLastSortType: TJclPeExportSort;
FLastSortDescending: Boolean;
FSorted: Boolean;
FTotalResolveCheck: TJclPeResolveCheck;
function GetForwardedLibsList: TStrings;
function GetItems(Index: Integer): TJclPeExportFuncItem;
function GetItemFromAddress(Address: DWORD): TJclPeExportFuncItem;
function GetItemFromOrdinal(Ordinal: DWORD): TJclPeExportFuncItem;
function GetItemFromName(const Name: string): TJclPeExportFuncItem;
function GetName: string;
protected
function CanPerformFastNameSearch: Boolean;
procedure CreateList;
property LastSortType: TJclPeExportSort read FLastSortType;
property LastSortDescending: Boolean read FLastSortDescending;
property Sorted: Boolean read FSorted;
public
constructor Create(AImage: TJclPeImage);
destructor Destroy; override;
procedure CheckForwards(PeImageCache: TJclPeImagesCache = nil);
class function ItemName(Item: TJclPeExportFuncItem): string;
function OrdinalValid(Ordinal: DWORD): Boolean;
procedure PrepareForFastNameSearch;
function SmartFindName(const CompareName: string; Options: TJclSmartCompOptions = []): TJclPeExportFuncItem;
procedure SortList(SortType: TJclPeExportSort; Descending: Boolean = False);
property AnyForwards: Boolean read FAnyForwards;
property Base: DWORD read FBase;
property ExportDir: PImageExportDirectory read FExportDir;
property ForwardedLibsList: TStrings read GetForwardedLibsList;
property FunctionCount: DWORD read FFunctionCount;
property Items[Index: Integer]: TJclPeExportFuncItem read GetItems; default;
property ItemFromAddress[Address: DWORD]: TJclPeExportFuncItem read GetItemFromAddress;
property ItemFromName[const Name: string]: TJclPeExportFuncItem read GetItemFromName;
property ItemFromOrdinal[Ordinal: DWORD]: TJclPeExportFuncItem read GetItemFromOrdinal;
property Name: string read GetName;
property TotalResolveCheck: TJclPeResolveCheck read FTotalResolveCheck;
end;
// Resource section related classes
TJclPeResourceKind = (
rtUnknown0,
rtCursorEntry,
rtBitmap,
rtIconEntry,
rtMenu,
rtDialog,
rtString,
rtFontDir,
rtFont,
rtAccelerators,
rtRCData,
rtMessageTable,
rtCursor,
rtUnknown13,
rtIcon,
rtUnknown15,
rtVersion,
rtDlgInclude,
rtUnknown18,
rtPlugPlay,
rtVxd,
rtAniCursor,
rtAniIcon,
rtHmtl,
rtManifest,
rtUserDefined);
TJclPeResourceList = class;
TJclPeResourceItem = class;
TJclPeResourceRawStream = class(TCustomMemoryStream)
public
constructor Create(AResourceItem: TJclPeResourceItem);
function Write(const Buffer; Count: Longint): Longint; override;
end;
TJclPeResourceItem = class(TObject)
private
FEntry: PImageResourceDirectoryEntry;
FImage: TJclPeImage;
FList: TJclPeResourceList;
FLevel: Byte;
FParentItem: TJclPeResourceItem;
FNameCache: string;
function GetDataEntry: PImageResourceDataEntry;
function GetIsDirectory: Boolean;
function GetIsName: Boolean;
function GetLangID: LANGID;
function GetList: TJclPeResourceList;
function GetName: string;
function GetParameterName: string;
function GetRawEntryData: Pointer;
function GetRawEntryDataSize: Integer;
function GetResourceType: TJclPeResourceKind;
function GetResourceTypeStr: string;
protected
function OffsetToRawData(Ofs: DWORD): TJclAddr;
function Level1Item: TJclPeResourceItem;
function SubDirData: PImageResourceDirectory;
public
constructor Create(AImage: TJclPeImage; AParentItem: TJclPeResourceItem;
AEntry: PImageResourceDirectoryEntry);
destructor Destroy; override;
function CompareName(AName: PChar): Boolean;
property DataEntry: PImageResourceDataEntry read GetDataEntry;
property Entry: PImageResourceDirectoryEntry read FEntry;
property Image: TJclPeImage read FImage;
property IsDirectory: Boolean read GetIsDirectory;
property IsName: Boolean read GetIsName;
property LangID: LANGID read GetLangID;
property List: TJclPeResourceList read GetList;
property Level: Byte read FLevel;
property Name: string read GetName;
property ParameterName: string read GetParameterName;
property ParentItem: TJclPeResourceItem read FParentItem;
property RawEntryData: Pointer read GetRawEntryData;
property RawEntryDataSize: Integer read GetRawEntryDataSize;
property ResourceType: TJclPeResourceKind read GetResourceType;
property ResourceTypeStr: string read GetResourceTypeStr;
end;
TJclPeResourceList = class(TJclPeImageBaseList)
private
FDirectory: PImageResourceDirectory;
FParentItem: TJclPeResourceItem;
function GetItems(Index: Integer): TJclPeResourceItem;
protected
procedure CreateList(AParentItem: TJclPeResourceItem);
public
constructor Create(AImage: TJclPeImage; AParentItem: TJclPeResourceItem;
ADirectory: PImageResourceDirectory);
function FindName(const Name: string): TJclPeResourceItem;
property Directory: PImageResourceDirectory read FDirectory;
property Items[Index: Integer]: TJclPeResourceItem read GetItems; default;
property ParentItem: TJclPeResourceItem read FParentItem;
end;
TJclPeRootResourceList = class(TJclPeResourceList)
private
FManifestContent: TStringList;
function GetManifestContent: TStrings;
public
destructor Destroy; override;
function FindResource(ResourceType: TJclPeResourceKind;
const ResourceName: string = ''): TJclPeResourceItem; overload;
function FindResource(const ResourceType: PChar;
const ResourceName: PChar = nil): TJclPeResourceItem; overload;
function ListResourceNames(ResourceType: TJclPeResourceKind; const Strings: TStrings): Boolean;
property ManifestContent: TStrings read GetManifestContent;
end;
// Relocation section related classes
TJclPeRelocation = record
Address: Word;
RelocType: Byte;
VirtualAddress: DWORD;
end;
TJclPeRelocEntry = class(TObject)
private
FChunk: PImageBaseRelocation;
FCount: Integer;
function GetRelocations(Index: Integer): TJclPeRelocation;
function GetSize: DWORD;
function GetVirtualAddress: DWORD;
public
constructor Create(AChunk: PImageBaseRelocation; ACount: Integer);
property Count: Integer read FCount;
property Relocations[Index: Integer]: TJclPeRelocation read GetRelocations; default;
property Size: DWORD read GetSize;
property VirtualAddress: DWORD read GetVirtualAddress;
end;
TJclPeRelocList = class(TJclPeImageBaseList)
private
FAllItemCount: Integer;
function GetItems(Index: Integer): TJclPeRelocEntry;
function GetAllItems(Index: Integer): TJclPeRelocation;
protected
procedure CreateList;
public
constructor Create(AImage: TJclPeImage);
property AllItems[Index: Integer]: TJclPeRelocation read GetAllItems;
property AllItemCount: Integer read FAllItemCount;
property Items[Index: Integer]: TJclPeRelocEntry read GetItems; default;
end;
// Debug section related classes
TJclPeDebugList = class(TJclPeImageBaseList)
private
function GetItems(Index: Integer): TImageDebugDirectory;
protected
procedure CreateList;
public
constructor Create(AImage: TJclPeImage);
property Items[Index: Integer]: TImageDebugDirectory read GetItems; default;
end;
// Certificates section related classes
TJclPeCertificate = class(TObject)
private
FData: Pointer;
FHeader: TWinCertificate;
public
constructor Create(AHeader: TWinCertificate; AData: Pointer);
property Data: Pointer read FData;
property Header: TWinCertificate read FHeader;
end;
TJclPeCertificateList = class(TJclPeImageBaseList)
private
function GetItems(Index: Integer): TJclPeCertificate;
protected
procedure CreateList;
public
constructor Create(AImage: TJclPeImage);
property Items[Index: Integer]: TJclPeCertificate read GetItems; default;
end;
// Common Language Runtime section related classes
TJclPeCLRHeader = class(TObject)
private
FHeader: TImageCor20Header;
FImage: TJclPeImage;
function GetVersionString: string;
function GetHasMetadata: Boolean;
protected
procedure ReadHeader;
public
constructor Create(AImage: TJclPeImage);
property HasMetadata: Boolean read GetHasMetadata;
property Header: TImageCor20Header read FHeader;
property VersionString: string read GetVersionString;
property Image: TJclPeImage read FImage;
end;
// PE Image
TJclPeHeader = (
JclPeHeader_Signature,
JclPeHeader_Machine,
JclPeHeader_NumberOfSections,
JclPeHeader_TimeDateStamp,
JclPeHeader_PointerToSymbolTable,
JclPeHeader_NumberOfSymbols,
JclPeHeader_SizeOfOptionalHeader,
JclPeHeader_Characteristics,
JclPeHeader_Magic,
JclPeHeader_LinkerVersion,
JclPeHeader_SizeOfCode,
JclPeHeader_SizeOfInitializedData,
JclPeHeader_SizeOfUninitializedData,
JclPeHeader_AddressOfEntryPoint,
JclPeHeader_BaseOfCode,
JclPeHeader_BaseOfData,
JclPeHeader_ImageBase,
JclPeHeader_SectionAlignment,
JclPeHeader_FileAlignment,
JclPeHeader_OperatingSystemVersion,
JclPeHeader_ImageVersion,
JclPeHeader_SubsystemVersion,
JclPeHeader_Win32VersionValue,
JclPeHeader_SizeOfImage,
JclPeHeader_SizeOfHeaders,
JclPeHeader_CheckSum,
JclPeHeader_Subsystem,
JclPeHeader_DllCharacteristics,
JclPeHeader_SizeOfStackReserve,
JclPeHeader_SizeOfStackCommit,
JclPeHeader_SizeOfHeapReserve,
JclPeHeader_SizeOfHeapCommit,
JclPeHeader_LoaderFlags,
JclPeHeader_NumberOfRvaAndSizes);
TJclLoadConfig = (
JclLoadConfig_Characteristics, { TODO : rename to Size? }
JclLoadConfig_TimeDateStamp,
JclLoadConfig_Version,
JclLoadConfig_GlobalFlagsClear,
JclLoadConfig_GlobalFlagsSet,
JclLoadConfig_CriticalSectionDefaultTimeout,
JclLoadConfig_DeCommitFreeBlockThreshold,
JclLoadConfig_DeCommitTotalFreeThreshold,
JclLoadConfig_LockPrefixTable,
JclLoadConfig_MaximumAllocationSize,
JclLoadConfig_VirtualMemoryThreshold,
JclLoadConfig_ProcessHeapFlags,
JclLoadConfig_ProcessAffinityMask,
JclLoadConfig_CSDVersion,
JclLoadConfig_Reserved1,
JclLoadConfig_EditList,
JclLoadConfig_Reserved { TODO : extend to the new fields? }
);
TJclPeFileProperties = record
Size: DWORD;
CreationTime: TDateTime;
LastAccessTime: TDateTime;
LastWriteTime: TDateTime;
Attributes: Integer;
end;
TJclPeImageStatus = (stNotLoaded, stOk, stNotPE, stNotSupported, stNotFound, stError);
TJclPeTarget = (taUnknown, taWin32, taWin64);
TJclPeImage = class(TObject)
private
FAttachedImage: Boolean;
FCertificateList: TJclPeCertificateList;
FCLRHeader: TJclPeCLRHeader;
FDebugList: TJclPeDebugList;
FFileName: TFileName;
FImageSections: TStringList;
FLoadedImage: TLoadedImage;
FExportList: TJclPeExportFuncList;
FImportList: TJclPeImportList;
FNoExceptions: Boolean;
FReadOnlyAccess: Boolean;
FRelocationList: TJclPeRelocList;
FResourceList: TJclPeRootResourceList;
FResourceVA: TJclAddr;
FStatus: TJclPeImageStatus;
FTarget: TJclPeTarget;
FVersionInfo: TJclFileVersionInfo;
FStringTable: TStringList;
function GetCertificateList: TJclPeCertificateList;
function GetCLRHeader: TJclPeCLRHeader;
function GetDebugList: TJclPeDebugList;
function GetDescription: string;
function GetDirectories(Directory: Word): TImageDataDirectory;
function GetDirectoryExists(Directory: Word): Boolean;
function GetExportList: TJclPeExportFuncList;
function GetFileProperties: TJclPeFileProperties;
function GetImageSectionCount: Integer;
function GetImageSectionHeaders(Index: Integer): TImageSectionHeader;
function GetImageSectionNames(Index: Integer): string;
function GetImageSectionNameFromRva(const Rva: DWORD): string;
function GetImportList: TJclPeImportList;
function GetHeaderValues(Index: TJclPeHeader): string;
function GetLoadConfigValues(Index: TJclLoadConfig): string;
function GetMappedAddress: TJclAddr;
function GetOptionalHeader32: TImageOptionalHeader32;
function GetOptionalHeader64: TImageOptionalHeader64;
function GetRelocationList: TJclPeRelocList;
function GetResourceList: TJclPeRootResourceList;
function GetUnusedHeaderBytes: TImageDataDirectory;
function GetVersionInfo: TJclFileVersionInfo;
function GetVersionInfoAvailable: Boolean;
procedure ReadImageSections;
procedure ReadStringTable;
procedure SetFileName(const Value: TFileName);
function GetStringTableCount: Integer;
function GetStringTableItem(Index: Integer): string;
function GetImageSectionFullNames(Index: Integer): string;
protected
procedure AfterOpen; dynamic;
procedure CheckNotAttached;
procedure Clear; dynamic;
function ExpandModuleName(const ModuleName: string): TFileName;
procedure RaiseStatusException;
function ResourceItemCreate(AEntry: PImageResourceDirectoryEntry;
AParentItem: TJclPeResourceItem): TJclPeResourceItem; virtual;
function ResourceListCreate(ADirectory: PImageResourceDirectory;
AParentItem: TJclPeResourceItem): TJclPeResourceList; virtual;
property NoExceptions: Boolean read FNoExceptions;
public
constructor Create(ANoExceptions: Boolean = False); virtual;
destructor Destroy; override;
procedure AttachLoadedModule(const Handle: HMODULE);
function CalculateCheckSum: DWORD;
function DirectoryEntryToData(Directory: Word): Pointer;
function GetSectionHeader(const SectionName: string; out Header: PImageSectionHeader): Boolean;
function GetSectionName(Header: PImageSectionHeader): string;
function GetNameInStringTable(Offset: ULONG): string;
function IsBrokenFormat: Boolean;
function IsCLR: Boolean;
function IsSystemImage: Boolean;
// RVA are always DWORD
function RawToVa(Raw: DWORD): Pointer; overload;
function RvaToSection(Rva: DWORD): PImageSectionHeader; overload;
function RvaToVa(Rva: DWORD): Pointer; overload;
function RvaToVaEx(Rva: DWORD): Pointer; overload;
function StatusOK: Boolean;
procedure TryGetNamesForOrdinalImports;
function VerifyCheckSum: Boolean;
class function DebugTypeNames(DebugType: DWORD): string;
class function DirectoryNames(Directory: Word): string;
class function ExpandBySearchPath(const ModuleName, BasePath: string): TFileName;
class function HeaderNames(Index: TJclPeHeader): string;
class function LoadConfigNames(Index: TJclLoadConfig): string;
class function ShortSectionInfo(Characteristics: DWORD): string;
class function DateTimeToStamp(const DateTime: TDateTime): DWORD;
class function StampToDateTime(TimeDateStamp: DWORD): TDateTime;
property AttachedImage: Boolean read FAttachedImage;
property CertificateList: TJclPeCertificateList read GetCertificateList;
property CLRHeader: TJclPeCLRHeader read GetCLRHeader;
property DebugList: TJclPeDebugList read GetDebugList;
property Description: string read GetDescription;
property Directories[Directory: Word]: TImageDataDirectory read GetDirectories;
property DirectoryExists[Directory: Word]: Boolean read GetDirectoryExists;
property ExportList: TJclPeExportFuncList read GetExportList;
property FileName: TFileName read FFileName write SetFileName;
property FileProperties: TJclPeFileProperties read GetFileProperties;
property HeaderValues[Index: TJclPeHeader]: string read GetHeaderValues;
property ImageSectionCount: Integer read GetImageSectionCount;
property ImageSectionHeaders[Index: Integer]: TImageSectionHeader read GetImageSectionHeaders;
property ImageSectionNames[Index: Integer]: string read GetImageSectionNames;
property ImageSectionFullNames[Index: Integer]: string read GetImageSectionFullNames;
property ImageSectionNameFromRva[const Rva: DWORD]: string read GetImageSectionNameFromRva;
property ImportList: TJclPeImportList read GetImportList;
property LoadConfigValues[Index: TJclLoadConfig]: string read GetLoadConfigValues;
property LoadedImage: TLoadedImage read FLoadedImage;
property MappedAddress: TJclAddr read GetMappedAddress;
property StringTableCount: Integer read GetStringTableCount;
property StringTable[Index: Integer]: string read GetStringTableItem;
// use the following properties
// property OptionalHeader: TImageOptionalHeader
property OptionalHeader32: TImageOptionalHeader32 read GetOptionalHeader32;
property OptionalHeader64: TImageOptionalHeader64 read GetOptionalHeader64;
property ReadOnlyAccess: Boolean read FReadOnlyAccess write FReadOnlyAccess;
property RelocationList: TJclPeRelocList read GetRelocationList;
property ResourceVA: TJclAddr read FResourceVA;
property ResourceList: TJclPeRootResourceList read GetResourceList;
property Status: TJclPeImageStatus read FStatus;
property Target: TJclPeTarget read FTarget;
property UnusedHeaderBytes: TImageDataDirectory read GetUnusedHeaderBytes;
property VersionInfo: TJclFileVersionInfo read GetVersionInfo;
property VersionInfoAvailable: Boolean read GetVersionInfoAvailable;
end;
{$IFDEF BORLAND}
TJclPeBorImage = class;
TJclPeBorImagesCache = class(TJclPeImagesCache)
private
function GetImages(const FileName: TFileName): TJclPeBorImage;
protected
function GetPeImageClass: TJclPeImageClass; override;
public
property Images[const FileName: TFileName]: TJclPeBorImage read GetImages; default;
end;
// Borland Delphi PE Image specific information
TJclPePackageInfo = class(TObject)
private
FAvailable: Boolean;
FContains: TStringList;
FDcpName: string;
FRequires: TStringList;
FFlags: Integer;
FDescription: string;
FEnsureExtension: Boolean;
FSorted: Boolean;
function GetContains: TStrings;
function GetContainsCount: Integer;
function GetContainsFlags(Index: Integer): Byte;
function GetContainsNames(Index: Integer): string;
function GetRequires: TStrings;
function GetRequiresCount: Integer;
function GetRequiresNames(Index: Integer): string;
protected
procedure ReadPackageInfo(ALibHandle: THandle);
procedure SetDcpName(const Value: string);
public
constructor Create(ALibHandle: THandle);
destructor Destroy; override;
class function PackageModuleTypeToString(Flags: Cardinal): string;
class function PackageOptionsToString(Flags: Cardinal): string;
class function ProducerToString(Flags: Cardinal): string;
class function UnitInfoFlagsToString(UnitFlags: Byte): string;
property Available: Boolean read FAvailable;
property Contains: TStrings read GetContains;
property ContainsCount: Integer read GetContainsCount;
property ContainsNames[Index: Integer]: string read GetContainsNames;
property ContainsFlags[Index: Integer]: Byte read GetContainsFlags;
property Description: string read FDescription;
property DcpName: string read FDcpName;
property EnsureExtension: Boolean read FEnsureExtension write FEnsureExtension;
property Flags: Integer read FFlags;
property Requires: TStrings read GetRequires;
property RequiresCount: Integer read GetRequiresCount;
property RequiresNames[Index: Integer]: string read GetRequiresNames;
property Sorted: Boolean read FSorted write FSorted;
end;
TJclPeBorForm = class(TObject)
private
FFormFlags: TFilerFlags;
FFormClassName: string;
FFormObjectName: string;
FFormPosition: Integer;
FResItem: TJclPeResourceItem;
function GetDisplayName: string;
public
constructor Create(AResItem: TJclPeResourceItem; AFormFlags: TFilerFlags;
AFormPosition: Integer; const AFormClassName, AFormObjectName: string);
procedure ConvertFormToText(const Stream: TStream); overload;
procedure ConvertFormToText(const Strings: TStrings); overload;
property FormClassName: string read FFormClassName;
property FormFlags: TFilerFlags read FFormFlags;
property FormObjectName: string read FFormObjectName;
property FormPosition: Integer read FFormPosition;
property DisplayName: string read GetDisplayName;
property ResItem: TJclPeResourceItem read FResItem;
end;
TJclPeBorImage = class(TJclPeImage)
private
FForms: TObjectList;
FIsPackage: Boolean;
FIsBorlandImage: Boolean;
FLibHandle: THandle;
FPackageInfo: TJclPePackageInfo;
FPackageInfoSorted: Boolean;
FPackageCompilerVersion: Integer;
function GetFormCount: Integer;
function GetForms(Index: Integer): TJclPeBorForm;
function GetFormFromName(const FormClassName: string): TJclPeBorForm;
function GetLibHandle: THandle;
function GetPackageCompilerVersion: Integer;
function GetPackageInfo: TJclPePackageInfo;
protected
procedure AfterOpen; override;
procedure Clear; override;
procedure CreateFormsList;
public
constructor Create(ANoExceptions: Boolean = False); override;
destructor Destroy; override;
function DependedPackages(List: TStrings; FullPathName, Descriptions: Boolean): Boolean;
function FreeLibHandle: Boolean;
property Forms[Index: Integer]: TJclPeBorForm read GetForms;
property FormCount: Integer read GetFormCount;
property FormFromName[const FormClassName: string]: TJclPeBorForm read GetFormFromName;
property IsBorlandImage: Boolean read FIsBorlandImage;
property IsPackage: Boolean read FIsPackage;
property LibHandle: THandle read GetLibHandle;
property PackageCompilerVersion: Integer read GetPackageCompilerVersion;
property PackageInfo: TJclPePackageInfo read GetPackageInfo;
property PackageInfoSorted: Boolean read FPackageInfoSorted write FPackageInfoSorted;
end;
{$ENDIF BORLAND}
// Threaded function search
TJclPeNameSearchOption = (seImports, seDelayImports, seBoundImports, seExports);
TJclPeNameSearchOptions = set of TJclPeNameSearchOption;
TJclPeNameSearchNotifyEvent = procedure (Sender: TObject; PeImage: TJclPeImage;
var Process: Boolean) of object;
TJclPeNameSearchFoundEvent = procedure (Sender: TObject; const FileName: TFileName;
const FunctionName: string; Option: TJclPeNameSearchOption) of object;
TJclPeNameSearch = class(TThread)
private
F_FileName: TFileName;
F_FunctionName: string;
F_Option: TJclPeNameSearchOption;
F_Process: Boolean;
FFunctionName: string;
FOptions: TJclPeNameSearchOptions;
FPath: string;
FPeImage: TJclPeImage;
FOnFound: TJclPeNameSearchFoundEvent;
FOnProcessFile: TJclPeNameSearchNotifyEvent;
protected
function CompareName(const FunctionName, ComparedName: string): Boolean; virtual;
procedure DoFound;
procedure DoProcessFile;
procedure Execute; override;
public
constructor Create(const FunctionName, Path: string; Options: TJclPeNameSearchOptions = [seImports, seExports]);
procedure Start;
property OnFound: TJclPeNameSearchFoundEvent read FOnFound write FOnFound;
property OnProcessFile: TJclPeNameSearchNotifyEvent read FOnProcessFile write FOnProcessFile;
end;
// PE Image miscellaneous functions
type
TJclRebaseImageInfo32 = record
OldImageSize: DWORD;
OldImageBase: TJclAddr32;
NewImageSize: DWORD;
NewImageBase: TJclAddr32;
end;
TJclRebaseImageInfo64 = record
OldImageSize: DWORD;
OldImageBase: TJclAddr64;
NewImageSize: DWORD;
NewImageBase: TJclAddr64;
end;
// renamed
// TJclRebaseImageInfo = TJclRebaseImageInfo32;
{ Image validity }
function IsValidPeFile(const FileName: TFileName): Boolean;
// use PeGetNtHeaders32 for backward compatibility
// function PeGetNtHeaders(const FileName: TFileName; out NtHeaders: TImageNtHeaders): Boolean;
function PeGetNtHeaders32(const FileName: TFileName; out NtHeaders: TImageNtHeaders32): Boolean;
function PeGetNtHeaders64(const FileName: TFileName; out NtHeaders: TImageNtHeaders64): Boolean;
{ Image modifications }
function PeCreateNameHintTable(const FileName: TFileName): Boolean;
// use PeRebaseImage32
//function PeRebaseImage(const ImageName: TFileName; NewBase: DWORD = 0; TimeStamp: DWORD = 0;
// MaxNewSize: DWORD = 0): TJclRebaseImageInfo;
function PeRebaseImage32(const ImageName: TFileName; NewBase: TJclAddr32 = 0; TimeStamp: DWORD = 0;
MaxNewSize: DWORD = 0): TJclRebaseImageInfo32;
function PeRebaseImage64(const ImageName: TFileName; NewBase: TJclAddr64 = 0; TimeStamp: DWORD = 0;
MaxNewSize: DWORD = 0): TJclRebaseImageInfo64;
function PeUpdateLinkerTimeStamp(const FileName: TFileName; const Time: TDateTime): Boolean;
function PeReadLinkerTimeStamp(const FileName: TFileName): TDateTime;
function PeInsertSection(const FileName: TFileName; SectionStream: TStream; SectionName: string): Boolean;
{ Image Checksum }
function PeVerifyCheckSum(const FileName: TFileName): Boolean;
function PeClearCheckSum(const FileName: TFileName): Boolean;
function PeUpdateCheckSum(const FileName: TFileName): Boolean;
// Various simple PE Image searching and listing routines
{ Exports searching }
function PeDoesExportFunction(const FileName: TFileName; const FunctionName: string;
Options: TJclSmartCompOptions = []): Boolean;
function PeIsExportFunctionForwardedEx(const FileName: TFileName; const FunctionName: string;
out ForwardedName: string; Options: TJclSmartCompOptions = []): Boolean;
function PeIsExportFunctionForwarded(const FileName: TFileName; const FunctionName: string;
Options: TJclSmartCompOptions = []): Boolean;
{ Imports searching }
function PeDoesImportFunction(const FileName: TFileName; const FunctionName: string;
const LibraryName: string = ''; Options: TJclSmartCompOptions = []): Boolean;
function PeDoesImportLibrary(const FileName: TFileName; const LibraryName: string;
Recursive: Boolean = False): Boolean;
{ Imports listing }
function PeImportedLibraries(const FileName: TFileName; const LibrariesList: TStrings;
Recursive: Boolean = False; FullPathName: Boolean = False): Boolean;
function PeImportedFunctions(const FileName: TFileName; const FunctionsList: TStrings;
const LibraryName: string = ''; IncludeLibNames: Boolean = False): Boolean;
{ Exports listing }
function PeExportedFunctions(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
function PeExportedNames(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
function PeExportedVariables(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
{ Resources listing }
function PeResourceKindNames(const FileName: TFileName; ResourceType: TJclPeResourceKind;
const NamesList: TStrings): Boolean;
{ Borland packages specific }
{$IFDEF BORLAND}
function PeBorFormNames(const FileName: TFileName; const NamesList: TStrings): Boolean;
function PeBorDependedPackages(const FileName: TFileName; PackagesList: TStrings;
FullPathName, Descriptions: Boolean): Boolean;
{$ENDIF BORLAND}
// Missing imports checking routines
function PeFindMissingImports(const FileName: TFileName; MissingImportsList: TStrings): Boolean; overload;
function PeFindMissingImports(RequiredImportsList, MissingImportsList: TStrings): Boolean; overload;
function PeCreateRequiredImportList(const FileName: TFileName; RequiredImportsList: TStrings): Boolean;
// Mapped or loaded image related routines
// use PeMapImgNtHeaders32
// function PeMapImgNtHeaders(const BaseAddress: Pointer): PImageNtHeaders;
function PeMapImgNtHeaders32(const BaseAddress: Pointer): PImageNtHeaders32; overload;
function PeMapImgNtHeaders32(Stream: TStream; const BasePosition: Int64; out NtHeaders32: TImageNtHeaders32): Int64; overload;
function PeMapImgNtHeaders64(const BaseAddress: Pointer): PImageNtHeaders64; overload;
function PeMapImgNtHeaders64(Stream: TStream; const BasePosition: Int64; out NtHeaders64: TImageNtHeaders64): Int64; overload;
function PeMapImgLibraryName(const BaseAddress: Pointer): string;
function PeMapImgLibraryName32(const BaseAddress: Pointer): string;
function PeMapImgLibraryName64(const BaseAddress: Pointer): string;
function PeMapImgSize(const BaseAddress: Pointer): DWORD; overload;
function PeMapImgSize(Stream: TStream; const BasePosition: Int64): DWORD; overload;
function PeMapImgSize32(const BaseAddress: Pointer): DWORD; overload;
function PeMapImgSize32(Stream: TStream; const BasePosition: Int64): DWORD; overload;
function PeMapImgSize64(const BaseAddress: Pointer): DWORD; overload;
function PeMapImgSize64(Stream: TStream; const BasePosition: Int64): DWORD; overload;
function PeMapImgTarget(const BaseAddress: Pointer): TJclPeTarget; overload;
function PeMapImgTarget(Stream: TStream; const BasePosition: Int64): TJclPeTarget; overload;
type
TImageSectionHeaderArray = array of TImageSectionHeader;
// use PeMapImgSections32
// function PeMapImgSections(NtHeaders: PImageNtHeaders): PImageSectionHeader;
function PeMapImgSections32(NtHeaders: PImageNtHeaders32): PImageSectionHeader; overload;
function PeMapImgSections32(Stream: TStream; const NtHeaders32Position: Int64; const NtHeaders32: TImageNtHeaders32;
out ImageSectionHeaders: TImageSectionHeaderArray): Int64; overload;
function PeMapImgSections64(NtHeaders: PImageNtHeaders64): PImageSectionHeader; overload;
function PeMapImgSections64(Stream: TStream; const NtHeaders64Position: Int64; const NtHeaders64: TImageNtHeaders64;
out ImageSectionHeaders: TImageSectionHeaderArray): Int64; overload;
// use PeMapImgFindSection32
// function PeMapImgFindSection(NtHeaders: PImageNtHeaders;
// const SectionName: string): PImageSectionHeader;
function PeMapImgFindSection32(NtHeaders: PImageNtHeaders32;
const SectionName: string): PImageSectionHeader;
function PeMapImgFindSection64(NtHeaders: PImageNtHeaders64;
const SectionName: string): PImageSectionHeader;
function PeMapImgFindSection(const ImageSectionHeaders: TImageSectionHeaderArray;
const SectionName: string): SizeInt;
function PeMapImgFindSectionFromModule(const BaseAddress: Pointer;
const SectionName: string): PImageSectionHeader;
function PeMapImgExportedVariables(const Module: HMODULE; const VariablesList: TStrings): Boolean;