7 #define EXECUTABLES "*.exe;*.dll;*.sys;*.pyd"
9 int SearchImport(char *ImportDLL
, char *ImportFunction
, char *SourcePath
);
10 int SearchExport(char *ExportFunction
, char *SourcePath
);
11 int SearchImportWithImageHlp(char *InputPath
, char *ImportDLL
, char *ImportFunction
);
12 int SearchExportWithImageHlp(char *InputPath
, char *ExportFunction
);
14 void Usage(char *ProgramName
)
16 printf("Usage: %s test.dll c:\\dir\\test.exe\n", ProgramName
);
17 printf("\tReport if c:\\dir\\test.exe imports test.dll\n");
18 printf("\nExamples:\n");
19 printf("%s test.dll!funcname c:\\dir\\test.exe\n", ProgramName
);
20 printf("\tReport if c:\\dir\\test.exe imports test.dll!funcname\n");
21 printf("%s test.dll c:\\dir\n", ProgramName
);
22 printf("\tFind executables importing test.dll in c:\\dir\n");
23 printf("%s test.dll!funcname c:\\dir\n", ProgramName
);
24 printf("\tFind executables importing funcname from test.dll in c:\\dir\n");
25 printf("%s test!funcname c:\\dir\n", ProgramName
);
26 printf("\tFind executables importing funcname from test.dll in c:\\dir\n");
27 printf("%s test!ord_1234 c:\\dir\n", ProgramName
);
28 printf("\tFind executables importing ordinal 1234 (in decimal) from test.dll in c:\\dir\n");
29 printf("\tNOTE: this only works if there is no name associated with the function\n");
30 printf("%s -e funcname c:\\dir\n", ProgramName
);
31 printf("\tFind all DLLs exporting funcname in c:\\dir\n");
34 // Try to match Target against Source
35 BOOL
CompareFilenames(char *Target
, char *Source
)
38 BOOL HasExtension
= FALSE
;
40 if (!Target
|| !Source
|| !Target
[0] || !Source
[0]) return FALSE
;
41 if (strchr(Source
, '.')) HasExtension
= TRUE
;
43 // If we don't need to consider that the source may lack an extension,
44 // then the lengths must be the same
45 if (HasExtension
&& strlen(Target
) != strlen(Source
)) return FALSE
;
47 for (i
= 0; i
< strlen(Source
); i
++)
49 if (tolower(Target
[i
]) != tolower(Source
[i
])) return FALSE
;
55 if (Target
[i
]) return FALSE
;
60 if (Target
[i
] == '.') return TRUE
;
65 int main(int argc
, char* argv
[])
75 if (argv
[1][0] == '-')
78 if (tolower(argv
[1][1]) != 'e')
80 fprintf(stderr
, "Error: -e is the only valid option\n");
85 if (argc
!= 3 && argc
!= 4)
87 fprintf(stderr
, "Error: incorrect number of parameters for export searching\n");
92 if (strchr(argv
[2], '!'))
94 fprintf(stderr
, "Error: you cannot pass a dll!func format with -e\n");
99 if (argc
== 4) return SearchExport(argv
[2], argv
[3]);
100 else return SearchExport(argv
[2], NULL
);
107 fprintf(stderr
, "Error: incorrect number of parameters for import searching\n");
112 if ((ImportFunction
= strchr(argv
[1], '!')) != NULL
)
114 *ImportFunction
++ = '\0';
115 return SearchImport(argv
[1], ImportFunction
, argv
[2]);
117 else return SearchImport(argv
[1], NULL
, argv
[2]);
123 int SearchImport(char *ImportDLL
, char *ImportFunction
, char *SourcePath
)
125 PDIRECTORY_INFO pDirectory
;
126 PSEARCH_RESULTS result
;
128 if (!(pDirectory
= DirectoryOpen(SourcePath
, TRUE
))) return -1;
129 if (!DirectorySearch(pDirectory
, EXECUTABLES
)) return -1;
131 for (result
= pDirectory
->pSearchResults
; result
; result
= result
->Next
)
133 SearchImportWithImageHlp(result
->FilePath
, ImportDLL
, ImportFunction
);
136 DirectoryClose(pDirectory
);
140 int SearchImportWithImageHlp(char *InputPath
, char *ImportDLL
, char *ImportFunction
)
144 char *Filename
, *ModuleName
;
146 // Used to read import table
148 IMAGE_DATA_DIRECTORY ImportDirectory
;
149 PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor
;
150 PIMAGE_THUNK_DATA pThunk
, pThunkIAT
;
151 PIMAGE_IMPORT_BY_NAME pOrdinalName
;
152 USHORT ImportOrdinal
= 0;
153 BOOL UseOrdinal
= FALSE
;
155 if (!(Filename
= strrchr(InputPath
, '\\')))
157 fprintf(stderr
, "Error: unexpected file \"%s\"\n", InputPath
);
162 //printf("Loading %s\n", Filename);
163 // TODO: under what circumstances does this fail?
164 if (!MapAndLoad(Filename
, InputPath
, &Image
, FALSE
, TRUE
))
166 fprintf(stderr
, "Unable to map and load %s\n", Filename
);
170 ImportDirectory
= Image
.FileHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
];
171 if (!ImportDirectory
.VirtualAddress
) return 0; // no imports
173 if (ImportDirectory
.Size
< sizeof(IMAGE_IMPORT_DESCRIPTOR
))
175 fprintf(stderr
, "Error loading %s: invalid import descriptor table (size < sizeof(IMAGE_IMPORT_DESCRIPTOR))\n", Filename
);
176 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
180 pImportDescriptor
= (PIMAGE_IMPORT_DESCRIPTOR
)GetAddressFromRVA(Image
, ImportDirectory
.VirtualAddress
);
181 if (!pImportDescriptor
)
183 fprintf(stderr
, "Error loading %s: invalid import descriptor table (invalid RVA)\n", Filename
);
184 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
188 for (i
= 0, ModuleFound
= FALSE
; i
< ImportDirectory
.Size
/ sizeof(IMAGE_IMPORT_DESCRIPTOR
); i
++)
190 ModuleName
= (char *)GetAddressFromRVA(Image
, pImportDescriptor
->Name
);
191 if (!ModuleName
|| !ModuleName
[0]) break;
193 if (CompareFilenames(ModuleName
, ImportDLL
))
203 if (!UnMapAndLoad(&Image
))
205 fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
213 printf("Match found: %s\\%s imports the library %s\n", InputPath
, Filename
, ImportDLL
);
214 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
218 if (strncmp(ImportFunction
, "ord_", 4) == 0)
220 ImportOrdinal
= atoi(ImportFunction
+ 4);
221 if (!ImportOrdinal
&& ImportFunction
[4] != '0')
223 fprintf(stderr
, "Error: you passed an invalid ordinal\n");
224 fprintf(stderr
, "Should be in the format ord_1234 where 1234 is a decimal number\n");
225 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
231 pThunkIAT
= (PIMAGE_THUNK_DATA
)GetAddressFromRVA(Image
, pImportDescriptor
->FirstThunk
);
232 if (!pImportDescriptor
->OriginalFirstThunk
) pThunk
= pThunkIAT
;
233 else pThunk
= (PIMAGE_THUNK_DATA
)GetAddressFromRVA(Image
, pImportDescriptor
->OriginalFirstThunk
);
234 if (!pThunk
|| !pThunkIAT
)
236 fprintf(stderr
, "Error loading %s: invalid import descriptor table (neither thunk is set)\n", Filename
);
237 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
241 for (; ; pThunk
++, pThunkIAT
++)
243 if (!pThunk
->u1
.AddressOfData
) break;
244 if (UseOrdinal
&& pThunk
->u1
.Ordinal
& IMAGE_ORDINAL_FLAG
)
246 if (ImportOrdinal
== IMAGE_ORDINAL(pThunk
->u1
.Ordinal
))
248 printf("Match found: %s\\%s imports ordinal %d from %s\n", InputPath
, Filename
, ImportOrdinal
, ImportDLL
);
249 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
255 pOrdinalName
= (PIMAGE_IMPORT_BY_NAME
)GetAddressFromRVA(Image
, (DWORD
)pThunk
->u1
.AddressOfData
);
256 if (!pOrdinalName
) continue;
258 if (_stricmp(pOrdinalName
->Name
, ImportFunction
) == 0)
260 printf("Match found: %s\\%s imports %s!%s\n", InputPath
, Filename
, ImportDLL
, pOrdinalName
->Name
);
261 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
267 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
271 int SearchExport(char *ExportFunction
, char *SourcePath
)
273 PDIRECTORY_INFO pDirectory
;
274 PSEARCH_RESULTS result
;
276 if (!(pDirectory
= DirectoryOpen(SourcePath
, TRUE
))) return -1;
277 if (!DirectorySearch(pDirectory
, EXECUTABLES
)) return -1;
279 for (result
= pDirectory
->pSearchResults
; result
; result
= result
->Next
)
281 SearchExportWithImageHlp(result
->FilePath
, ExportFunction
);
284 DirectoryClose(pDirectory
);
288 int SearchExportWithImageHlp(char *InputPath
, char *ExportFunction
)
290 char *Filename
, *FunctionName
;
291 // Used to read export table
292 PIMAGE_EXPORT_DIRECTORY pExportTable
;
293 IMAGE_DATA_DIRECTORY ExportDirectory
;
295 DWORD
*pFunctions
; // an RVA
296 DWORD
*pNames
; // an RVA
297 USHORT
*pNameOrdinals
;
300 if (!(Filename
= strrchr(InputPath
, '\\')))
302 fprintf(stderr
, "Error: unexpected file \"%s\"\n", InputPath
);
307 printf("Loading %s\n", Filename
);
308 if (!MapAndLoad(Filename
, InputPath
, &Image
, FALSE
, TRUE
))
310 fprintf(stderr
, "Unable to map and load %s\n", Filename
);
314 ExportDirectory
= Image
.FileHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
];
315 if (!ExportDirectory
.VirtualAddress
) return 0; // no exports
317 if (ExportDirectory
.Size
< sizeof(IMAGE_EXPORT_DIRECTORY
))
319 fprintf(stderr
, "Error loading %s: invalid export table (size < sizeof(IMAGE_EXPORT_DIRECTORY))\n", Filename
);
320 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
324 pExportTable
= (PIMAGE_EXPORT_DIRECTORY
)GetAddressFromRVA(Image
, ExportDirectory
.VirtualAddress
);
327 fprintf(stderr
, "Error loading %s: invalid export table (invalid RVA)\n", Filename
);
328 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
332 pFunctions
= (DWORD
*)GetAddressFromRVA(Image
, pExportTable
->AddressOfFunctions
);
333 pNameOrdinals
= (USHORT
*)GetAddressFromRVA(Image
, pExportTable
->AddressOfNameOrdinals
);
334 pNames
= (DWORD
*)GetAddressFromRVA(Image
, pExportTable
->AddressOfNames
);
336 if (!pFunctions
|| !pNameOrdinals
|| !pNames
)
338 fprintf(stderr
, "Error loading %s: invalid export table (invalid name/function/ordinal RVAs)\n", Filename
);
339 if (!UnMapAndLoad(&Image
)) fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());
343 // Rather than just read directly from pNames, we do this to ensure that we're matching
344 // a function instead of a variable
345 for (i
= 0; i
< pExportTable
->NumberOfFunctions
; i
++)
347 if (!pFunctions
[i
]) continue;
349 for (j
= 0; j
< pExportTable
->NumberOfNames
; j
++)
351 if (i
== pNameOrdinals
[j
])
353 FunctionName
= (char *)GetAddressFromRVA(Image
, pNames
[j
]);
354 if (_stricmp(FunctionName
, ExportFunction
) == 0)
356 printf("Match found: %s\\%s exports %s\n", InputPath
, Filename
, FunctionName
);
359 if (!UnMapAndLoad(&Image
))
361 fprintf(stderr
, "Error unloading %s (error code 0x%08lx)\n", Filename
, GetLastError());