Bien, use CreateRemoteThread
en un proceso remoto e invoque algo [1] que bloquee el proceso de manera confiable. No estoy seguro de si CreateRemoteThread
protege contra punteros nulos, pero podría pasarle una dirección en la página nula y hacer que el proceso remoto lo ejecute.
[1] puntero nulo o acceso a la página nula, la división por cero, la invocación de una instrucción privilegiada, int3
...
Ejemplo:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
BOOL setCurrentPrivilege(BOOL bEnable, LPCTSTR lpszPrivilege)
{
HANDLE hToken = 0;
if(::OpenThreadToken(::GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)
|| ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
TOKEN_PRIVILEGES tp;
LUID luid;
if(!::LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
::CloseHandle(hToken);
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
// Enable the privilege or disable all privileges.
if(!::AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL)
)
{
CloseHandle(hToken);
return FALSE;
}
::CloseHandle(hToken);
}
return TRUE;
}
int killProcess(DWORD processID)
{
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if(hProcess)
{
if(!setCurrentPrivilege(TRUE, SE_DEBUG_NAME))
{
_tprintf(TEXT("Could not enable debug privilege\n"));
}
HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)1, NULL, 0, NULL);
if(hThread)
{
::CloseHandle(hThread);
}
else
{
_tprintf(TEXT("Error: %d\n"), GetLastError());
::CloseHandle(hProcess);
return 1;
}
::CloseHandle(hProcess);
}
return 0;
}
int __cdecl _tmain(int argc, _TCHAR *argv[])
{
killProcess(3016);
}
Por supuesto, usted querrá ajuste el PID en la llamada al killProcess
. Compilado con WNET DDK y probado en 2003 Server R2.
Lo esencial aquí es que le decimos al proceso remoto que ejecute el código en la dirección 0x1 ((LPTHREAD_START_ROUTINE)1
), que está dentro de la página nula pero no en un puntero nulo (en caso de que exista una verificación). El crud alrededor de la función, en particular setCurrentPrivilege
se utiliza para obtener privilegios de depuración completos para que podamos hacer nuestra mala acción.
Si este es un programa al que puede adjuntar un depurador, puede salir del depurador sin desconectarlo; esto bloqueará su aplicación –