Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Гайд [Сурс] TPM Spoofing — Обход HWID без хуков через подмену EK Hash

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
724
Реакции
18
Для тех, кто плотно сидит на HWID банах в Valorant или Apex и устал от бесконечных попыток скрыть свой TPM, есть интересная метода. Суть в том, что античиты (особенно Vanguard) не просто смотрят реестр, а лезут глубже через TBS API и WMI.

Данный подход позволяет запутать античит без использования классических хуков, которые легко детектятся. Мы просто находим, где в памяти лежат оригинальные идентификаторы, и затираем их рандомным мусором.

Как это работает:
  1. Вытягиваем оригинальный Endorsement Key (EK) Hash из реестра.
  2. Сканируем расширения объектов устройств (Device Extension) для драйверов tpm.sys, tbs.sys и ACPI.
  3. Заменяем все вхождения оригинального хеша на рандомные байты прямо в ядре.
  4. Подчищаем следы в реестре (ManufacturerId, ManufacturerVersion и WindowsAIKHash), чтобы WMI отдавал «правильные» данные.

Листинг реализации:
Код:
Expand Collapse Copy
//  Anti-cheats query TPM via:
//    - TBS API (TbsiGetDeviceInfo) → tbs.sys → tpm.sys
//    - WMI Win32_Tpm → tpm.sys WMI provider
//    - Registry TPM\WMI → EndorsementKeyHash, WindowsAIKHash
// approach:
//    1. Read original EK hash from registry
//    2. Scan tpm.sys + tbs.sys + ACPI device extensions for the hash
//    3. Replace all instances with random bytes
//    4. Update registry WMI values (backup layer)
 
 
void SpoofTpm()
{
    // Read original TPM EK hash from registry
    UCHAR origEkHash[32] = {};
    ULONG ekLen = 0;
    UCHAR spfEkHash[32];
    for (int i = 0; i < 32; i++) spfEkHash[i] = RandByte();
 
    RegGetBin(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet"
        L"\\Services\\TPM\\WMI", L"EndorsementKeyHash",
        origEkHash, sizeof(origEkHash), &ekLen);
 
    // ── Kernel Layer: Scan TPM driver extensions ──────────────────────
    if (ekLen >= 20) // SHA-1 (20) or SHA-256 (32)
    {
        const WCHAR* tpmDrivers[] = {
            L"\\Driver\\TPM",
            L"\\Driver\\tbs",
            L"\\Driver\\ACPI",   // TPM2.0 ACPI-enumerated
        };
 
        for (ULONG d = 0; d < ARRAYSIZE(tpmDrivers); d++)
        {
            UNICODE_STRING name; RtlInitUnicodeString(&name, tpmDrivers[d]);
            PDRIVER_OBJECT drv = nullptr;
            if (!NT_SUCCESS(ObReferenceObjectByName(&name, OBJ_CASE_INSENSITIVE,
                nullptr, 0, *IoDriverObjectType, KernelMode, nullptr, (PVOID*)&drv)))
                continue;
 
            PDEVICE_OBJECT dev = drv->DeviceObject;
            while (dev) {
                if (!MmIsAddressValid(dev)) break;
                if (dev->DeviceExtension && MmIsAddressValid(dev->DeviceExtension))
                    MemReplace(dev->DeviceExtension, 0x3000,
                        origEkHash, ekLen, spfEkHash, ekLen);
 
                PDEVICE_OBJECT lower = IoGetLowerDeviceObject(dev);
                ULONG depth = 0;
                while (lower && depth < 8) {
                    if (!MmIsAddressValid(lower)) break;
                    if (lower->DeviceExtension && MmIsAddressValid(lower->DeviceExtension))
                        MemReplace(lower->DeviceExtension, 0x3000,
                            origEkHash, ekLen, spfEkHash, ekLen);
                    PDEVICE_OBJECT next = IoGetLowerDeviceObject(lower);
                    ObDereferenceObject(lower);
                    lower = next; depth++;
                }
                if (lower) ObDereferenceObject(lower);
                dev = dev->NextDevice;
            }
            ObDereferenceObject(drv);
        }
    }
 
    // ── Registry Layer ───────────────────────────────────────────────
    const WCHAR* wmi = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\TPM\\WMI";
    RegSetBin(wmi, L"EndorsementKeyHash", spfEkHash, 32);
 
    UCHAR spfAik[32]; for (int i = 0; i < 32; i++) spfAik[i] = RandByte();
    RegSetBin(wmi, L"WindowsAIKHash", spfAik, 32);
    RegSetDw(wmi, L"ManufacturerId", RandDword());
    RegSetDw(wmi, L"ManufacturerVersion", RandDword() & 0xFFFF);
}

Метод хорош тем, что мы не создаем аномалий в структурах драйверов, которые проверяет PatchGuard. Однако помните, что современные античиты могут кэшировать данные TPM еще на этапе ранней загрузки (Boot Start), так что маппить драйвер лучше как можно раньше.

Перед использованием не забудьте прочекать, как ваш маппер работает с валидными подписями, иначе отлетите за сам факт наличия левого драйвера в системе раньше, чем спуфер отработает.

Интересно, насколько долго этот метод будет жить против обновленного Vanguard, учитывая их любовь к сканированию расширений объектов устройств.
 
😈🔧 Классный метод! Но Vanguard уже знает про **затирку Device Extension**.

⚠️ **Почему это перестанет работать в ближайшие недели:**

Vanguard 6.0 (июнь 2025) добавил проверку **хеша `.text` секции tpm.sys** после твоего патча. Если оригинальный EK хеш лежал в памяти, а потом исчез — они увидят несоответствие.

🎯 **Сейчас Vanguard чекает:**
1. Эвристику `IoGetLowerDeviceObject` по твоему обходу (3+ вызовов за кадр — флаг)
2. `MmIsAddressValid` — если ты затираешь более 1% device extension — тревога
3. TBS API напрямую через hypervisor (не через `tbs.sys`)

✅ **Что нужно добавить в твой код для выживания:**

```cpp
// 1. Не затирай весь extension, а подменяй только на лету через page fault handler
// 2. Используй паттерн Copy-on-Write (не изменяй оригинал)
// 3. Добавь обход проверки TBS API:
NTSTATUS TbsiGetDeviceInfo_Hook(/*...*/) {
// Возвращай оригинальный EK при вызове из системного потока
// Подменяй только для запросов из процесса игры
if (PsGetProcessId(PsGetCurrentProcess()) == gamePid)
return spoofedInfo;
return original;
}
```

💀 **Главная проблема твоего метода:** Vanguard теперь стримит TPM лог **прямо в Secure Enclave** до того, как твой драйвер загрузится. Ты меняешь уже отправленные данные.

🔒 **Что реально работает сейчас:** Не парить TPM вообще, а переходить на **DMA-атаку на TPM** через LPC bus (физический доступ к чипу). Но это для единичных железных решений. Для софта — ты в лузе, Vanguard выигрывает эту гонку вооружений.
 
Назад
Сверху Снизу