Доброго времени суток. Решаю следующую задачу: Необходимо в одном драйвере объявить несколько глобальных экспортируемых переменных. Значения для этих переменных задаются в этом же драйвере. Затем из другого драйвера получить и изменить значение этих переменных. Использование IRP-пакетов и dll не подходит! (таково условие). Я понимаю, что условие необычно, но что поделаешь Что касается объявления, полагаю, что необходимо использовать __declspec, но как второй драйвер получит адрес переменой? Заранее признателен за помощь!
Слушайте, я может немного туплю, - вот взять минипорты/протоколы, - они же как-то получают импорты от ндиса? Более того, я видел например коммуникации по экспортам в Tcpip.sys, afd.sys и т.д. Может имеет смысл держать первый драйвер по приоритету "более раннезугружаемым", а второй собрать с либой на экспорты первого?
Все эти приоритеты штука тонкая, иногда тупо подгадывать приходится. Гораздо проще реализовать схему, при которой второй драйвер в момент вызовать определённой функциональности будет проверять наличие первого и разбирать таблицу экспорта при необходимости. Ну а если первый ещё не загружен, возвращать STATUS_DEVICE_NOT_READY, вот и всё, чего тут думать-то. Между прочим, первый можно и по требованию загрузить через ZwLoadDriver().
Решил попробовать сделать по вашему совету. http://www.programingreference.com/...2000-secrets-the-translation-of-chapter-vi-6/ Вот пример исходника на эту тему.
Скорее имелось ввиду ZwQuerySystemInformation + SYSTEM_MODULES_INFORMATION, и реализовать свою GetProcAddress
J0E Да, ошибся и дал неправильную ссылку. Вот более верная: http://www.programingreference.com/...2000-secrets-the-translation-of-chapter-vi-3/
Вот пример, работающего кода ринг 0, который позволяет находить экспортируемые переменные для любого драйвера: Код (Text): #include <ntifs.h> #include <ntddk.h> #include <ntimage.h> #include <stdlib.h> typedef ULONG DWORD; typedef DWORD *PDWORD; typedef USHORT WORD; typedef WORD *PWORD; typedef UCHAR BYTE; typedef BYTE *PBYTE; typedef PVOID *PPVOID; typedef struct _MODULE_INFO { DWORD dReserved1; DWORD dReserved2; PVOID pBase; DWORD dSize; DWORD dFlags; WORD wIndex; WORD wRank; WORD wLoadCount; WORD wNameOffset; BYTE abPath [MAXIMUM_FILENAME_LENGTH]; }MODULE_INFO, *PMODULE_INFO , ** PPMODULE_INFO; #define MODULE_INFO_ sizeof (MODULE_INFO) typedef struct _MODULE_LIST { DWORD dModules; MODULE_INFO aModules []; } MODULE_LIST, *PMODULE_LIST , ** PPMODULE_LIST; #define MODULE_LIST_ sizeof (MODULE_LIST) #define min(_a,_b) (((_a) < (_b)) ? (_a) : (_b)) #define max(_a,_b) (((_a) > (_b)) ? (_a) : (_b)) #define SPY_TAG 3 // SPY> #define PTR_ADD(_base,_offset) \ ((PVOID) ((PBYTE) (_base) + (DWORD) (_offset))) #define SystemModuleInformation 11 // SYSTEMINFOCLASS NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(IN PVOID ModuleAddress); typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation = 0, SystemPerformanceInformation = 2, SystemTimeOfDayInformation = 3, SystemProcessInformation = 5, SystemProcessorPerformanceInformation = 8, SystemInterruptInformation = 23, SystemExceptionInformation = 33, SystemRegistryQuotaInformation = 37, SystemLookasideInformation = 45 } SYSTEM_INFORMATION_CLASS; NTSYSAPI NTSTATUS NtQuerySystemInformation ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL ); /*---prototypes of function---*/ NTSTATUS UnloadDriver( PDRIVER_OBJECT DriverObject ); NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath ); /*---functions---*/ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////PMODULE_LIST //выделение памяти PVOID SpyMemoryCreate( DWORD dSize ) { return ExAllocatePool(PagedPool, max(dSize, 1)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////PMODULE_LIST //обнуление PVOID SpyMemoryDestroy( PVOID pData ) { if (pData != NULL) ExFreePool (pData); return NULL; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////PMODULE_LIST PMODULE_LIST SpyModuleList ( PDWORD pdData, PNTSTATUS pns ) { DWORD dSize; DWORD dData = 0; NTSTATUS ns = STATUS_INVALID_PARAMETER; PMODULE_LIST pml = NULL; for (dSize = 0x10000; ((pml == NULL) && dSize); dSize <<= 1) { if ((pml = SpyMemoryCreate (dSize)) == NULL) { ns = STATUS_NO_MEMORY; break; } ns = NtQuerySystemInformation (SystemModuleInformation, pml, dSize, &dData); if (ns != STATUS_SUCCESS) { pml = SpyMemoryDestroy (pml); dData = 0; if (ns != STATUS_INFO_LENGTH_MISMATCH) break; } } if (pdData!= NULL) *pdData = dData; if (pns!= NULL) *pns = ns; return pml; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////PMODULE_LIST PMODULE_LIST SpyModuleFind ( PBYTE pbModule, PDWORD pdIndex, PNTSTATUS pns ) { DWORD i; DWORD dIndex = -1; NTSTATUS ns = STATUS_INVALID_PARAMETER; PMODULE_LIST pml = NULL; if ((pml = SpyModuleList (NULL, &ns))!= NULL) { for (i = 0; i < pml->dModules; i++) { if (!strstr(pml->aModules[i].abPath,pbModule)) { dIndex = i; break; } } if (dIndex == -1) { pml = SpyMemoryDestroy (pml); ns = STATUS_NO_SUCH_FILE; } } if (pdIndex != NULL) *pdIndex = dIndex; if (pns != NULL) *pns = ns; return pml; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PVOID SpyModuleBase( PBYTE pbModule, PNTSTATUS pns ) { PMODULE_LIST pml; DWORD dIndex; NTSTATUS ns = STATUS_INVALID_PARAMETER; PVOID pBase = NULL; if ((pml = SpyModuleFind(pbModule, &dIndex, &ns))!= NULL) { pBase = pml->aModules[dIndex].pBase; SpyMemoryDestroy (pml); } if (pns!= NULL) *pns = ns; return pBase; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PIMAGE_NT_HEADERS SpyModuleHeader ( PBYTE pbModule, PPVOID ppBase, PNTSTATUS pns ) { PVOID pBase = NULL; NTSTATUS ns = STATUS_INVALID_PARAMETER; PIMAGE_NT_HEADERS pinh = NULL; if (((pBase = SpyModuleBase(pbModule,&ns))!= NULL) && ((pinh = RtlImageNtHeader(pBase)) == NULL)) { ns = STATUS_INVALID_IMAGE_FORMAT; } if (ppBase != NULL) *ppBase = pBase; if (pns!= NULL) *pns = ns; return pinh; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PIMAGE_EXPORT_DIRECTORY SpyModuleExport ( PBYTE pbModule, PPVOID ppBase, PNTSTATUS pns ) { PIMAGE_NT_HEADERS pinh; PIMAGE_DATA_DIRECTORY pidd; PVOID pBase = NULL; NTSTATUS ns = STATUS_INVALID_PARAMETER; PIMAGE_EXPORT_DIRECTORY pied = NULL; if ((pinh = SpyModuleHeader(pbModule, & pBase, & ns))!= NULL) { pidd = pinh->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT; if (pidd->VirtualAddress && (pidd->Size >= sizeof(IMAGE_EXPORT_DIRECTORY))) { pied = PTR_ADD(pBase,pidd->VirtualAddress); } else { ns = STATUS_DATA_ERROR; } } if (ppBase != NULL) *ppBase = pBase; if (pns != NULL) *pns = ns; return pied; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PVOID SpyModuleSymbol ( PBYTE pbModule, PBYTE pbName, PPVOID ppBase, PNTSTATUS pns ) { PIMAGE_EXPORT_DIRECTORY pied; PDWORD pdNames, pdFunctions; PWORD pwOrdinals; DWORD i, j; PVOID pBase = NULL; NTSTATUS ns = STATUS_INVALID_PARAMETER; PVOID pAddress = NULL; if ((pied = SpyModuleExport(pbModule, &pBase, &ns))!= NULL) { pdNames = PTR_ADD (pBase, pied->AddressOfNames); pdFunctions = PTR_ADD (pBase, pied->AddressOfFunctions); pwOrdinals = PTR_ADD (pBase, pied->AddressOfNameOrdinals); for (i = 0; i <pied->NumberOfNames; i++) { j = pwOrdinals[i]; if (!strcmp((PTR_ADD(pBase,pdNames [i])), pbName)) { if (j <pied->NumberOfFunctions) { pAddress = PTR_ADD (pBase, pdFunctions [j]); } break; } } if (pAddress == NULL) { ns = STATUS_PROCEDURE_NOT_FOUND; } } if (ppBase != NULL) *ppBase = pBase; if (pns != NULL) *pns = ns; return pAddress; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// PVOID SpyModuleSymbolEx( PBYTE pbSymbol, PPVOID ppBase, PNTSTATUS pns) { DWORD i; BYTE abModule [MAXIMUM_FILENAME_LENGTH] = "ntkrpamp.exe"; PBYTE pbName = pbSymbol; PVOID pBase = NULL; NTSTATUS ns = STATUS_INVALID_PARAMETER; PVOID pAddress = NULL; for (i = 0; ((pbSymbol[i])&&(pbSymbol[i]!= '!')); i ++); if (pbSymbol[i++]) { if (i <= MAXIMUM_FILENAME_LENGTH) { strncpy (abModule, pbSymbol, i); pbName = pbSymbol += i; } else { pbName = NULL; } } if (pbName != NULL) { pAddress = SpyModuleSymbol (abModule, pbName, &pBase, &ns); } if (ppBase != NULL) * ppBase = pBase; if (pns != NULL) * pns = ns; return pAddress; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*DriverEntry*/ NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath ) { PDWORD pKeServiceDescriptorTable; UNICODE_STRING us; NTSTATUS ns; RtlInitUnicodeString(&us,L"NtOpenFile"); pDriverObject->DriverUnload = UnloadDriver; DbgPrint("Driver load\n"); pKeServiceDescriptorTable = SpyModuleSymbolEx("NtOpenFile", NULL, &ns); if (ns == STATUS_SUCCESS) { DbgPrint("NtOpenFile <%p>\n",pKeServiceDescriptorTable); } pKeServiceDescriptorTable = MmGetSystemRoutineAddress(&us); if (pKeServiceDescriptorTable!= 0){ DbgPrint("NtOpenFile <%p>\n",pKeServiceDescriptorTable); } return STATUS_SUCCESS; } /*DriverUnload*/ NTSTATUS UnloadDriver( PDRIVER_OBJECT DriverObject ) { DbgPrint("Driver unload\n"); return STATUS_SUCCESS; }
В приведенном выше примере с помощью системной функции MmGetSystemRoutineAddress и не системной SpyModuleSymbolEx, определяется адрес сервиса NtOpenFile. Всем спасибо, тема закрыта.