@@ -40,7 +40,7 @@ function TPEImportParser.Parse: TParserResult;
4040 TImpDirs = TList<TImportDirectoryTable>;
4141 TILTs = TList<TImportLookupTable>;
4242var
43- ddir : TImageDataDirectory;
43+ dir : TImageDataDirectory;
4444 bIs32: boolean;
4545 dq: uint64;
4646 sizet: byte;
@@ -54,7 +54,9 @@ function TPEImportParser.Parse: TParserResult;
5454 Lib: TPEImportLibrary;
5555 PE: TPEImage;
5656 LibraryName: string;
57- FunctionAlreadyExists: boolean;
57+ dwLeft: uint32;
58+ bEmptyLastDirFound: boolean;
59+ IDirNumber: integer;
5860begin
5961 PE := TPEImage(FPE);
6062
@@ -68,59 +70,76 @@ function TPEImportParser.Parse: TParserResult;
6870 sizet := PE.ImageBits div 8 ;
6971
7072 // If no imports, it's ok.
71- if not PE.DataDirectories.Get(DDIR_IMPORT, @ddir ) then
73+ if not PE.DataDirectories.Get(DDIR_IMPORT, @dir ) then
7274 exit(PR_OK);
73- if ddir .IsEmpty then
75+ if dir .IsEmpty then
7476 exit(PR_OK);
7577
7678 // Seek import dir.
77- if not PE.SeekRVA(ddir .VirtualAddress) then
79+ if not PE.SeekRVA(dir .VirtualAddress) then
7880 exit;
7981
8082 // Read import descriptors.
81- while true do
83+ dwLeft := dir.Size;
84+ bEmptyLastDirFound := False;
85+ while dwLeft >= sizeof(IDir) do
8286 begin
8387 // Read IDir.
8488 if not PE.ReadEx(@IDir, sizeof(IDir)) then
8589 exit;
90+
8691 if IDir.IsEmpty then // it's last dir
92+ begin
93+ bEmptyLastDirFound := true;
8794 break;
95+ end ;
96+
97+ // Check RVA.
98+ if not (PE.RVAExists(IDir.NameRVA)) then
99+ begin
100+ PE.Msg.Write(SCategoryImports, ' Bad RVAs in directory. Imports are incorrect.' );
101+ exit;
102+ end ;
103+
88104 IDirs.Add(IDir); // add read dir
105+
106+ dec(dwLeft, sizeof(IDir));
107+ end ;
108+
109+ if IDirs.Count = 0 then
110+ begin
111+ PE.Msg.Write(SCategoryImports, ' No directories found.' );
112+ exit;
113+ end ;
114+
115+ if not bEmptyLastDirFound then
116+ begin
117+ PE.Msg.Write(SCategoryImports, ' No last (empty) directory found.' );
89118 end ;
90119
91120 // Parse import descriptors.
121+ IDirNumber := -1 ;
92122 for IDir in IDirs do
93123 begin
124+ inc(IDirNumber);
125+
94126 ILTs.Clear;
95127
96128 // Read library name.
97129 if (not PE.SeekRVA(IDir.NameRVA)) then
98130 begin
99- PE.Msg.Write(' Import library name RVA not found (0x%x).' , [IDir.NameRVA]);
131+ PE.Msg.Write(SCategoryImports, ' Library name RVA not found (0x%x) for dir # %d .' , [IDir.NameRVA, IDirNumber ]);
100132 Continue;
101133 end ;
102134
103135 LibraryName := PE.ReadAnsiString;
104136
105137 if LibraryName.IsEmpty then
106138 begin
107- PE.Msg.Write(' Import library has NULL name.' );
139+ PE.Msg.Write(SCategoryImports, ' Library # %d has empty name.' , [IDirNumber] );
108140 Continue;
109141 end ;
110142
111- {
112- // Try to find existing library. If there are few libraries with same
113- // name, the libs are merged.
114- Lib := PE.Imports.FindLib(LibraryName);
115- // if not found, create new.
116- if Lib = nil then
117- begin
118- Lib := TPEImportLibrary.Create(LibraryName, IDir.IsBound);
119- PE.Imports.Add(Lib);
120- end;
121- }
122- // Don't merge libraries any more.
123- // It should be implemented as optional optimization pass.
124143 Lib := TPEImportLibrary.Create(LibraryName, IDir.IsBound);
125144 PE.Imports.Add(Lib);
126145
@@ -129,14 +148,14 @@ function TPEImportParser.Parse: TParserResult;
129148 // Skip bad dll name.
130149 if Lib.Name .IsEmpty then
131150 begin
132- PE.Msg.Write(' Bad import library name. ' );
151+ PE.Msg.Write(SCategoryImports, ' Bad library name (# %d) ' , [IDirNumber] );
133152 Continue;
134153 end ;
135154
136155 PATCHRVA := IDir.FirstThunk;
137156 if PATCHRVA = 0 then
138157 begin
139- PE.Msg.Write(' Import library %s has NULL patch RVA.' , [Lib.Name ]);
158+ PE.Msg.Write(SCategoryImports, ' Library # %d (%s) has NULL patch RVA.' , [IDirNumber, Lib.Name ]);
140159 break;
141160 end ;
142161
@@ -147,42 +166,37 @@ function TPEImportParser.Parse: TParserResult;
147166
148167 if IATRVA = 0 then
149168 begin
150- PE.Msg.Write(' Import library %s has NULL IAT RVA.' , [Lib.Name ]);
169+ PE.Msg.Write(SCategoryImports, ' Library # %d (%s) has NULL IAT RVA.' , [IDirNumber, Lib.Name ]);
151170 break;
152171 end ;
153172
154173 Lib.IATRVA := IATRVA;
155174
156175 // Read IAT elements.
157- while PE.SeekRVA(IATRVA) and ReadGoodILTItem(TPEImage(FPE) , dq) do
176+ while PE.SeekRVA(IATRVA) and ReadGoodILTItem(PE , dq) do
158177 begin
159- FunctionAlreadyExists := False; // Assigned(Lib.Functions.FindByRVA(PATCHRVA));
160-
161178 // Process only unique functions (by RVA).
162- if not FunctionAlreadyExists then
179+ ILT.Create(dq, bIs32);
180+
181+ ImpFn := TPEImportFunction.CreateEmpty;
182+
183+ // By ordinal.
184+ if ILT.IsImportByOrdinal then
163185 begin
164- ILT.Create(dq, bIs32);
165-
166- ImpFn := TPEImportFunction.CreateEmpty;
167-
168- // By ordinal.
169- if ILT.IsImportByOrdinal then
170- begin
171- ImpFn.Ordinal := ILT.OrdinalNumber;
172- ImpFn.Name := ' ' ;
173- end
174-
175- // By name.
176- else if PE.SeekRVA(ILT.HintNameTableRVA) then
177- begin
178- dq := 0 ;
179- PE.ReadEx(@dq, 2 );
180- ImpFn.Name := PE.ReadAnsiString;
181- end ;
182-
183- Lib.Functions.Add(ImpFn);
186+ ImpFn.Ordinal := ILT.OrdinalNumber;
187+ ImpFn.Name := ' ' ;
188+ end
189+
190+ // By name.
191+ else if PE.SeekRVA(ILT.HintNameTableRVA) then
192+ begin
193+ dq := 0 ;
194+ PE.ReadEx(@dq, 2 );
195+ ImpFn.Name := PE.ReadAnsiString;
184196 end ;
185197
198+ Lib.Functions.Add(ImpFn);
199+
186200 inc(IATRVA, sizet); // next item
187201 inc(PATCHRVA, sizet);
188202 end ;
0 commit comments