Microsoft Detours - DetourUpdateThread?

У меня есть несколько вопросов о библиотеке Microsoft Detours. Я использовал его раньше (успешно), но я только что подумал об этой функции:

LONG DetourUpdateThread (HANDLE hThread);

В другом месте я читал, что эта функция фактически приостановит поток, пока транзакция не завершится. Это кажется странным, так как большинство примеров кода вызывает:

DetourUpdateThread (GetCurrentThread ());

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

Мои вопросы:

Когда транзакция фиксируется, будет ли указатель инструкции текущего потока находиться в функции DetourTransactionCommit? Если это так, почему мы должны привлекать его к обновлению?

Кроме того, если зачисленные потоки приостановлены, как текущий поток может продолжать выполняться (учитывая, что большинство примеров кода вызывает DetourUpdateThread(GetCurrentThread());)?

Наконец, не могли бы вы приостановить все потоки для текущего процесса, избегая условий гонки (учитывая, что потоки могут быть созданы и уничтожены в любое время)? Возможно, это делается, когда начинается транзакция? Это позволило бы нам более безопасно перечислять потоки (так как кажется менее вероятным, что новые потоки могут быть созданы), хотя как насчет CreateRemoteThread()?

Спасибо,

Павел

Для справки вот выдержка из простого примера:

// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function.  The Sleep target function is referred to
// through the TrueSleep target pointer.
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
        DetourTransactionCommit();
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
        DetourTransactionCommit();
    }
    return TRUE;
}

1 ответ

Решение

Как неловко: я забыл, что источник доступен!

DetourUpdateThread молча игнорирует включение текущего потока. В противном случае данный поток приостанавливается. Интересно, почему ВСЕ примеры кода подключают текущий поток в любом случае! Это отвечает на первые 2 вопроса.

Что касается третьего вопроса: я обнаружил другую обходную библиотеку, которая пытается приостановить все потоки, выполнив следующие действия:

  1. Получить снимок всех потоков

  2. Выполните цикл по снимку и приостановите потоки, которые мы еще не приостановили.

  3. Если потоки были приостановлены, вернитесь к 1 (мы все еще отслеживаем потоки, которые мы приостановили). Если никакие темы не были приостановлены, то мы сделали.

Я думаю, что предположение состоит в том, что, если мы сможем перебрать все потоки, и все они уже приостановлены (то есть, до того, как мы сделали снимок), тогда больше не может быть создано потоков. Хотя не уверен насчет CreateRemoteThread!

Редактировать: Re: CreateRemoteThread.

"Только один поток в процессе может одновременно находиться в инициализации или отсоединении DLL". CreateRemoteThread "приводит к вызову точки входа каждой DLL в процессе". http://msdn.microsoft.com/en-us/library/ms682437%28VS.85%29.aspx

Новый поток не может начать выполняться, если вы находитесь в функции DllMain (если новый поток еще не вызвал вызывающую точку входа каждой DLL в процессе). Поэтому, если вы примените свои обходные пути в функции DllMain, вы можете просто быть в безопасности от состояния гонки нового удаленного потока, который имеет указатель команд в вашей переписанной функции target / trampoline.

Спасибо,

Павел

Другие вопросы по тегам