Лок на PspCidTable

Тема в разделе "WASM.NT.KERNEL", создана пользователем sergegers, 26 янв 2011.

  1. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    В статье Ms-Rem'а "Обнаружение скрытых процессов" параграф "Получение списка процессов путем сканирования PspCidTable" и в статье "3 метода работы с занятыми файлами" происходит обращение к PspCidTable без наложения блокировки. Правильно ли это? Если это не правльно, то как её поставить? В структуре _HANDLE_TABLE есть поле EX_PUSH_LOCK HandleTableLock[4] - почему то 4х элементный массив. Это блокировки на каждый индекс?
    Вообщем, если у кого-то есть какие-то соображения, буду признателен.
     
  2. 0x6b65

    0x6b65 Забанен

    Публикаций:
    0
    Регистрация:
    8 окт 2009
    Сообщения:
    92
    Нет, конечно не правильно. Какие именно операции над таблицей описателей интересуют? Разные операции требуют разных манипуляций над синхро-объектами.

    P.S. ответы на все заданные вопросы есть в WRK
     
  3. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    интересует нахождение ETHREAD по ThreadId. конкретная задача своя реализация PsLookupThreadByThreadId для Windows XP. она не срабатывает в колбэке PsSetCreateThreadNotifyRoutine
     
  4. ntkernelspawn

    ntkernelspawn New Member

    Публикаций:
    0
    Регистрация:
    17 дек 2010
    Сообщения:
    61
    Возьми сорсы и не еб* могзи! Извини за грубость ...
     
  5. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    охуительный совет
     
  6. 0x6b65

    0x6b65 Забанен

    Публикаций:
    0
    Регистрация:
    8 окт 2009
    Сообщения:
    92
    А совет-то не плохой: если не умеем читать дизассемблерные листинги, то открываем реализацию nt!PspCreateThread() в WRK. И в ней видим, что вызов nt!PspCreateThreadNotifyRoutine–callback’ов происходит уже после вставки нового элемента в nt!PspCidTable (а иначе ядру будет неоткуда взять ThreadId).
    Трассировкой nt!PsLookupThreadByThreadId можно найти отличия ее от "своей реализации" и исправить ошибку. Это если присутствует академический интерес, если нужна реализация – просто копируем ее из WRK.
    Или "свою реализацию" выкладывайте - тут нет экстрасенсов, никто баг не найдет без дополнительных данных: исходники, анализ падения, если происходит.
     
  7. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    ситуация обратная - стандартная реализация в Windows XP не срабатывает в колбэке. в блоге x64 я прочёл, что это происходит из-за не установленной к этому моменту маски доступа и совет реализовать сканирование таблицы PspCidTable самостоятельно
    вот код


    ::P_ETHREAD GetThreadHandleById( ::PHANDLE_TABLE HandleTable, ::ULONG ThreadId )
    {
    ::ULONG TableCode = HandleTable->TableCode & ~TABLE_LEVEL_MASK;
    ::PHANDLE_TABLE_ENTRY HandleTableEntry;

    switch (HandleTable->TableCode & TABLE_LEVEL_MASK)
    {
    case 0:
    // one index level table
    for (int i = 0; i < 200; ++i)
    {
    HandleTableEntry = &reinterpret_cast< ::PHANDLE_TABLE_ENTRY>(TableCode);
    if (HandleTableEntry->Object)
    {
    ::P_ETHREAD EThread = reinterpret_cast< ::P_ETHREAD>(
    reinterpret_cast< ::ULONG>(HandleTableEntry->Object) & ~XP_TABLE_ENTRY_LOCK_BIT);
    if (reinterpret_cast< ::ULONG>(EThread->Cid.UniqueThread) == ThreadId)
    return EThread;
    }
    }
    break;

    case 1:
    // two index level table
    {
    for (int i = 0; i < 200; ++i)
    {
    if (reinterpret_cast< ::PVOID *>(TableCode))
    {
    for (int j = 0; j < 200; ++j)
    {
    HandleTableEntry =
    &reinterpret_cast< ::PHANDLE_TABLE_ENTRY *>(TableCode)[j];
    if (HandleTableEntry->Object)
    {
    ::P_ETHREAD EThread = reinterpret_cast< ::P_ETHREAD>(
    reinterpret_cast< ::ULONG>(HandleTableEntry->Object) &
    ~XP_TABLE_ENTRY_LOCK_BIT);
    if (reinterpret_cast< ::ULONG>(EThread->Cid.UniqueThread) == ThreadId)
    return EThread;
    }
    }
    }
    }
    }
    break;

    case 2:
    // three index level table
    {
    for (int i = 0; i < 200; ++i)
    {
    if (reinterpret_cast< ::PVOID *>(TableCode))
    {
    for (int j = 0; j < 200; ++j)
    {
    if (reinterpret_cast< ::PVOID **>(TableCode)[j])
    {
    for (int k = 0; k < 200; ++k)
    {
    HandleTableEntry = &reinterpret_cast<
    ::PHANDLE_TABLE_ENTRY **>(TableCode)[j][k];
    if (HandleTableEntry->Object)
    {
    ::P_ETHREAD EThread =
    reinterpret_cast< ::P_ETHREAD>(
    reinterpret_cast< ::ULONG>(HandleTableEntry->Object) &
    ~XP_TABLE_ENTRY_LOCK_BIT);
    if (reinterpret_cast< ::ULONG>(EThread->Cid.UniqueThread) ==
    ThreadId)
    return EThread;
    }
    }
    }
    }
    }
    }
    }
    break;

    default:
    ASSERT(!"Unexpected");
    }
    return NULL;
    }


    NTSTATUS CProcessTracker::PsLookupThreadByThreadId( __in HANDLE ThreadId, __out PETHREAD *Thread )
    {
    #if (NTDDI_VERSION == NTDDI_WINXP)
    if (!Thread) return STATUS_INVALID_PARAMETER_2;

    ::P_ETHREAD pEThread = GetThreadHandleById(m_pPspCidTable, reinterpret_cast< ::ULONG>(ThreadId));
    if (!pEThread) return STATUS_UNSUCCESSFUL;

    // increase reference count
    ::POBJECT_HEADER pObjHeader = OBJECT_TO_OBJECT_HEADER(pEThread);
    ::InterlockedIncrement(&pObjHeader->PointerCount);

    *Thread = reinterpret_cast< ::PETHREAD>(pEThread);
    return STATUS_SUCCESS;

    #elif (NTDDI_VERSION >= NTDDI_VISTA)
    return ::PsLookupThreadByThreadId(ThreadId, Thread);
    #else
    error Not Implemented!
    #endif // NTDDI_VERSION
    }

    // это PspCreateThreadNotifyRoutine callback
    VOID CProcessTracker::ThreadNotifyRoutine(
    IN HANDLE ProcessId, IN HANDLE ThreadId, IN BOOLEAN Create)
    {
    CProcessTracker *pProcessTracker = GetProcessTracker();
    ::ULONG pid = reinterpret_cast<ULONG>(ProcessId);
    ::ULONG tid = reinterpret_cast<ULONG>(ThreadId);

    if (pid != pProcessTracker->m_TrackedProcessId) return;
    if (!Create) return;

    ::NTSTATUS status(STATUS_SUCCESS);
    ::ExAcquireFastMutex(&pProcessTracker->m_OperationGuard);
    __try
    {
    // recheck thread tracking conditions
    if (pid != pProcessTracker->m_TrackedProcessId) __leave;

    ::PETHREAD pEthread;
    status = pProcessTracker->PsLookupThreadByThreadId(ThreadId, &pEthread);
    if (NT_ERROR(status))
    {
    ::lol: bgPrint("Failed to lookup thread.\nProces %i thread %i\nMessage: %s\n",
    pid, tid, OsrNTStatusToString(status));
    __leave;
    }

    __try
    {
    ::HANDLE hThread;
    status = ::ObOpenObjectByPointer(
    pEthread,
    OBJ_KERNEL_HANDLE,
    NULL,
    STANDARD_RIGHTS_ALL,
    NULL,
    KernelMode,
    &hThread
    );
    if (NT_ERROR(status))
    {
    ::lol: bgPrint("Unable to open thread.\nProces %i thread %i\nMessage: %s\n",
    pid, tid, OsrNTStatusToString(status));
    __leave;
    }

    __try
    {
    if (pProcessTracker->IsThreadExcluded(tid))
    {
    status = (*pProcessTracker->m_pfnNtResumeThread)(hThread, NULL);
    }
    else
    {
    status = (*pProcessTracker->m_pfnNtSuspendThread)(hThread, NULL);
    // ^^^ выходит со статусом STATUS_INVALID_HANDLE
    }

    if (NT_ERROR(status))
    {
    ::lol: bgPrint("Unable to suspend/resume thread.\nProces %i thread %i\nMessage: %s\n",
    pid, tid, OsrNTStatusToString(status));
    __leave;
    }
    }
    __finally
    {
    ::ZwClose(hThread);
    }
    }
    __finally
    {
    ::ObfDereferenceObject(pEthread);
    }
    }
    __finally
    {
    ::ExReleaseFastMutex(&pProcessTracker->m_OperationGuard);
    }
    }

    PS Опыта кернел программирования у меня немного, поэтому правильный совет сэкономит мне массу времени
     
  8. 0x6b65

    0x6b65 Забанен

    Публикаций:
    0
    Регистрация:
    8 окт 2009
    Сообщения:
    92
    Имея на руках ThreadId (читай: описатель из nt!PspCidTable) приведенный код еще раз линейно идет по содержимому таблицы nt!PspCidTable...
    Значение описателя само по себе содержит необходимые индексы в своей таблице! В приведенном листинге, функцию GetThreadHandleById нужно заменить на аналог nt!ExpLookupHandleTableEntry(). А если уж есть навыки поиска и использования не-экспортируемых символов ядра, то проще всего вызвать:
    Код (Text):
    1. PHANDLE_TABLE_ENTRY
    2. ExMapHandleToPointer (
    3.     __in PHANDLE_TABLE HandleTable,
    4.     __in HANDLE Handle
    5.     );
     
  9. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    всё вроде получилось. большое спасибо!