Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2009-02-18 17:25:20 +01:00
Родитель f768fdfad9
Коммит df724b0324
10 изменённых файлов: 909 добавлений и 1051 удалений

1
src/depends/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
*.o

10
src/depends/Makefile Normal file
Просмотреть файл

@ -0,0 +1,10 @@
TARGET=depends.exe
OBJS=directory.o image.o depends.o
CFLAGS=-g
LIBS=-limagehlp
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $^ $(LIBS)

Просмотреть файл

@ -1,36 +1,36 @@
w00w00 improved version of depends.exe (minus the GUI + automated searching)
Matt Conover (shok@dataforce.net)
April 2003
This will find *.exe, *.dll, *.sys, and *.pyd (Python DLLs) that imports a certain DLL or function in a DLL (e.g., import wsock32.dll or import msvcrt.dll!_snprintf) or export a certain function. It can be useful when you don't know what libraries export a certain function (like RtlInitUnicodeString) or you want to find all applications using a function in a DLL with a known vulnerability.
Usage: w00depends test.dll c:\dir\test.exe
Report if c:\dir\test.exe imports test.dll
Examples:
w00depends test.dll!funcname c:\dir\test.exe
Report if c:\dir\test.exe imports test.dll!funcname
w00depends test.dll c:\dir
Find executables importing test.dll in c:\dir
w00depends test.dll!funcname c:\dir
Find executables importing funcname from test.dll in c:\dir
w00depends test!funcname c:\dir
Find executables importing funcname from test.dll in c:\dir
w00depends test!ord_1234 c:\dir
Find executables importing ordinal 1234 (in decimal) from test.dll in c:\dir
w00depends -e funcname c:\dir
Find all DLLs exporting funcname in c:\dir
Output will look like this:
C:\> w00depends kernel32!CreateFileA c:\winnt\system32
Match found: c:\winnt\system32\ACrd10SM.dll imports kernel32!createfilea
Match found: c:\winnt\system32\actmovie.exe imports kernel32!createfilea
Match found: c:\winnt\system32\ACUMon.exe imports kernel32!createfilea
Match found: c:\winnt\system32\ADVAPI32.DLL imports kernel32!createfilea
Match found: c:\winnt\system32\advpack.dll imports kernel32!createfilea
Match found: c:\winnt\system32\atmadm.exe imports kernel32!createfilea
Match found: c:\winnt\system32\AUTMGR32.EXE imports kernel32!createfilea
Match found: c:\winnt\system32\Axntbc32.dll imports kernel32!createfilea
Match found: c:\winnt\system32\Axntcp32.dll imports kernel32!createfilea
Match found: c:\winnt\system32\cabinet.dll imports kernel32!createfilea
Match found: c:\winnt\system32\catsrvut.dll imports kernel32!createfilea
w00w00 improved version of depends.exe (minus the GUI + automated searching)
Matt Conover (shok@dataforce.net)
April 2003
This will find *.exe, *.dll, *.sys, and *.pyd (Python DLLs) that imports a certain DLL or function in a DLL (e.g., import wsock32.dll or import msvcrt.dll!_snprintf) or export a certain function. It can be useful when you don't know what libraries export a certain function (like RtlInitUnicodeString) or you want to find all applications using a function in a DLL with a known vulnerability.
Usage: w00depends test.dll c:\dir\test.exe
Report if c:\dir\test.exe imports test.dll
Examples:
w00depends test.dll!funcname c:\dir\test.exe
Report if c:\dir\test.exe imports test.dll!funcname
w00depends test.dll c:\dir
Find executables importing test.dll in c:\dir
w00depends test.dll!funcname c:\dir
Find executables importing funcname from test.dll in c:\dir
w00depends test!funcname c:\dir
Find executables importing funcname from test.dll in c:\dir
w00depends test!ord_1234 c:\dir
Find executables importing ordinal 1234 (in decimal) from test.dll in c:\dir
w00depends -e funcname c:\dir
Find all DLLs exporting funcname in c:\dir
Output will look like this:
C:\> w00depends kernel32!CreateFileA c:\winnt\system32
Match found: c:\winnt\system32\ACrd10SM.dll imports kernel32!createfilea
Match found: c:\winnt\system32\actmovie.exe imports kernel32!createfilea
Match found: c:\winnt\system32\ACUMon.exe imports kernel32!createfilea
Match found: c:\winnt\system32\ADVAPI32.DLL imports kernel32!createfilea
Match found: c:\winnt\system32\advpack.dll imports kernel32!createfilea
Match found: c:\winnt\system32\atmadm.exe imports kernel32!createfilea
Match found: c:\winnt\system32\AUTMGR32.EXE imports kernel32!createfilea
Match found: c:\winnt\system32\Axntbc32.dll imports kernel32!createfilea
Match found: c:\winnt\system32\Axntcp32.dll imports kernel32!createfilea
Match found: c:\winnt\system32\cabinet.dll imports kernel32!createfilea
Match found: c:\winnt\system32\catsrvut.dll imports kernel32!createfilea

Просмотреть файл

@ -1,371 +1,371 @@
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "directory.h"
#include "image.h"
#define EXECUTABLES "*.exe;*.dll;*.sys;*.pyd"
int SearchImport(char *ImportDLL, char *ImportFunction, char *SourcePath);
int SearchExport(char *ExportFunction, char *SourcePath);
int SearchImportWithImageHlp(char *InputPath, char *ImportDLL, char *ImportFunction);
int SearchExportWithImageHlp(char *InputPath, char *ExportFunction);
void Usage(char *ProgramName)
{
printf("Usage: %s test.dll c:\\dir\\test.exe\n", ProgramName);
printf("\tReport if c:\\dir\\test.exe imports test.dll\n");
printf("\nExamples:\n");
printf("%s test.dll!funcname c:\\dir\\test.exe\n", ProgramName);
printf("\tReport if c:\\dir\\test.exe imports test.dll!funcname\n");
printf("%s test.dll c:\\dir\n", ProgramName);
printf("\tFind executables importing test.dll in c:\\dir\n");
printf("%s test.dll!funcname c:\\dir\n", ProgramName);
printf("\tFind executables importing funcname from test.dll in c:\\dir\n");
printf("%s test!funcname c:\\dir\n", ProgramName);
printf("\tFind executables importing funcname from test.dll in c:\\dir\n");
printf("%s test!ord_1234 c:\\dir\n", ProgramName);
printf("\tFind executables importing ordinal 1234 (in decimal) from test.dll in c:\\dir\n");
printf("\tNOTE: this only works if there is no name associated with the function\n");
printf("%s -e funcname c:\\dir\n", ProgramName);
printf("\tFind all DLLs exporting funcname in c:\\dir\n");
}
// Try to match Target against Source
BOOL CompareFilenames(char *Target, char *Source)
{
DWORD i;
BOOL HasExtension = FALSE;
if (!Target || !Source || !Target[0] || !Source[0]) return FALSE;
if (strchr(Source, '.')) HasExtension = TRUE;
// If we don't need to consider that the source may lack an extension,
// then the lengths must be the same
if (HasExtension && strlen(Target) != strlen(Source)) return FALSE;
for (i = 0; i < strlen(Source); i++)
{
if (tolower(Target[i]) != tolower(Source[i])) return FALSE;
}
if (HasExtension)
{
if (Target[i]) return FALSE;
else return TRUE;
}
else
{
if (Target[i] == '.') return TRUE;
else return FALSE;
}
}
int main(int argc, char* argv[])
{
char *ImportFunction;
if (argc < 2)
{
Usage(argv[0]);
return -1;
}
if (argv[1][0] == '-')
{
if (tolower(argv[1][1]) != 'e')
{
fprintf(stderr, "Error: -e is the only valid option\n");
Usage(argv[0]);
return -1;
}
if (argc != 3 && argc != 4)
{
fprintf(stderr, "Error: incorrect number of parameters for export searching\n");
Usage(argv[0]);
return -1;
}
if (strchr(argv[2], '!'))
{
fprintf(stderr, "Error: you cannot pass a dll!func format with -e\n");
Usage(argv[0]);
return -1;
}
if (argc == 4) return SearchExport(argv[2], argv[3]);
else return SearchExport(argv[2], NULL);
}
else
{
if (argc != 3)
{
fprintf(stderr, "Error: incorrect number of parameters for import searching\n");
Usage(argv[0]);
return -1;
}
if ((ImportFunction = strchr(argv[1], '!')) != NULL)
{
*ImportFunction++ = '\0';
return SearchImport(argv[1], ImportFunction, argv[2]);
}
else return SearchImport(argv[1], NULL, argv[2]);
}
return 0;
}
int SearchImport(char *ImportDLL, char *ImportFunction, char *SourcePath)
{
PDIRECTORY_INFO pDirectory;
PSEARCH_RESULTS result;
if (!(pDirectory = DirectoryOpen(SourcePath, TRUE))) return -1;
if (!DirectorySearch(pDirectory, EXECUTABLES)) return -1;
for (result = pDirectory->pSearchResults; result; result = result->Next)
{
SearchImportWithImageHlp(result->FilePath, ImportDLL, ImportFunction);
}
DirectoryClose(pDirectory);
return 0;
}
int SearchImportWithImageHlp(char *InputPath, char *ImportDLL, char *ImportFunction)
{
DWORD i = 0;
BOOL ModuleFound;
char *Filename, *ModuleName;
// Used to read import table
LOADED_IMAGE Image;
IMAGE_DATA_DIRECTORY ImportDirectory;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_THUNK_DATA pThunk, pThunkIAT;
PIMAGE_IMPORT_BY_NAME pOrdinalName;
USHORT ImportOrdinal = 0;
BOOL UseOrdinal = FALSE;
if (!(Filename = strrchr(InputPath, '\\')))
{
fprintf(stderr, "Error: unexpected file \"%s\"\n", InputPath);
return -1;
}
*Filename++ = '\0';
//printf("Loading %s\n", Filename);
// TODO: under what circumstances does this fail?
if (!MapAndLoad(Filename, InputPath, &Image, FALSE, TRUE))
{
fprintf(stderr, "Unable to map and load %s\n", Filename);
return -1;
}
ImportDirectory = Image.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (!ImportDirectory.VirtualAddress) return 0; // no imports
if (ImportDirectory.Size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
{
fprintf(stderr, "Error loading %s: invalid import descriptor table (size < sizeof(IMAGE_IMPORT_DESCRIPTOR))\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)GetAddressFromRVA(Image, ImportDirectory.VirtualAddress);
if (!pImportDescriptor)
{
fprintf(stderr, "Error loading %s: invalid import descriptor table (invalid RVA)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
for (i = 0, ModuleFound = FALSE; i < ImportDirectory.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); i++)
{
ModuleName = (char *)GetAddressFromRVA(Image, pImportDescriptor->Name);
if (!ModuleName || !ModuleName[0]) break;
if (CompareFilenames(ModuleName, ImportDLL))
{
ModuleFound = TRUE;
break;
}
pImportDescriptor++;
}
if (!ModuleFound)
{
if (!UnMapAndLoad(&Image))
{
fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 0;
}
return -1;
}
if (!ImportFunction)
{
printf("Match found: %s\\%s imports the library %s\n", InputPath, Filename, ImportDLL);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 1;
}
if (strncmp(ImportFunction, "ord_", 4) == 0)
{
ImportOrdinal = atoi(ImportFunction + 4);
if (!ImportOrdinal && ImportFunction[4] != '0')
{
fprintf(stderr, "Error: you passed an invalid ordinal\n");
fprintf(stderr, "Should be in the format ord_1234 where 1234 is a decimal number\n");
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
UseOrdinal = TRUE;
}
pThunkIAT = (PIMAGE_THUNK_DATA)GetAddressFromRVA(Image, pImportDescriptor->FirstThunk);
if (!pImportDescriptor->OriginalFirstThunk) pThunk = pThunkIAT;
else pThunk = (PIMAGE_THUNK_DATA)GetAddressFromRVA(Image, pImportDescriptor->OriginalFirstThunk);
if (!pThunk || !pThunkIAT)
{
fprintf(stderr, "Error loading %s: invalid import descriptor table (neither thunk is set)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
for (; ; pThunk++, pThunkIAT++)
{
if (!pThunk->u1.AddressOfData) break;
if (UseOrdinal && pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
if (ImportOrdinal == IMAGE_ORDINAL(pThunk->u1.Ordinal))
{
printf("Match found: %s\\%s imports ordinal %d from %s\n", InputPath, Filename, ImportOrdinal, ImportDLL);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 1;
}
}
else
{
pOrdinalName = (PIMAGE_IMPORT_BY_NAME)GetAddressFromRVA(Image, (DWORD)pThunk->u1.AddressOfData);
if (!pOrdinalName) continue;
if (_stricmp(pOrdinalName->Name, ImportFunction) == 0)
{
printf("Match found: %s\\%s imports %s!%s\n", InputPath, Filename, ImportDLL, pOrdinalName->Name);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 1;
}
}
}
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 0;
}
int SearchExport(char *ExportFunction, char *SourcePath)
{
PDIRECTORY_INFO pDirectory;
PSEARCH_RESULTS result;
if (!(pDirectory = DirectoryOpen(SourcePath, TRUE))) return -1;
if (!DirectorySearch(pDirectory, EXECUTABLES)) return -1;
for (result = pDirectory->pSearchResults; result; result = result->Next)
{
SearchExportWithImageHlp(result->FilePath, ExportFunction);
}
DirectoryClose(pDirectory);
return 0;
}
int SearchExportWithImageHlp(char *InputPath, char *ExportFunction)
{
char *Filename, *FunctionName;
// Used to read export table
PIMAGE_EXPORT_DIRECTORY pExportTable;
IMAGE_DATA_DIRECTORY ExportDirectory;
LOADED_IMAGE Image;
DWORD *pFunctions; // an RVA
DWORD *pNames; // an RVA
USHORT *pNameOrdinals;
USHORT i, j;
if (!(Filename = strrchr(InputPath, '\\')))
{
fprintf(stderr, "Error: unexpected file \"%s\"\n", InputPath);
return -1;
}
*Filename++ = '\0';
printf("Loading %s\n", Filename);
if (!MapAndLoad(Filename, InputPath, &Image, FALSE, TRUE))
{
fprintf(stderr, "Unable to map and load %s\n", Filename);
return -1;
}
ExportDirectory = Image.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (!ExportDirectory.VirtualAddress) return 0; // no exports
if (ExportDirectory.Size < sizeof(IMAGE_EXPORT_DIRECTORY))
{
fprintf(stderr, "Error loading %s: invalid export table (size < sizeof(IMAGE_EXPORT_DIRECTORY))\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
pExportTable = (PIMAGE_EXPORT_DIRECTORY)GetAddressFromRVA(Image, ExportDirectory.VirtualAddress);
if (!pExportTable)
{
fprintf(stderr, "Error loading %s: invalid export table (invalid RVA)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
pFunctions = (DWORD *)GetAddressFromRVA(Image, pExportTable->AddressOfFunctions);
pNameOrdinals = (USHORT *)GetAddressFromRVA(Image, pExportTable->AddressOfNameOrdinals);
pNames = (DWORD *)GetAddressFromRVA(Image, pExportTable->AddressOfNames);
if (!pFunctions || !pNameOrdinals || !pNames)
{
fprintf(stderr, "Error loading %s: invalid export table (invalid name/function/ordinal RVAs)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
// Rather than just read directly from pNames, we do this to ensure that we're matching
// a function instead of a variable
for (i = 0; i < pExportTable->NumberOfFunctions; i++)
{
if (!pFunctions[i]) continue;
for (j = 0; j < pExportTable->NumberOfNames; j++)
{
if (i == pNameOrdinals[j])
{
FunctionName = (char *)GetAddressFromRVA(Image, pNames[j]);
if (_stricmp(FunctionName, ExportFunction) == 0)
{
printf("Match found: %s\\%s exports %s\n", InputPath, Filename, FunctionName);
exit(0);
if (!UnMapAndLoad(&Image))
{
fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
return 1;
}
}
}
}
return 0;
}
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "directory.h"
#include "image.h"
#define EXECUTABLES "*.exe;*.dll;*.sys;*.pyd"
int SearchImport(char *ImportDLL, char *ImportFunction, char *SourcePath);
int SearchExport(char *ExportFunction, char *SourcePath);
int SearchImportWithImageHlp(char *InputPath, char *ImportDLL, char *ImportFunction);
int SearchExportWithImageHlp(char *InputPath, char *ExportFunction);
void Usage(char *ProgramName)
{
printf("Usage: %s test.dll c:\\dir\\test.exe\n", ProgramName);
printf("\tReport if c:\\dir\\test.exe imports test.dll\n");
printf("\nExamples:\n");
printf("%s test.dll!funcname c:\\dir\\test.exe\n", ProgramName);
printf("\tReport if c:\\dir\\test.exe imports test.dll!funcname\n");
printf("%s test.dll c:\\dir\n", ProgramName);
printf("\tFind executables importing test.dll in c:\\dir\n");
printf("%s test.dll!funcname c:\\dir\n", ProgramName);
printf("\tFind executables importing funcname from test.dll in c:\\dir\n");
printf("%s test!funcname c:\\dir\n", ProgramName);
printf("\tFind executables importing funcname from test.dll in c:\\dir\n");
printf("%s test!ord_1234 c:\\dir\n", ProgramName);
printf("\tFind executables importing ordinal 1234 (in decimal) from test.dll in c:\\dir\n");
printf("\tNOTE: this only works if there is no name associated with the function\n");
printf("%s -e funcname c:\\dir\n", ProgramName);
printf("\tFind all DLLs exporting funcname in c:\\dir\n");
}
// Try to match Target against Source
BOOL CompareFilenames(char *Target, char *Source)
{
DWORD i;
BOOL HasExtension = FALSE;
if (!Target || !Source || !Target[0] || !Source[0]) return FALSE;
if (strchr(Source, '.')) HasExtension = TRUE;
// If we don't need to consider that the source may lack an extension,
// then the lengths must be the same
if (HasExtension && strlen(Target) != strlen(Source)) return FALSE;
for (i = 0; i < strlen(Source); i++)
{
if (tolower(Target[i]) != tolower(Source[i])) return FALSE;
}
if (HasExtension)
{
if (Target[i]) return FALSE;
else return TRUE;
}
else
{
if (Target[i] == '.') return TRUE;
else return FALSE;
}
}
int main(int argc, char* argv[])
{
char *ImportFunction;
if (argc < 2)
{
Usage(argv[0]);
return -1;
}
if (argv[1][0] == '-')
{
if (tolower(argv[1][1]) != 'e')
{
fprintf(stderr, "Error: -e is the only valid option\n");
Usage(argv[0]);
return -1;
}
if (argc != 3 && argc != 4)
{
fprintf(stderr, "Error: incorrect number of parameters for export searching\n");
Usage(argv[0]);
return -1;
}
if (strchr(argv[2], '!'))
{
fprintf(stderr, "Error: you cannot pass a dll!func format with -e\n");
Usage(argv[0]);
return -1;
}
if (argc == 4) return SearchExport(argv[2], argv[3]);
else return SearchExport(argv[2], NULL);
}
else
{
if (argc != 3)
{
fprintf(stderr, "Error: incorrect number of parameters for import searching\n");
Usage(argv[0]);
return -1;
}
if ((ImportFunction = strchr(argv[1], '!')) != NULL)
{
*ImportFunction++ = '\0';
return SearchImport(argv[1], ImportFunction, argv[2]);
}
else return SearchImport(argv[1], NULL, argv[2]);
}
return 0;
}
int SearchImport(char *ImportDLL, char *ImportFunction, char *SourcePath)
{
PDIRECTORY_INFO pDirectory;
PSEARCH_RESULTS result;
if (!(pDirectory = DirectoryOpen(SourcePath, TRUE))) return -1;
if (!DirectorySearch(pDirectory, EXECUTABLES)) return -1;
for (result = pDirectory->pSearchResults; result; result = result->Next)
{
SearchImportWithImageHlp(result->FilePath, ImportDLL, ImportFunction);
}
DirectoryClose(pDirectory);
return 0;
}
int SearchImportWithImageHlp(char *InputPath, char *ImportDLL, char *ImportFunction)
{
DWORD i = 0;
BOOL ModuleFound;
char *Filename, *ModuleName;
// Used to read import table
LOADED_IMAGE Image;
IMAGE_DATA_DIRECTORY ImportDirectory;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_THUNK_DATA pThunk, pThunkIAT;
PIMAGE_IMPORT_BY_NAME pOrdinalName;
USHORT ImportOrdinal = 0;
BOOL UseOrdinal = FALSE;
if (!(Filename = strrchr(InputPath, '\\')))
{
fprintf(stderr, "Error: unexpected file \"%s\"\n", InputPath);
return -1;
}
*Filename++ = '\0';
//printf("Loading %s\n", Filename);
// TODO: under what circumstances does this fail?
if (!MapAndLoad(Filename, InputPath, &Image, FALSE, TRUE))
{
fprintf(stderr, "Unable to map and load %s\n", Filename);
return -1;
}
ImportDirectory = Image.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (!ImportDirectory.VirtualAddress) return 0; // no imports
if (ImportDirectory.Size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
{
fprintf(stderr, "Error loading %s: invalid import descriptor table (size < sizeof(IMAGE_IMPORT_DESCRIPTOR))\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)GetAddressFromRVA(Image, ImportDirectory.VirtualAddress);
if (!pImportDescriptor)
{
fprintf(stderr, "Error loading %s: invalid import descriptor table (invalid RVA)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
for (i = 0, ModuleFound = FALSE; i < ImportDirectory.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); i++)
{
ModuleName = (char *)GetAddressFromRVA(Image, pImportDescriptor->Name);
if (!ModuleName || !ModuleName[0]) break;
if (CompareFilenames(ModuleName, ImportDLL))
{
ModuleFound = TRUE;
break;
}
pImportDescriptor++;
}
if (!ModuleFound)
{
if (!UnMapAndLoad(&Image))
{
fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 0;
}
return -1;
}
if (!ImportFunction)
{
printf("Match found: %s\\%s imports the library %s\n", InputPath, Filename, ImportDLL);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 1;
}
if (strncmp(ImportFunction, "ord_", 4) == 0)
{
ImportOrdinal = atoi(ImportFunction + 4);
if (!ImportOrdinal && ImportFunction[4] != '0')
{
fprintf(stderr, "Error: you passed an invalid ordinal\n");
fprintf(stderr, "Should be in the format ord_1234 where 1234 is a decimal number\n");
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
UseOrdinal = TRUE;
}
pThunkIAT = (PIMAGE_THUNK_DATA)GetAddressFromRVA(Image, pImportDescriptor->FirstThunk);
if (!pImportDescriptor->OriginalFirstThunk) pThunk = pThunkIAT;
else pThunk = (PIMAGE_THUNK_DATA)GetAddressFromRVA(Image, pImportDescriptor->OriginalFirstThunk);
if (!pThunk || !pThunkIAT)
{
fprintf(stderr, "Error loading %s: invalid import descriptor table (neither thunk is set)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
for (; ; pThunk++, pThunkIAT++)
{
if (!pThunk->u1.AddressOfData) break;
if (UseOrdinal && pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
if (ImportOrdinal == IMAGE_ORDINAL(pThunk->u1.Ordinal))
{
printf("Match found: %s\\%s imports ordinal %d from %s\n", InputPath, Filename, ImportOrdinal, ImportDLL);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 1;
}
}
else
{
pOrdinalName = (PIMAGE_IMPORT_BY_NAME)GetAddressFromRVA(Image, (DWORD)pThunk->u1.AddressOfData);
if (!pOrdinalName) continue;
if (_stricmp(pOrdinalName->Name, ImportFunction) == 0)
{
printf("Match found: %s\\%s imports %s!%s\n", InputPath, Filename, ImportDLL, pOrdinalName->Name);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 1;
}
}
}
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return 0;
}
int SearchExport(char *ExportFunction, char *SourcePath)
{
PDIRECTORY_INFO pDirectory;
PSEARCH_RESULTS result;
if (!(pDirectory = DirectoryOpen(SourcePath, TRUE))) return -1;
if (!DirectorySearch(pDirectory, EXECUTABLES)) return -1;
for (result = pDirectory->pSearchResults; result; result = result->Next)
{
SearchExportWithImageHlp(result->FilePath, ExportFunction);
}
DirectoryClose(pDirectory);
return 0;
}
int SearchExportWithImageHlp(char *InputPath, char *ExportFunction)
{
char *Filename, *FunctionName;
// Used to read export table
PIMAGE_EXPORT_DIRECTORY pExportTable;
IMAGE_DATA_DIRECTORY ExportDirectory;
LOADED_IMAGE Image;
DWORD *pFunctions; // an RVA
DWORD *pNames; // an RVA
USHORT *pNameOrdinals;
USHORT i, j;
if (!(Filename = strrchr(InputPath, '\\')))
{
fprintf(stderr, "Error: unexpected file \"%s\"\n", InputPath);
return -1;
}
*Filename++ = '\0';
printf("Loading %s\n", Filename);
if (!MapAndLoad(Filename, InputPath, &Image, FALSE, TRUE))
{
fprintf(stderr, "Unable to map and load %s\n", Filename);
return -1;
}
ExportDirectory = Image.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (!ExportDirectory.VirtualAddress) return 0; // no exports
if (ExportDirectory.Size < sizeof(IMAGE_EXPORT_DIRECTORY))
{
fprintf(stderr, "Error loading %s: invalid export table (size < sizeof(IMAGE_EXPORT_DIRECTORY))\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
pExportTable = (PIMAGE_EXPORT_DIRECTORY)GetAddressFromRVA(Image, ExportDirectory.VirtualAddress);
if (!pExportTable)
{
fprintf(stderr, "Error loading %s: invalid export table (invalid RVA)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
pFunctions = (DWORD *)GetAddressFromRVA(Image, pExportTable->AddressOfFunctions);
pNameOrdinals = (USHORT *)GetAddressFromRVA(Image, pExportTable->AddressOfNameOrdinals);
pNames = (DWORD *)GetAddressFromRVA(Image, pExportTable->AddressOfNames);
if (!pFunctions || !pNameOrdinals || !pNames)
{
fprintf(stderr, "Error loading %s: invalid export table (invalid name/function/ordinal RVAs)\n", Filename);
if (!UnMapAndLoad(&Image)) fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
// Rather than just read directly from pNames, we do this to ensure that we're matching
// a function instead of a variable
for (i = 0; i < pExportTable->NumberOfFunctions; i++)
{
if (!pFunctions[i]) continue;
for (j = 0; j < pExportTable->NumberOfNames; j++)
{
if (i == pNameOrdinals[j])
{
FunctionName = (char *)GetAddressFromRVA(Image, pNames[j]);
if (_stricmp(FunctionName, ExportFunction) == 0)
{
printf("Match found: %s\\%s exports %s\n", InputPath, Filename, FunctionName);
exit(0);
if (!UnMapAndLoad(&Image))
{
fprintf(stderr, "Error unloading %s (error code 0x%08lx)\n", Filename, GetLastError());
return -1;
}
return 1;
}
}
}
}
return 0;
}

Просмотреть файл

@ -1,432 +1,432 @@
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "directory.h"
#define MAX_WILDCARDS 10
// Internal functions only
BOOL AddFileToSearchResult(PDIRECTORY_INFO pDirectory, char *BasePathName, char *Filename);
BOOL MergeSearchResults(PDIRECTORY_INFO pBaseDir, PDIRECTORY_INFO pSubDir);
BOOL MergeSearchResultsAndClose(PDIRECTORY_INFO pBaseDir, PDIRECTORY_INFO pSubDir);
PSEARCH_RESULTS GetLastSearchResult(PSEARCH_RESULTS pSearchResult);
DWORD GetSearchResultCount(PSEARCH_RESULTS pSearchResult);
void DumpSearchResults(PSEARCH_RESULTS pSearchResults);
BOOL IsSameExtension(char *Extension1, char *Extension2)
{
if (_stricmp(Extension1, Extension2) == 0) return TRUE;
else return FALSE;
}
void PrintWildcardError()
{
fprintf(stderr, "Error: invalid wildcards for filename\n"
"Wildcards can be:\n"
"\tfilename match \"filename\"\n"
"\tfilename.ext match \"filename.ext\"\n"
"\t* match all files (with or without extensions)\n"
"\t*.* match all files with extensions\n"
"\t*. match all files without extensions\n"
"\t*.ext match all files ending in \".ext\"\n"
"\t*.ext1;*.ext2 match all files ending in \".ext1\" or \".ext2\"\n");
}
PDIRECTORY_INFO DirectoryOpen(char *Directory, BOOL RecurseSubDirs)
{
PDIRECTORY_INFO pDirectory;
char tmpdir[MAX_PATH+1];
if (!Directory) return NULL;
//printf("Opening directory %s (RecurseSubDirs = %d)\n", Directory, RecurseSubDirs);
pDirectory = (PDIRECTORY_INFO)malloc(sizeof(DIRECTORY_INFO));
if (!pDirectory)
{
fprintf(stderr, "Unable to allocate %d bytes\n", sizeof(DIRECTORY_INFO));
return NULL;
}
_snprintf(tmpdir, sizeof(tmpdir), "%s\\*", Directory);
pDirectory->hFileList = FindFirstFile(tmpdir, &pDirectory->BasePath);
if (pDirectory->hFileList == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Invalid path \"%s\"\n", Directory);
return NULL;
}
pDirectory->Initialized = TRUE;
pDirectory->Finished = FALSE;
pDirectory->RecurseSubDirs = RecurseSubDirs;
pDirectory->pSearchResults = NULL;
_snprintf(pDirectory->BasePathName, sizeof(pDirectory->BasePathName), "%s", Directory);
return pDirectory;
}
void DirectoryClose(PDIRECTORY_INFO pDirectory)
{
PSEARCH_RESULTS pLast;
if (!pDirectory || !pDirectory->Initialized) return;
//printf("Closing %s\n", pDirectory->BasePathName);
// Free the search results, if any
if (pDirectory->pSearchResults)
{
assert(pDirectory->pSearchResults->Previous == NULL);
pLast = GetLastSearchResult(pDirectory->pSearchResults);
assert(pLast);
while (pLast->Previous)
{
assert(pLast->FilePath);
if (pLast->FilePath)
{
//printf("Deallocating entry for %s\n", pLast->FilePath);
free(pLast->FilePath);
pLast->FilePath = NULL;
}
pLast = pLast->Previous;
free(pLast->Next);
pLast->Next = NULL;
}
assert(pDirectory->pSearchResults == pLast);
assert(pDirectory->pSearchResults->FilePath);
if (pDirectory->pSearchResults->FilePath)
{
//printf("Deallocating entry for %s\n", pDirectory->pSearchResults->FilePath);
free(pDirectory->pSearchResults->FilePath);
pDirectory->pSearchResults->FilePath = NULL;
}
pDirectory->pSearchResults->Next = NULL;
free(pDirectory->pSearchResults);
pDirectory->pSearchResults = NULL;
}
FindClose(pDirectory->hFileList);
pDirectory->Initialized = FALSE;
free(pDirectory);
}
// This will match all files in a directory (or subdirectories if recursion is enabled)
// Currently, this will not match any directories or specific filenames
// Must use "*", "*.ext", or "*.ext1;*.ext2"
// This is definitely not efficient and may crash when dealing with very deep levels
BOOL DirectorySearch(PDIRECTORY_INFO pDirectory, char *FileWildcard)
{
int i, WildcardCount = 0;
BOOL IsDirectory;
BOOL RecurseSubDirs, MatchAllFiles = FALSE;
char tmpSubDir[MAX_PATH+1];
char *tmpWildcard, *Wildcard, *Wildcards[MAX_WILDCARDS];
char *BasePathName, *Filename, *FileExtension, *tmpFileExtension;
PDIRECTORY_INFO pNewDirectory;
if (!pDirectory || !pDirectory->Initialized || pDirectory->Finished) return FALSE;
//////////////////////////////////////////////////////////////
// Setup wildcards
if (!FileWildcard)
{
MatchAllFiles = TRUE;
}
else if (!FileWildcard[0] || strchr(FileWildcard, ','))
{
PrintWildcardError();
return FALSE;
}
else
{
if (!(tmpWildcard = Wildcard = strdup(FileWildcard)))
{
fprintf(stderr, "Error allocating %d bytes\n", strlen(FileWildcard)+1);
return FALSE;
}
while (*tmpWildcard && (tmpFileExtension = strchr(tmpWildcard, ';')))
{
*tmpFileExtension++ = '\0';
if (WildcardCount == MAX_WILDCARDS - 1) return FALSE;
if (tmpWildcard[0] == '*' && !tmpWildcard[1])
{
MatchAllFiles = TRUE;
break;
}
else
{
if (tmpWildcard[0] == '*' && tmpWildcard[1] != '.')
{
PrintWildcardError();
return FALSE;
}
Wildcards[WildcardCount++] = strdup(tmpWildcard);
tmpWildcard = tmpFileExtension;
}
}
if (MatchAllFiles || (tmpWildcard[0] == '*' && !tmpWildcard[1]))
{
MatchAllFiles = TRUE;
for (i = 0; i < WildcardCount; i++) free(Wildcards[i]);
WildcardCount = 0;
}
else if (*tmpWildcard)
{
Wildcards[WildcardCount++] = strdup(tmpWildcard);
free(Wildcard);
}
}
//////////////////////////////////////////////////////////////
// Iterate through subdirectories
RecurseSubDirs = pDirectory->RecurseSubDirs;
BasePathName = pDirectory->BasePathName;
Filename = pDirectory->BasePath.cFileName;
//printf("=== Searching in %s (RecurseSubDirs = %d)\n", BasePathName, RecurseSubDirs);
while (TRUE)
{
IsDirectory = pDirectory->BasePath.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
FileExtension = strrchr(Filename, '.');
// Match if the currently found item is a subdirectory and recursion is enabled
if (IsDirectory && RecurseSubDirs && *Filename != '.')
{
_snprintf(tmpSubDir, sizeof(tmpSubDir), "%s\\%s", BasePathName, Filename);
if (!(pNewDirectory = DirectoryOpen(tmpSubDir, TRUE))) return FALSE;
if (!(DirectorySearch(pNewDirectory, FileWildcard))) return FALSE;
if (!MergeSearchResults(pDirectory, pNewDirectory)) return FALSE;
DirectoryClose(pNewDirectory);
}
// Try to match the current file to a wildcard or filename
else if (!IsDirectory)
{
//printf("Found %s\\%s\n", BasePathName, Filename);
if (MatchAllFiles)
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
}
else if (FileExtension)
{
FileExtension++; // point to one byte past "." (the file extension)
for (i = 0; i < WildcardCount; i++)
{
if (Wildcards[i][0] == '*')
{
if (!Wildcards[i][1] || Wildcards[i][2] == '*')
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
else if (Wildcards[i][2] && IsSameExtension(FileExtension, Wildcards[i] + 2))
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
}
else if (IsSameExtension(Filename, Wildcards[i]))
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
}
}
else
{
for (i = 0; i < WildcardCount; i++)
{
if (Wildcards[i][0] == '*' && Wildcards[i][1] == '.' && !Wildcards[i][2])
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
else if (IsSameExtension(Filename, Wildcards[i])) // match file
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
}
}
}
if (!FindNextFile(pDirectory->hFileList, &pDirectory->BasePath))
{
if (GetLastError() == ERROR_NO_MORE_FILES) break;
fprintf(stderr, "FindNextFile failed: error code 0x%08lx\n", GetLastError());
return FALSE;
}
}
pDirectory->Finished = TRUE;
return TRUE;
}
PSEARCH_RESULTS GetLastSearchResult(PSEARCH_RESULTS pSearchResult)
{
while (pSearchResult && pSearchResult->Next) pSearchResult = pSearchResult->Next;
return pSearchResult;
}
BOOL AddFileToSearchResult(PDIRECTORY_INFO pDirectory, char *BasePathName, char *Filename)
{
DWORD PathLength;
PSEARCH_RESULTS pSearchResults;
////////////////////////////////////////////////////////////////
// Allocate a new search result set or append to an existing one
if (!pDirectory->pSearchResults)
{
pSearchResults = pDirectory->pSearchResults = malloc(sizeof(SEARCH_RESULTS));
if (!pSearchResults)
{
fprintf(stderr, "Error allocating %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pSearchResults->Previous = NULL;
}
else // an existing entry
{
pSearchResults = GetLastSearchResult(pDirectory->pSearchResults);
if (!(pSearchResults->Next = malloc(sizeof(SEARCH_RESULTS))))
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pSearchResults->Next->Previous = pSearchResults;
pSearchResults = pSearchResults->Next;
}
pSearchResults->Next = NULL;
////////////////////////////////////////////////////////////////
// Save path to filename for the search result
PathLength = strlen(pDirectory->BasePathName) + strlen(Filename) + 2;
if (PathLength > MAX_PATH)
{
fprintf(stderr, "Error: File path is too large\n");
return FALSE;
}
if (!(pSearchResults->FilePath = (char *)malloc(PathLength)))
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", PathLength);
return FALSE;
}
sprintf(pSearchResults->FilePath, "%s\\%s", BasePathName, Filename);
//printf("Added %s\n", pSearchResults->FilePath);
return TRUE;
}
BOOL MergeSearchResults(PDIRECTORY_INFO pBaseDir, PDIRECTORY_INFO pSubDir)
{
DWORD PathLength;
PSEARCH_RESULTS pDestination, pSource;
if (!pBaseDir || !pSubDir) return FALSE;
pSource = pSubDir->pSearchResults;
if (!pSource) return TRUE; // subdirectory is empty (don't merge)
assert(pSource->Previous == NULL);
if (!pBaseDir->pSearchResults) // merge subdirectory into empty result set
{
pDestination = pBaseDir->pSearchResults = malloc(sizeof(SEARCH_RESULTS));
if (!pDestination)
{
fprintf(stderr, "Error allocating %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pDestination->Previous = NULL;
pDestination->Next = NULL;
}
else // merge subdirectory with an existing result set
{
assert(pBaseDir->pSearchResults->Previous == NULL);
pDestination = GetLastSearchResult(pBaseDir->pSearchResults);
pDestination->Next = malloc(sizeof(SEARCH_RESULTS));
if (!pDestination->Next)
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pDestination->Next->Previous = pDestination;
pDestination = pDestination->Next;
pDestination->Next = NULL;
}
while (TRUE)
{
assert(pSource->FilePath != NULL);
PathLength = strlen(pSource->FilePath) + 1;
if (!(pDestination->FilePath = (char *)malloc(PathLength)))
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", PathLength);
return FALSE;
}
strcpy(pDestination->FilePath, pSource->FilePath);
//printf("Merged %s\n", pDestination->FilePath);
pSource = pSource->Next;
if (!pSource) break;
pDestination->Next = malloc(sizeof(SEARCH_RESULTS));
if (!pDestination->Next)
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pDestination->Next->Previous = pDestination;
pDestination = pDestination->Next;
pDestination->Next = NULL;
}
//printf("New base directory contains:\n");
//DumpSearchResults(pSubDir->pSearchResults);
return TRUE;
}
DWORD GetSearchResultCount(PSEARCH_RESULTS pSearchResult)
{
DWORD Count = 0;
if (!pSearchResult) return 0;
while (pSearchResult && pSearchResult->Next)
{
pSearchResult = pSearchResult->Next;
Count++;
}
return Count + 1;
}
void DumpSearchResults(PSEARCH_RESULTS pSearchResults)
{
PSEARCH_RESULTS tmpResult;
if (!pSearchResults) return;
printf("Total records: %d\n", GetSearchResultCount(pSearchResults));
for (tmpResult = pSearchResults; tmpResult; tmpResult = tmpResult->Next)
{
if (tmpResult->FilePath) printf("\t%s\n", tmpResult->FilePath);
}
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "directory.h"
#define MAX_WILDCARDS 10
// Internal functions only
BOOL AddFileToSearchResult(PDIRECTORY_INFO pDirectory, char *BasePathName, char *Filename);
BOOL MergeSearchResults(PDIRECTORY_INFO pBaseDir, PDIRECTORY_INFO pSubDir);
BOOL MergeSearchResultsAndClose(PDIRECTORY_INFO pBaseDir, PDIRECTORY_INFO pSubDir);
PSEARCH_RESULTS GetLastSearchResult(PSEARCH_RESULTS pSearchResult);
DWORD GetSearchResultCount(PSEARCH_RESULTS pSearchResult);
void DumpSearchResults(PSEARCH_RESULTS pSearchResults);
BOOL IsSameExtension(char *Extension1, char *Extension2)
{
if (_stricmp(Extension1, Extension2) == 0) return TRUE;
else return FALSE;
}
void PrintWildcardError()
{
fprintf(stderr, "Error: invalid wildcards for filename\n"
"Wildcards can be:\n"
"\tfilename match \"filename\"\n"
"\tfilename.ext match \"filename.ext\"\n"
"\t* match all files (with or without extensions)\n"
"\t*.* match all files with extensions\n"
"\t*. match all files without extensions\n"
"\t*.ext match all files ending in \".ext\"\n"
"\t*.ext1;*.ext2 match all files ending in \".ext1\" or \".ext2\"\n");
}
PDIRECTORY_INFO DirectoryOpen(char *Directory, BOOL RecurseSubDirs)
{
PDIRECTORY_INFO pDirectory;
char tmpdir[MAX_PATH+1];
if (!Directory) return NULL;
//printf("Opening directory %s (RecurseSubDirs = %d)\n", Directory, RecurseSubDirs);
pDirectory = (PDIRECTORY_INFO)malloc(sizeof(DIRECTORY_INFO));
if (!pDirectory)
{
fprintf(stderr, "Unable to allocate %d bytes\n", sizeof(DIRECTORY_INFO));
return NULL;
}
_snprintf(tmpdir, sizeof(tmpdir), "%s\\*", Directory);
pDirectory->hFileList = FindFirstFile(tmpdir, &pDirectory->BasePath);
if (pDirectory->hFileList == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Invalid path \"%s\"\n", Directory);
return NULL;
}
pDirectory->Initialized = TRUE;
pDirectory->Finished = FALSE;
pDirectory->RecurseSubDirs = RecurseSubDirs;
pDirectory->pSearchResults = NULL;
_snprintf(pDirectory->BasePathName, sizeof(pDirectory->BasePathName), "%s", Directory);
return pDirectory;
}
void DirectoryClose(PDIRECTORY_INFO pDirectory)
{
PSEARCH_RESULTS pLast;
if (!pDirectory || !pDirectory->Initialized) return;
//printf("Closing %s\n", pDirectory->BasePathName);
// Free the search results, if any
if (pDirectory->pSearchResults)
{
assert(pDirectory->pSearchResults->Previous == NULL);
pLast = GetLastSearchResult(pDirectory->pSearchResults);
assert(pLast);
while (pLast->Previous)
{
assert(pLast->FilePath);
if (pLast->FilePath)
{
//printf("Deallocating entry for %s\n", pLast->FilePath);
free(pLast->FilePath);
pLast->FilePath = NULL;
}
pLast = pLast->Previous;
free(pLast->Next);
pLast->Next = NULL;
}
assert(pDirectory->pSearchResults == pLast);
assert(pDirectory->pSearchResults->FilePath);
if (pDirectory->pSearchResults->FilePath)
{
//printf("Deallocating entry for %s\n", pDirectory->pSearchResults->FilePath);
free(pDirectory->pSearchResults->FilePath);
pDirectory->pSearchResults->FilePath = NULL;
}
pDirectory->pSearchResults->Next = NULL;
free(pDirectory->pSearchResults);
pDirectory->pSearchResults = NULL;
}
FindClose(pDirectory->hFileList);
pDirectory->Initialized = FALSE;
free(pDirectory);
}
// This will match all files in a directory (or subdirectories if recursion is enabled)
// Currently, this will not match any directories or specific filenames
// Must use "*", "*.ext", or "*.ext1;*.ext2"
// This is definitely not efficient and may crash when dealing with very deep levels
BOOL DirectorySearch(PDIRECTORY_INFO pDirectory, char *FileWildcard)
{
int i, WildcardCount = 0;
BOOL IsDirectory;
BOOL RecurseSubDirs, MatchAllFiles = FALSE;
char tmpSubDir[MAX_PATH+1];
char *tmpWildcard, *Wildcard, *Wildcards[MAX_WILDCARDS];
char *BasePathName, *Filename, *FileExtension, *tmpFileExtension;
PDIRECTORY_INFO pNewDirectory;
if (!pDirectory || !pDirectory->Initialized || pDirectory->Finished) return FALSE;
//////////////////////////////////////////////////////////////
// Setup wildcards
if (!FileWildcard)
{
MatchAllFiles = TRUE;
}
else if (!FileWildcard[0] || strchr(FileWildcard, ','))
{
PrintWildcardError();
return FALSE;
}
else
{
if (!(tmpWildcard = Wildcard = strdup(FileWildcard)))
{
fprintf(stderr, "Error allocating %d bytes\n", strlen(FileWildcard)+1);
return FALSE;
}
while (*tmpWildcard && (tmpFileExtension = strchr(tmpWildcard, ';')))
{
*tmpFileExtension++ = '\0';
if (WildcardCount == MAX_WILDCARDS - 1) return FALSE;
if (tmpWildcard[0] == '*' && !tmpWildcard[1])
{
MatchAllFiles = TRUE;
break;
}
else
{
if (tmpWildcard[0] == '*' && tmpWildcard[1] != '.')
{
PrintWildcardError();
return FALSE;
}
Wildcards[WildcardCount++] = strdup(tmpWildcard);
tmpWildcard = tmpFileExtension;
}
}
if (MatchAllFiles || (tmpWildcard[0] == '*' && !tmpWildcard[1]))
{
MatchAllFiles = TRUE;
for (i = 0; i < WildcardCount; i++) free(Wildcards[i]);
WildcardCount = 0;
}
else if (*tmpWildcard)
{
Wildcards[WildcardCount++] = strdup(tmpWildcard);
free(Wildcard);
}
}
//////////////////////////////////////////////////////////////
// Iterate through subdirectories
RecurseSubDirs = pDirectory->RecurseSubDirs;
BasePathName = pDirectory->BasePathName;
Filename = pDirectory->BasePath.cFileName;
//printf("=== Searching in %s (RecurseSubDirs = %d)\n", BasePathName, RecurseSubDirs);
while (TRUE)
{
IsDirectory = pDirectory->BasePath.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
FileExtension = strrchr(Filename, '.');
// Match if the currently found item is a subdirectory and recursion is enabled
if (IsDirectory && RecurseSubDirs && *Filename != '.')
{
_snprintf(tmpSubDir, sizeof(tmpSubDir), "%s\\%s", BasePathName, Filename);
if (!(pNewDirectory = DirectoryOpen(tmpSubDir, TRUE))) return FALSE;
if (!(DirectorySearch(pNewDirectory, FileWildcard))) return FALSE;
if (!MergeSearchResults(pDirectory, pNewDirectory)) return FALSE;
DirectoryClose(pNewDirectory);
}
// Try to match the current file to a wildcard or filename
else if (!IsDirectory)
{
//printf("Found %s\\%s\n", BasePathName, Filename);
if (MatchAllFiles)
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
}
else if (FileExtension)
{
FileExtension++; // point to one byte past "." (the file extension)
for (i = 0; i < WildcardCount; i++)
{
if (Wildcards[i][0] == '*')
{
if (!Wildcards[i][1] || Wildcards[i][2] == '*')
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
else if (Wildcards[i][2] && IsSameExtension(FileExtension, Wildcards[i] + 2))
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
}
else if (IsSameExtension(Filename, Wildcards[i]))
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
}
}
else
{
for (i = 0; i < WildcardCount; i++)
{
if (Wildcards[i][0] == '*' && Wildcards[i][1] == '.' && !Wildcards[i][2])
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
else if (IsSameExtension(Filename, Wildcards[i])) // match file
{
if (!AddFileToSearchResult(pDirectory, BasePathName, Filename)) return FALSE;
break;
}
}
}
}
if (!FindNextFile(pDirectory->hFileList, &pDirectory->BasePath))
{
if (GetLastError() == ERROR_NO_MORE_FILES) break;
fprintf(stderr, "FindNextFile failed: error code 0x%08lx\n", GetLastError());
return FALSE;
}
}
pDirectory->Finished = TRUE;
return TRUE;
}
PSEARCH_RESULTS GetLastSearchResult(PSEARCH_RESULTS pSearchResult)
{
while (pSearchResult && pSearchResult->Next) pSearchResult = pSearchResult->Next;
return pSearchResult;
}
BOOL AddFileToSearchResult(PDIRECTORY_INFO pDirectory, char *BasePathName, char *Filename)
{
DWORD PathLength;
PSEARCH_RESULTS pSearchResults;
////////////////////////////////////////////////////////////////
// Allocate a new search result set or append to an existing one
if (!pDirectory->pSearchResults)
{
pSearchResults = pDirectory->pSearchResults = malloc(sizeof(SEARCH_RESULTS));
if (!pSearchResults)
{
fprintf(stderr, "Error allocating %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pSearchResults->Previous = NULL;
}
else // an existing entry
{
pSearchResults = GetLastSearchResult(pDirectory->pSearchResults);
if (!(pSearchResults->Next = malloc(sizeof(SEARCH_RESULTS))))
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pSearchResults->Next->Previous = pSearchResults;
pSearchResults = pSearchResults->Next;
}
pSearchResults->Next = NULL;
////////////////////////////////////////////////////////////////
// Save path to filename for the search result
PathLength = strlen(pDirectory->BasePathName) + strlen(Filename) + 2;
if (PathLength > MAX_PATH)
{
fprintf(stderr, "Error: File path is too large\n");
return FALSE;
}
if (!(pSearchResults->FilePath = (char *)malloc(PathLength)))
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", PathLength);
return FALSE;
}
sprintf(pSearchResults->FilePath, "%s\\%s", BasePathName, Filename);
//printf("Added %s\n", pSearchResults->FilePath);
return TRUE;
}
BOOL MergeSearchResults(PDIRECTORY_INFO pBaseDir, PDIRECTORY_INFO pSubDir)
{
DWORD PathLength;
PSEARCH_RESULTS pDestination, pSource;
if (!pBaseDir || !pSubDir) return FALSE;
pSource = pSubDir->pSearchResults;
if (!pSource) return TRUE; // subdirectory is empty (don't merge)
assert(pSource->Previous == NULL);
if (!pBaseDir->pSearchResults) // merge subdirectory into empty result set
{
pDestination = pBaseDir->pSearchResults = malloc(sizeof(SEARCH_RESULTS));
if (!pDestination)
{
fprintf(stderr, "Error allocating %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pDestination->Previous = NULL;
pDestination->Next = NULL;
}
else // merge subdirectory with an existing result set
{
assert(pBaseDir->pSearchResults->Previous == NULL);
pDestination = GetLastSearchResult(pBaseDir->pSearchResults);
pDestination->Next = malloc(sizeof(SEARCH_RESULTS));
if (!pDestination->Next)
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pDestination->Next->Previous = pDestination;
pDestination = pDestination->Next;
pDestination->Next = NULL;
}
while (TRUE)
{
assert(pSource->FilePath != NULL);
PathLength = strlen(pSource->FilePath) + 1;
if (!(pDestination->FilePath = (char *)malloc(PathLength)))
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", PathLength);
return FALSE;
}
strcpy(pDestination->FilePath, pSource->FilePath);
//printf("Merged %s\n", pDestination->FilePath);
pSource = pSource->Next;
if (!pSource) break;
pDestination->Next = malloc(sizeof(SEARCH_RESULTS));
if (!pDestination->Next)
{
fprintf(stderr, "Error: unable to allocate %d bytes\n", sizeof(SEARCH_RESULTS));
return FALSE;
}
pDestination->Next->Previous = pDestination;
pDestination = pDestination->Next;
pDestination->Next = NULL;
}
//printf("New base directory contains:\n");
//DumpSearchResults(pSubDir->pSearchResults);
return TRUE;
}
DWORD GetSearchResultCount(PSEARCH_RESULTS pSearchResult)
{
DWORD Count = 0;
if (!pSearchResult) return 0;
while (pSearchResult && pSearchResult->Next)
{
pSearchResult = pSearchResult->Next;
Count++;
}
return Count + 1;
}
void DumpSearchResults(PSEARCH_RESULTS pSearchResults)
{
PSEARCH_RESULTS tmpResult;
if (!pSearchResults) return;
printf("Total records: %d\n", GetSearchResultCount(pSearchResults));
for (tmpResult = pSearchResults; tmpResult; tmpResult = tmpResult->Next)
{
if (tmpResult->FilePath) printf("\t%s\n", tmpResult->FilePath);
}
}

Просмотреть файл

@ -1,23 +1,23 @@
#ifndef DIRECTORY_H
#define DIRECTORY_H
typedef struct _DIRECTORY_INFO {
HANDLE hFileList;
BOOL Initialized;
BOOL Finished;
BOOL RecurseSubDirs;
char BasePathName[MAX_PATH+1];
WIN32_FIND_DATA BasePath; // do not reference this
struct _SEARCH_RESULTS *pSearchResults; // use this!
} DIRECTORY_INFO, *PDIRECTORY_INFO;
typedef struct _SEARCH_RESULTS {
struct _SEARCH_RESULTS *Previous, *Next;
char *FilePath;
} SEARCH_RESULTS, *PSEARCH_RESULTS;
PDIRECTORY_INFO DirectoryOpen(char *Directory, BOOL RecurseSubDirs);
BOOL DirectorySearch(PDIRECTORY_INFO pDirectory, char *FileWildcard);
void DirectoryClose(PDIRECTORY_INFO pDirectory);
#endif // DIRECTORY_H
#ifndef DIRECTORY_H
#define DIRECTORY_H
typedef struct _DIRECTORY_INFO {
HANDLE hFileList;
BOOL Initialized;
BOOL Finished;
BOOL RecurseSubDirs;
char BasePathName[MAX_PATH+1];
WIN32_FIND_DATA BasePath; // do not reference this
struct _SEARCH_RESULTS *pSearchResults; // use this!
} DIRECTORY_INFO, *PDIRECTORY_INFO;
typedef struct _SEARCH_RESULTS {
struct _SEARCH_RESULTS *Previous, *Next;
char *FilePath;
} SEARCH_RESULTS, *PSEARCH_RESULTS;
PDIRECTORY_INFO DirectoryOpen(char *Directory, BOOL RecurseSubDirs);
BOOL DirectorySearch(PDIRECTORY_INFO pDirectory, char *FileWildcard);
void DirectoryClose(PDIRECTORY_INFO pDirectory);
#endif // DIRECTORY_H

Просмотреть файл

@ -1,30 +1,30 @@
#include <windows.h>
#include <stdio.h>
#include "image.h"
PIMAGE_SECTION_HEADER GetSection(LOADED_IMAGE Image, DWORD RVA)
{
DWORD i;
PIMAGE_SECTION_HEADER pSection;
for (i = 0, pSection = Image.Sections; i < Image.NumberOfSections; i++, pSection++)
{
if (RVA >= pSection->VirtualAddress &&
RVA < pSection->VirtualAddress + pSection->Misc.VirtualSize)
{
return pSection;
}
}
return NULL;
}
BYTE *GetAddressFromRVA(LOADED_IMAGE Image, DWORD RVA)
{
int delta;
PIMAGE_SECTION_HEADER pSection;
if (!(pSection = GetSection(Image, RVA))) return NULL;
delta = (int)(pSection->VirtualAddress - pSection->PointerToRawData);
return (BYTE *)Image.MappedAddress + RVA - delta;
}
#include <windows.h>
#include <stdio.h>
#include "image.h"
PIMAGE_SECTION_HEADER GetSection(LOADED_IMAGE Image, DWORD RVA)
{
DWORD i;
PIMAGE_SECTION_HEADER pSection;
for (i = 0, pSection = Image.Sections; i < Image.NumberOfSections; i++, pSection++)
{
if (RVA >= pSection->VirtualAddress &&
RVA < pSection->VirtualAddress + pSection->Misc.VirtualSize)
{
return pSection;
}
}
return NULL;
}
BYTE *GetAddressFromRVA(LOADED_IMAGE Image, DWORD RVA)
{
int delta;
PIMAGE_SECTION_HEADER pSection;
if (!(pSection = GetSection(Image, RVA))) return NULL;
delta = (int)(pSection->VirtualAddress - pSection->PointerToRawData);
return (BYTE *)Image.MappedAddress + RVA - delta;
}

Просмотреть файл

@ -1,8 +1,8 @@
#ifndef IMAGE_H
#define IMAGE_H
#include <imagehlp.h>
PIMAGE_SECTION_HEADER GetSection(LOADED_IMAGE Image, DWORD RVA);
BYTE *GetAddressFromRVA(LOADED_IMAGE Image, DWORD RVA);
#ifndef IMAGE_H
#define IMAGE_H
#include <imagehlp.h>
PIMAGE_SECTION_HEADER GetSection(LOADED_IMAGE Image, DWORD RVA);
BYTE *GetAddressFromRVA(LOADED_IMAGE Image, DWORD RVA);
#endif // IMAGE_H

Просмотреть файл

@ -1,124 +0,0 @@
# Microsoft Developer Studio Project File - Name="w00depends" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=w00depends - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "w00depends.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "w00depends.mak" CFG="w00depends - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "w00depends - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "w00depends - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "w00depends - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib imagehlp.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "w00depends - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /YX /Yc /Yu
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib imagehlp.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "w00depends - Win32 Release"
# Name "w00depends - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\directory.c
# End Source File
# Begin Source File
SOURCE=.\image.c
# End Source File
# Begin Source File
SOURCE=.\w00depends.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\directory.h
# End Source File
# Begin Source File
SOURCE=.\image.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\ReadMe.txt
# End Source File
# End Target
# End Project

Просмотреть файл

@ -1,29 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "w00depends"=.\w00depends.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################