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