Стоит задача заставить работать одну прожку под всеми виндами, т.к. работает она только под серверными виндами, под другими версиями выскакивает окно и работа прекращается. Но не хотелось бы юзать внедрение кода и перехват GetVersionEx , хочу решить задачу через патч PEB , но столкнулся со сложностью и сейчас думаю возможно ли так вообще решить задачу, т.к. определение винды происходит по 3 полям структуры osversionex Код (Text): if ( osvi.dwMajorVersion == 6 ) { if( osvi.dwMinorVersion == 0 ) { if( osvi.wProductType == VER_NT_WORKSTATION ) StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista ")); else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " )); } MajorVersion и MinorVersion легко подменить в PEB , а вот ProductType реально ли ? для win7 значение наиболее интересных полей следующее: Код (Text): peb->NtMajorVersion = 6; peb->NtMinorVersion = 1; peb->NtBuildNumber = 7601; peb->NtCSDVersion = 256; peb->PlatformId = 2; peb->Subsystem = 2; peb->MajorSubsystemVersion = 5; peb->MinorSubsystemVersion = 1; peb->AffinityMask = 3;
productType берется из USER_SHARED_DATA. значения которые в пеб заполняются, скорее всего тоже оттуда, для изменения этой памяти нужен драйвер. либо для вашего случая - перехват GetVersionExW
нашел таки способ обойтись без перехвата - патчем вызываемой итоговой ntdll фунцкии, способ не очень, конечно, но в рамках моей проблемы меня устраивает. Заметил что реальный результат берется из DWORD PTR DS:[7FFE0264] на всех виндах по одинаковому смещению , 7FFE000 это я так понимаю и есть usersharedata интересует почему не совпадают peb->NtMajorVersion = 6; и peb->MajorSubsystemVersion = 5; а также что означают поля peb->Subsytem peb->NtCSDVersion peb->AffinityMask
можно использовать appverif для подмены ProductType. например в серверной системе (windows 2008 r2) не отображается опция Сон в Пуске, а после подмены для explorer.exe она появляется. все еще некоторые программы требуют клиентской ОС для установки.. есть ли решение этой проблемы для системы в целом?
Код (C): BOOLEAN RtlGetNtProductType( OUT PNT_PRODUCT_TYPE NtProductType ) /*++ Routine Description: Returns the product type of the current system. Arguments: NtProductType - Returns the product type. Either NtProductWinNt or NtProductLanManNt. Return Value: TRUE on success, FALSE on failure The product type will be set to WinNt on failure --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE KeyHandle; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; ULONG KeyValueInfoLength; ULONG ResultLength; UNICODE_STRING KeyPath; UNICODE_STRING ValueName; UNICODE_STRING Value; UNICODE_STRING WinNtValue; UNICODE_STRING LanmanNtValue; UNICODE_STRING ServerNtValue; BOOLEAN Result; RTL_PAGED_CODE(); // // if we are in gui setup mode, product type is read from the registry since // gui setup mode is the only time product type can be changed. // All other times, the "captured at boot" version of product type is used // if ( USER_SHARED_DATA->ProductTypeIsValid ) { *NtProductType = USER_SHARED_DATA->NtProductType; return TRUE; } // // Prepare default value for failure case // *NtProductType = NtProductWinNt; Result = FALSE; RtlInitUnicodeString( &KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ProductOptions" ); RtlInitUnicodeString( &ValueName, L"ProductType" ); InitializeObjectAttributes( &ObjectAttributes, &KeyPath, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenKey( &KeyHandle, MAXIMUM_ALLOWED, &ObjectAttributes ); KeyValueInformation = NULL; if (NT_SUCCESS( Status )) { KeyValueInfoLength = 256; KeyValueInformation = RtlAllocateHeap( RtlProcessHeap(), 0, KeyValueInfoLength ); if (KeyValueInformation == NULL) { Status = STATUS_NO_MEMORY; } else { Status = NtQueryValueKey( KeyHandle, &ValueName, KeyValueFullInformation, KeyValueInformation, KeyValueInfoLength, &ResultLength ); } } else { KeyHandle = NULL; } if (NT_SUCCESS( Status ) && KeyValueInformation->Type == REG_SZ) { // // Decide which product we are installed as // Value.Buffer = (PWSTR)((PCHAR)KeyValueInformation + KeyValueInformation->DataOffset); Value.Length = (USHORT)(KeyValueInformation->DataLength - sizeof( UNICODE_NULL )); Value.MaximumLength = (USHORT)(KeyValueInformation->DataLength); RtlInitUnicodeString(&WinNtValue, L"WinNt"); RtlInitUnicodeString(&LanmanNtValue, L"LanmanNt"); RtlInitUnicodeString(&ServerNtValue, L"ServerNt"); if (RtlEqualUnicodeString(&Value, &WinNtValue, TRUE)) { *NtProductType = NtProductWinNt; Result = TRUE; } else if (RtlEqualUnicodeString(&Value, &LanmanNtValue, TRUE)) { *NtProductType = NtProductLanManNt; Result = TRUE; } else if (RtlEqualUnicodeString(&Value, &ServerNtValue, TRUE)) { *NtProductType = NtProductServer; Result = TRUE; } else { #if DBG DbgPrint("RtlGetNtProductType: Product type unrecognised <%wZ>\n", &Value); #endif // DBG } } else { #if DBG DbgPrint("RtlGetNtProductType: %wZ\\%wZ not found or invalid type\n", &KeyPath, &ValueName ); #endif // DBG } // // Clean up our resources. // if (KeyValueInformation != NULL) { RtlFreeHeap( RtlProcessHeap(), 0, KeyValueInformation ); } if (KeyHandle != NULL) { NtClose( KeyHandle ); } // // Return result. // return(Result);
Indy, мне нужно подменить ProductType для любой устанавливаемой программы (exe) или установочного пакета (msi), а не получить информацию о текущем состоянии.
determin1st, Тоесть вам имени ключа не достаточно, оно автоматикой красным цветом даже выделено. Если это не сработает, то значит данная инфа зашита в виде константы в ядро.
Если изменить значение в реестре, то через секунду оно возвращается в первоначальное состояние. Отладка не моя специализация. в скудной документации по Application Verifier ничего особо не написано.. вот это найдено в интернете:
determin1st, Измените и ребутнитесь. Если даже и восстанавливается значение, то верифер это юзер механизм. Тогда можно права доступа к ключу поменять, либо есчо как то отключить изменение ключа. Хотя вы правы, это нужно отлаживать. Кстате верифер просто так не запускается.
Indy_, еще раз, значение меняется, но тут же возвращается в исходное. скорее всего это сделано для защиты (финансовой) самой микрософт и тех кто с ней сотрудничает, очередная палка в колесо обычным пользователям(
determin1st, Зачем вы повторяете, я понял сразу. Используйте системный монитор что бы узнать источник изменений, у Руссиновича были и у мс тоже. Что бы избежать необходимости использовать виндебаг.
determin1st, Я не знаю, я не смотрел, но описал как это сделать. Запустите монитор и посмотрите. Система изменяется и что бы решить задачу нужна куча времени, софта. Сурки же старые - w2k, но судя по нт 10-ки(у меня открыто всегда идой) процедура неизменна.