Поигравшись с процессами и файлами перешел к реестру. Поставил задачу: скрыть раздел с заданным именем. Как я понимаю, алгоритм следующий: перехватить NtEnumerateKey, в перехватчике получить имя раздела по его Index (второй параметр NtEnumerateKey), если имя равно заданному, вместо вызова NtEnumerateKey c заданным Index вызвать c Index+1 (будем считать, что имя раздела уникально). Но TrueEnumerateKey(hKey, Index, 0, &Buff, 512, &dwTemp) (Buff - это буфер для структуры KEY_BASIC_INFORMATION) возвращает STATUS_ACCESS_VIOLATION. Помогите пожалуйста, я в панике )).
pObjectNames - юникодный массив с именами ключей, которые нужно скрыть. nkeys - количество элементов в массиве. Код (Text): NTSTATUS MyNtEnumerateKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG KeyInformationLength, OUT PULONG ResultLength) { NTSTATUS ns; UNICODE_STRING Name; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Key; ULONG i = 0, hkeysum = 0, id; BOOLEAN hideit; ns=NtEnumerateKey(KeyHandle,Index,KeyNameInformation, KeyInformation,KeyInformationLength,ResultLength); if (ns!=STATUS_SUCCESS) return ns; ObjectAttributes.Length=sizeof(OBJECT_ATTRIBUTES); ObjectAttributes.Attributes=OBJ_CASE_INSENSITIVE; ObjectAttributes.RootDirectory=KeyHandle; ObjectAttributes.SecurityDescriptor=NULL; ObjectAttributes.SecurityQualityOfService=NULL; RtlInitUnicodeString(&Name,KeyInformation->Name); while (i<nkeys) { ObjectAttributes.ObjectName=&pObjectNames[i]; if (NtOpenKey(&Key,KEY_ENUMERATE_SUB_KEYS,&ObjectAttributes)==STATUS_SUCCESS) { NtClose(Key); if (RtlCompareUnicodeString(&pObjectNames[i],&Name,TRUE)<=0) ++hkeysum; } ++i; } id=Index+hkeysum; if (id>Index) while (TRUE) { i=0; hideit=FALSE; ns=NtEnumerateKey(KeyHandle,id,KeyNameInformation, KeyInformation,KeyInformationLength,ResultLength); if (ns!=STATUS_SUCCESS) return ns; RtlInitUnicodeString(&Name,KeyInformation->Name); while (i<nkeys) { ObjectAttributes.ObjectName=&pObjectNames[i]; if (NtOpenKey(&Key,KEY_ENUMERATE_SUB_KEYS,&ObjectAttributes)==STATUS_SUCCESS) { NtClose(Key); if (!RtlCompareUnicodeString(&pObjectNames[i],&Name,TRUE)) { hideit=TRUE; break; } } ++i; } if (!hideit) break; ++id; } return NtEnumerateKey(KeyHandle,id,KeyInformationClass, KeyInformation,KeyInformationLength,ResultLength); }
Пример обработчика скрывающего раздел начинающийся с "_": Код (Text): NTSTATUS NewNtEnumerateKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG KeyInformationLength, OUT PULONG ResultLength ) { Result=TrueNtEnumerateKey(KeyHandle,Index,KeyInformationClass,KeyInformation,KeyInformationLength,ResultLength); switch(KeyInformationClass) { case KeyBasicInformation: if(((PKEY_BASIC_INFORMATION)KeyInformation)->Name[0]==0x5F) return STATUS_OBJECT_NAME_NOT_FOUND; break; case KeyNodeInformation: if(((PKEY_NODE_INFORMATION)KeyInformation)->Name[0]==0x5F) return STATUS_OBJECT_NAME_NOT_FOUND; break; case KeyNameInformation: if(((PKEY_NAME_INFORMATION)KeyInformation)->Name[0]==0x5F) return STATUS_OBJECT_NAME_NOT_FOUND; break; } return Result; }
Код (Text): NTSTATUS NewEnumerateKey(HANDLE hKey, ULONG Index, ULONG KeyInfoClass, PVOID pKeyInfo, ULONG KeyInfoLen, PULONG ResultLen) { NTSTATUS st; ULONG dwTemp; UCHAR Buff[sizeof(KEY_BASIC_INFORMATION)+1024]; st = TrueEnumerateKey(hKey, Index, KeyBasicInformation, &Buff, sizeof(KEY_BASIC_INFORMATION)+1024, &dwTemp); DPRINT("TrueEnumerateKey returns 0x%08x", st); return TrueEnumerateKey(hKey, Index, KeyInfoClass, pKeyInfo, KeyInfoLen, ResultLen); } При первом вызове TrueEnumerateKey постоянно получаю 0xC0000005 == STATUS_ACCESS_VIOLATION. При этом regedit функционирует нормально. На всякий случай даже посмотрел ассемблерный листинг - все компилится все равно как если бы я тоже самое написал на асме. Что не так?
Точно! Вот вчера написал тоже самое и сидел парился почему не прячутся в записи в реестре. Потом посмотрел, а у меня даже дело до цикла не доходит. Не возвращается STATUS_SUCCESS при вызове TRUE функции с KeyBasicInformation. Пока не понял почему. А и ещё почему то при выгрузке драйвера BSOD c DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS. По ходу у меня что-то ещё выполняется а я его выгружаю. Не нашел что там ещё выполняется.
Твоя проблема заключается в том, что адреса аргументов передаваемых функции не соответствуют PreviousMode. Есть несколько путей решения этой проблемы. 1) Использовать Zw функцию вместо Nt, она сама устанавливает PreviousMode. Но в твоем случае это неприменимо, так как вызовет рекурсию. 2) Использовать для своих вызовов буфер переданый тебе из юзермода. 3) Создавать свой буфер, и мапить его в юзермод через mdl.
X_k >>DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS такая ошибка оычно появляется когда ты выгружаешь драйвер, не сняв хуки. PE386 Спасибо, буду думать.
Фу ну вот вроде всё сделал. Всё что надо скрывает. Всё что не надо не скрывает. Тока вот одна ерунда не могу зайти в некоторые разделы реестра при загруженном драйвере. Они просто не открываются. Ни у кого такой проблемы не было?
И вообще сейчас потестил дровина себя как то странно ведет. При запущенном драйвере у меня скрываются папки "Мои документы" и "Общие документы" Пропадает звук везде. Пишет Bad Direct Sound Driver. Ну там еще кое какие ярлыки не хотят работать. Што за бред?
Вот код если поможет: Код (Text): NTSTATUS Captured_NtEnumerateKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength ) { NTSTATUS Result; UNICODE_STRING usKeyName; UNICODE_STRING usKeyHide; OBJECT_ATTRIBUTES ObjectAttributes; KEY_BASIC_INFORMATION *lpKey; HANDLE hKey; ULONG dwTemp; BOOLEAN bIfHide = TRUE; //UCHAR Buff[sizeof(KEY_BASIC_INFORMATION)+1024]; int i; DPRINT( "Captured NtEnumerateKey function called\n" ); //lpKey=ExAllocatePool(PagedPool,sizeof(KEY_BASIC_INFORMATION)+1024); Result = True_NtEnumerateKey( KeyHandle, Index, KeyBasicInformation, KeyInformation, Length, ResultLength ); DPRINT("TrueEnumerateKey with KeyBasicInformation returns 0x%08x", Result); if ( Result != STATUS_SUCCESS ) return True_NtEnumerateKey( KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength ); lpKey = KeyInformation; usKeyName.Buffer = lpKey->Name; usKeyName.Length = usKeyName.MaximumLength = (USHORT) lpKey->NameLength; ObjectAttributes.Length=sizeof(OBJECT_ATTRIBUTES); ObjectAttributes.Attributes=OBJ_CASE_INSENSITIVE; ObjectAttributes.RootDirectory=KeyHandle; ObjectAttributes.SecurityDescriptor=NULL; ObjectAttributes.SecurityQualityOfService=NULL; for( i = 0; i != CAPREG_MAX_HIDE_SUBKEYS; i++ ) { usKeyHide.Buffer = wHideKeys[i]; usKeyHide.Length = usKeyHide.MaximumLength = (USHORT) wcslen(wHideKeys[i])*sizeof(WCHAR); ObjectAttributes.ObjectName=&usKeyHide; //InitializeObjectAttributes(&ObjectAttributes, &usKeyHide, OBJ_CASE_INSENSITIVE, NULL, NULL); Result = ZwOpenKey( &hKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes ); DPRINT("Result of open key is:%d\n",Result); if ( Result == STATUS_SUCCESS ) { ZwClose(hKey); if ( RtlCompareUnicodeString(&usKeyName, &usKeyHide, TRUE) >= 0 ) Index++; } } while (bIfHide) { Result = True_NtEnumerateKey( KeyHandle, Index, KeyBasicInformation, KeyInformation, Length, ResultLength ); if ( Result != STATUS_SUCCESS ) return STATUS_EA_LIST_INCONSISTENT; lpKey = KeyInformation; usKeyName.Buffer = lpKey->Name; usKeyName.Length = usKeyName.MaximumLength = (USHORT) lpKey->NameLength; for( i = 0; i != CAPREG_MAX_HIDE_SUBKEYS; i++ ) { usKeyHide.Buffer = wHideKeys[i]; usKeyHide.Length = usKeyHide.MaximumLength = (USHORT) wcslen(wHideKeys[i])*sizeof(WCHAR); if ( RtlCompareUnicodeString(&usKeyName, &usKeyHide, TRUE) == 0 ) { Index++; break; } } if ( i == CAPREG_MAX_HIDE_SUBKEYS) bIfHide = FALSE; } return True_NtEnumerateKey( KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength ); } тег code для кого придуман?
Код (Text): NTSTATUS NewEnumerateKey(HANDLE hKey, ULONG Index, ULONG KeyInfoClass, PVOID pKeyInfo, ULONG KeyInfoLen, PULONG ResultLen) { NTSTATUS st; ULONG dwTemp = 0; PMDL Mdl; PKEY_BASIC_INFORMATION pTmpKeyInfo; PVOID pTempBuff; PVOID pMapped; // _asm int 3 pTempBuff = ExAllocatePool(NonPagedPool, sizeof(KEY_BASIC_INFORMATION)+1024); Mdl = IoAllocateMdl(pTempBuff, sizeof(KEY_BASIC_INFORMATION)+1024, FALSE, FALSE, NULL); MmBuildMdlForNonPagedPool(Mdl); pMapped = MmMapLockedPages(Mdl, UserMode); pTmpKeyInfo = (PKEY_BASIC_INFORMATION)MmGetSystemAddressForMdl(Mdl); st = TrueEnumerateKey(hKey, Index, KeyBasicInformation, pTmpKeyInfo, sizeof(KEY_BASIC_INFORMATION)+1024, &dwTemp); DPRINT("EnumerateKey: 0x%08x", st); MmUnmapLockedPages(pMapped, Mdl); MmUnlockPages(Mdl); IoFreeMdl(Mdl); ExFreePool(pTempBuff); return TrueEnumerateKey(hKey, Index, KeyInfoClass, pKeyInfo, KeyInfoLen, ResultLen); } Получаю Bsod, Stop 4E: PFN_LIST_CORRUPT, притом он вылетает не с первого вызова моей функции потому где происходит ошибка сказать лично мне затруднительно. Я дурак, объясните что нет так.
drmist Мда, руки нужно срочно выпремлять. Код просто блещет багами. 1) pTmpKeyInfo = (PKEY_BASIC_INFORMATION)MmGetSystemAddressForMdl(Mdl); (а мапили то зачем спрашивается?) 2) MmMapLockedPages(Mdl, UserMode) (а если юзермода нет? например мы в system) 3) ULONG dwTemp = 0; (а указатель то в ядре) 4) MmUnlockPages(Mdl); (чето я не видел, чтобы страницы где-то блокировались) 5) А кто результаты всех этих функций проверять будет?? Имхо не пиши дрова, пожалей бедную винду )
PE386 Пока не буду. Сначал доку хорошую подыщу по работе с MDL и динамической памятью в ring0 (думаю, статьи Four-F подойдут), потом глядишь винда меня сама уговаривать будет, чтоб я под нее драйвер написал )) Не суди строго - я DDK неделю назад поставил.