То же самое, что произошло бы в противном случае, я полагаю.
Допустим, что целевая тема в данный момент находится в пользовательском режиме. Вы сохраните все регистры позже, установите RIP
, чтобы указать на код и позвонить ResumeThread()
. В какой-то момент ваш код начинает выполняться, делает все, что он делает, восстанавливает все регистры, сохраненные кодом впрыска, и позволяет программе возобновить нормальную работу.
Теперь можно сказать, что целевая нить ждет. Ожидание означает, что поток выполняет системный вызов, который сообщает планировщику не планировать поток для выполнения, пока что-то не произойдет (событие сигнализируется и т. Д.). Вы сохраняете регистры контекста пользовательского режима (так, как они были при вызове sysenter
), установите RIP, чтобы указать на код и позвонить ResumeThread()
. Это все хорошо и приятно, но планировщик по-прежнему не планирует его исполнять до тех пор, пока условия ожидания не будут удовлетворены.
После завершения ожидания поток завершает свою работу в режиме ядра, возвращается в пользовательский режим и вместо выполнения команды ret
, следующей за sysenter
, продолжает выполнять ваш код. Наконец, ваш код восстанавливает все регистры и переходит к сохраненному RIP
(от ntdll!ZwWaitForSingleObject
или тому подобное), и все продолжается как обычно.
Наконец, скажем, вы выполняли предупредительное ожидание. История продолжается в основном, как и в предыдущих двух параграфах (вам не нужно, чтобы я повторил это в третий раз, не так ли? :)), за исключением того, что до возвращения функции ожидания она выполняет все пользовательские APC, поставленные в очередь для нить - точно так, как это могло бы произойти без вмешательства - и затем переходит на выполнение кода и т.д.
так в основном то, что происходит то, что вы должны ожидать случиться:
- Если вы вызвали
SetThreadContext()
, контекст пользовательского режима изменяется, и компьютер ведет себя соответственно, независимо от того, или нить ожидала, или нет.
- Если поток ждал чего-то, он продолжает ждать того же, независимо от того, вы вызываете «SetThreadContext()» или нет.
- Если поток был в ожидаемом ожидании, до того, как системный вызов будет возвращен, он будет уверен, что пользовательская APC-очередь пуста (либо потому, что есть пользовательские БТРы, и она вызвала их, либо потому, что очередь была пуста, а условие «обычного» ожидания наконец, произошло). Это, опять же, независимо от того, звоните ли вы
SetThreadContext()
или нет.
Рассмотрите возможность чтения [Функция SuspendThread приостанавливает поток, но делает это асинхронно] (https://blogs.msdn.microsoft.com/oldnewthing/20150205-00/?p=44743) и [Почему вы должны никогда не приостанавливать поток] (https://blogs.msdn.microsoft.com/oldnewthing/20031209-00/?p=41573). – IInspectable
Я не уверен, как приостановление нити связано с инъекционным кодом, а я второй возражений IInspectable. Но SuspendThread/ReleaseThread не должен влиять на вызовы API, если вы их правильно используете. (Например, WaitForSingleObjectEx может сразу вернуться с WAIT_IO_COMPLETION, но если вы правильно обрабатываете этот случай, это не имеет значения.) –
@IInpectable, вы даже прочитали ссылки, которые вы размахиваете здесь? Раймонд Чен говорит, что * «чтобы убедиться, что поток действительно приостановлен, вам необходимо выполнить синхронную операцию, зависящую от того, что поток приостановлен» * и сразу дает пример такого метода: * «Традиционный способ это нужно вызвать 'GetThreadContext' * *. Угадай, что? Это то, что он написал в OP. Подумайте о том, как читать ссылки, которые вы говорите другим людям, чтобы читать ** перед **, вы предлагаете им рассмотреть их чтение. – conio