Skip to content

Commit 973c93a

Browse files
author
vdisasmdev
committed
* Update import parsing to handle more malformed imports.
* Some imports cleanup.
1 parent 0bc52ad commit 973c93a

File tree

2 files changed

+63
-48
lines changed

2 files changed

+63
-48
lines changed

PE.Common.pas

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ interface
124124
SCategorySections = 'Sections';
125125
SCategoryDataDirecory = 'Data Directories';
126126
SCategoryResources = 'Resources';
127+
SCategoryImports = 'Imports';
127128

128129
implementation
129130

PE.Parser.Import.pas

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function TPEImportParser.Parse: TParserResult;
4040
TImpDirs = TList<TImportDirectoryTable>;
4141
TILTs = TList<TImportLookupTable>;
4242
var
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;
5860
begin
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

Comments
 (0)