@@ -182,38 +182,47 @@ def resolve_forwarded_exports(self):
182182 target_dll = forwarded_export .target_dll
183183 target_symbol = forwarded_export .target_symbol
184184
185+ if not source_symbol :
186+ # Some DLLs (shlwapi.dll) have a bunch of forwarded
187+ # exports with ordinals but no symbols.
188+ # These are really annoying to deal with, but they are
189+ # used extremely rarely, so we will ignore them.
190+ continue
191+
185192 target_iat = self .import_address_table .get (target_dll )
186193
187- if target_iat :
188- # If we have an existing entry in the process IAT for the code
189- # this entry forwards to, then we will point the symbol there
190- # rather than the symbol string in the exporter's data section.
191- forward_ea = target_iat .get (target_symbol )
192-
193- if forward_ea :
194- self .import_address_table [source_dll ][source_symbol ] = forward_ea
195- self .import_address_table [source_dll ][source_ordinal ] = forward_ea
196-
197- # Register the new address as having the source symbol/ordinal.
198- # This way, hooks on forward source symbols will function
199- # correctly.
200-
201- self .import_symbols [forward_ea ] = {
202- 'name' : source_symbol ,
203- 'ordinal' : source_ordinal ,
204- 'dll' : source_dll .split ('.' )[0 ]
205- }
206-
207- # TODO: With the above code, hooks on functions which are
208- # forward targets may not work correctly.
209- # The most correct way to resolve this would be to add
210- # support for addresses to be associated with multiple symbols.
211-
212- self .ql .log .debug (f"Forwarding symbol { source_dll } .{ source_symbol } to { target_dll } .{ target_symbol } : Resolved symbol to ({ forward_ea :#x} )" )
213- else :
214- self .ql .log .warning (f"Forwarding symbol { source_dll } .{ source_symbol } to { target_dll } .{ target_symbol } : Failed to resolve address" )
215- else :
216- pass # If IAT was not found, it is probably a virtual library.
194+ if not target_iat :
195+ # If IAT was not found, it is probably a virtual library.
196+ continue
197+
198+ # If we have an existing entry in the process IAT for the code
199+ # this entry forwards to, then we will point the symbol there
200+ # rather than the symbol string in the exporter's data section.
201+ forward_ea = target_iat .get (target_symbol )
202+
203+ if not forward_ea :
204+ self .ql .log .warning (f"Forwarding symbol { source_dll } .{ source_symbol } to { target_dll } .{ target_symbol } : Failed to resolve address" )
205+ continue
206+
207+ self .import_address_table [source_dll ][source_symbol ] = forward_ea
208+ self .import_address_table [source_dll ][source_ordinal ] = forward_ea
209+
210+ # Register the new address as having the source symbol/ordinal.
211+ # This way, hooks on forward source symbols will function
212+ # correctly.
213+
214+ self .import_symbols [forward_ea ] = {
215+ 'name' : source_symbol ,
216+ 'ordinal' : source_ordinal ,
217+ 'dll' : source_dll .split ('.' )[0 ]
218+ }
219+
220+ # TODO: With the above code, hooks on functions which are
221+ # forward targets may not work correctly.
222+ # The most correct way to resolve this would be to add
223+ # support for addresses to be associated with multiple symbols.
224+
225+ self .ql .log .debug (f"Forwarding symbol { source_dll } .{ source_symbol } to { target_dll } .{ target_symbol } : Resolved symbol to ({ forward_ea :#x} )" )
217226
218227 def load_dll (self , name : str , is_driver : bool = False ) -> int :
219228 dll_path , dll_name = self .__get_path_elements (name )
0 commit comments