• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Получение версии ОС Windows через ключи системного реестра.

varwar

El Diff
Забанен
Регистрация
12.11.2020
Сообщения
1 383
Решения
5
Реакции
1 537
Пожалуйста, обратите внимание, что пользователь заблокирован

Введение​

В этой статье я хотел бы рассмотреть один из способов получения информации об операционной системе через ключи реестра Windows в пользовательском режиме (ring 3), однако, аналогичным образом могут быть получены данные и в режиме ядра (ring 0).

Известно, что поля MajorVersion, MinorVersion и BuildNumber могут быть извлечены напрямую из структуры _PEB или через вызов RtlGetVersion в режиме ядра, которая, в свою очередь, возвращает указатель на структуру _OSVERSIONINFO. Эта информация может быть использована при разработке эксплойтов или какого-либо легитимного ПО. Особенно справедливо это для версий Windows 10, Windows Server 2016/2019, которые имеют дополнительное поле UBR (Update Build Revision), не представленное структурой _PEB. Например, если вы разрабатываете эксплойт для CVE-2020-17087, то из двух версий ОС 19042.542 и 19042.630 уязвимой будет только первая. Следовательно, проверки по BuildNumber недостаточно и желательно дополнительно проверять поле UBR. Это будет надежнее, т. к., отпадает вероятность попытки эксплуатации пропатченного билда. Безусловно, есть и другие способы, основанные на проверке версии файлов, но в этой статье мы их не будем рассматривать.

Ключи реестра​

Для наших целей может подойти два ключа:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
и
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion.

Оба ключа идентичны с той лишь разницей, что второй используется как редиректор на 64-битных системах. Например, когда 32-битное приложение читает значение ключа из HKEY_LOCAL_MACHINE\SOFTWARE\<компания>\<продукт>, то оно в действительности его получает из HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\<компания>\<продукт>.

В качестве тестируемых значений мы попробуем получить данные полей CurrentMajorVersionNumber, CurrentMinorVersionNumber, CurrentBuild и UBR.

Поля ключа HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion


Функции RegOpenKeyEx и RegQueryValueEx​

В качестве кандидатов для выполнения нашей задачи нам потребуются Windows API RegOpenKeyEx и RegQueryValueEx.

Прототип функций выглядит следующим образом:

Код:
LSTATUS RegOpenKeyExA(

    HKEY hKey,

    LPCSTR lpSubKey,

    DWORD ulOptions,

    REGSAM samDesired,

    PHKEY phkResult
);

LSTATUS RegQueryValueExA(

    HKEY hKey,

    LPCSTR lpValueName,

    LPDWORD lpReserved,

    LPDWORD lpType,

    LPBYTE lpData,

    LPDWORD lpcbData
);


Сам код довольно примитивный и не требует дополнительных разъяснений.
C:
#include <windows.h>
#include <winreg.h>
#include <stdio.h>

extern "C"
int ShowWindVer()
{
    // Объявлям переменные типа DWORD, которые будут хранить необходимые значения.
    // Поскольку запись реестра CurrentBuild имеет тип REG_SZ, то
    // результат мы сохраняем в массив
    DWORD mj_ver, min_ver, ubr, dwType, size;
    BYTE cur_build[256];
    HKEY hKey;
    LSTATUS retValue;
    LPCSTR lpSubkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";

    // Открываем хэндл ключа для чтения
    retValue = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
                            lpSubkey,
                            NULL,
                            KEY_QUERY_VALUE,
                            &hKey);
    // Проверяем возвращаемое значение
    if (ERROR_SUCCESS != retValue) {
        printf("RegOpenKeyEx err=%ld\n", retValue);
        return 1;
    }
    // Получаем значение CurrentMajorVersionNumber
    size = sizeof(DWORD);
    retValue = RegQueryValueExA(hKey,
                                "CurrentMajorVersionNumber",
                                NULL,
                                &dwType,
                                (LPBYTE)&mj_ver,
                                &size);
 
    if (ERROR_SUCCESS != retValue) {
        printf("MajorVersion err=%ld\n", retValue);
        return 1;
    }
 
    // Получаем значение CurrentMinorVersionNumber
    size = sizeof(DWORD);
    retValue = RegQueryValueExA(hKey,
                                "CurrentMinorVersionNumber",
                                NULL,
                                &dwType,
                                (LPBYTE)&min_ver,
                                &size);
 
    if(ERROR_SUCCESS != retValue) {
        printf("MinorVersion err=%ld\n", retValue);
        return 1;
    }

    // Получаем значение CurrentBuild
    memset(cur_build, 0, sizeof(cur_build));
    size = sizeof(cur_build);
    retValue = RegQueryValueExA(hKey,
                                "CurrentBuild",
                                NULL,
                                &dwType,
                                (LPBYTE)&cur_build,
                                &size);

    if (ERROR_SUCCESS != retValue) {
        printf("CurrentBuild err=%ld", retValue);
        return 1;
        // Обрабатываем ERROR_MORE_DATA при необходимости
        // ...
    }

    // Получаем значение UBR
    size = sizeof(DWORD);
    retValue = RegQueryValueExA(hKey,
                                "UBR",
                                NULL,
                                &dwType,
                                (LPBYTE)&ubr,
                                &size);

    if (ERROR_SUCCESS != retValue) {
        printf("UBR err=%ld", retValue);
        return 1;
    }

    // Выводим результат
    printf("The Windows version is: %d.%d.%s.%d\n",
            mj_ver,
            min_ver,
            cur_build,
            ubr);
 
    size = 0;
    memset(cur_build, 0, sizeof(cur_build));
    RegCloseKey(hKey);
    return 0;
}

extern "C"
int main()
{
    ShowWindVer();
}

Любые замечания, идеи и вопросы прошу оставлять в комментариях.
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх