В Windows API есть две в чем-то родственные функции - TerminateThread и SuspendThread. Обе роднит то, что они без спроса вмешиваются в выполнение какой-нибудь программы (или ее части - потока (Thread)). При этом первая функция принудительно завершает выполнение программы, а вторая приостанавливает его - до вызова функции возобновления ResumeThread.
Поиграться с этим можно с помощью Process Explorer (
www.sysinternals.com). Данный мощный инструмент позволяет останавливать и завершать любые процессы и потоки в системе. Удобное и подробное отображение информации о процессах и потоках также позволяет легко найти подходящий "объект для экспериментов".
В документации на TerminateThread сказано, что "после вызова данной функции поток, который требуется завершить, не имеет шанса выполнить больше кода в пользовательском режиме (User mode)". Про код режима ядра (Kernel Mode) в документации не сказано - и на самом деле, если поток-жертва выполнял что-то в режиме ядра, то он беспрепятственно продолжит это делать до перехода в пользовательский режим. Тогда-то он и будет завершен.
Это логично и правильно. Если прибить поток, когда он выполняет системные вызовы где-то глубоко в недрах винды, то ядро операционной системы останется в нештатном состоянии. В результате работа всей системы и других программ будет нарушена, и потребуется перезагрузка. Поэтому, прибивая поток, винда дает ему возможность "прибрать за собой" в режиме ядра.
Почему-то подобного ограничения вмешательства не предусмотрено для функции SuspendThread. Она может остановить работу потока где угодно - хоть в пользовательском режиме, хоть в режиме ядра. Вот о втором случае мы и поговорим особо.
Работая с ресурсами ядра Windows, поток обычно блокирует доступ к этим ресурсам со стороны других программ. Данная блокировка обычно является кратковременной и внешне для пользователя незаметна. Пользователю кажется, что доступ к ресурсам (таким, как файлы на диске) идет со стороны многих программ одновременно. На самом же деле программы поочередно захватывают ресурс полностью, на короткое время. Пока одна программа захватывает ресурс, остальные ждут.
И вот что получается. Если остановить поток в "удачный" момент, когда он заблокировал что-нибудь важное в ядре Windows, то этот ресурс так и останется заблокированным - до возобновления работы потока. Неограниченно долго. Таким образом может быть нарушена работа многих программ и системных компонент.
При этом - обращаю внимание - будет нарушена работа тех программ, которые не имеют никакого отношения к остановленному потоку! Тут не действует никаких ограничений привилегий. Пользователь с ограниченными правами может многократно останавливать свои программы с помощью SuspendThread - до тех пор, пока не попадет на удачный момент и не заблокирует важный системный ресурс - хотя блокировать его на длительное время он, по идее, прав не имел.
Я совершенно недавно узнал об этой уязвимости - читая свежую документацию для разработчиков драйверов. Фирма Microsoft предлагает разработчикам драйверов принимать особые меры - защищать поток от остановки - на время доступа к критичным ресурсам. Благо есть такая возможность. Но предусмотреть все случаи неявной блокировки ресурсов, чтобы на это время блокировать остановку потока, просто нереально! И вообще это костыли. Можно было бы одним махом решить проблему, не переписывая старых драйверов, если позволить остановку потока только в пользовательском режиме, как это сделано для TerminateThread.
И вообще риск нечаянно нарушить работу системы заставляет разработчиков не только драйверов, но и пользовательских приложений, вообще отказаться от использования SuspendThread и ResumeThread - и реализовывать желаемое иными способами.