2015-05-08 9 views
1

Я пытаюсь найти способ, позволяющий запускать один процесс как повышенный пользователь, но запретить этому процессу запускать любые дети с его жетоном - в некотором смысле, вроде «герметизации» токена. Причиной этого является предотвращение запуска пользователем cmd.exe и получение полного доступа к системе.Есть ли способ «запечатать» токен, чтобы дочерние процессы не могли наследовать его?

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

+0

Хорошая идея, хотя, к сожалению, приложенное приложение может быть чем угодно и неизвестно. Моя модель мышления тяготеет к чему-то вроде: -Создайте службу, которая запускает процесс как повышенный пользователь. -Получить ссылку на его токен и сохранить эту ссылку. -Register прослушиватель WMI для проверки запуска приложений - если запущенное приложение имеет тот же токен/привилегии, что и приложение для увеличения, автоматически убивает дочерний процесс. – slashp

+1

Я думаю, вы могли бы сделать это с помощью драйвера режима ядра через ObRegisterCallbacks. Но это была бы очень мелкая защита: любой, кто может сделать запуск процесса с повышенным запуском cmd.exe, почти наверняка заставит процесс с повышенным уровнем сделать что-нибудь, что может сделать cmd.exe, и многое другое. (Включая отключение вашего механизма защиты и * затем * запуск cmd.exe!) –

ответ

3

Я не думаю, что вы можете запечатать маркер, но вы можете контролировать создание дочернего процесса с объектами на работу:

static BOOL SpawnProcessAndTerminateGrandchildren(PTSTR Cmdline) 
{ 
    HANDLE hJob = CreateJobObject(0, 0); 
    if (!hJob) return false; 

    JOBOBJECT_BASIC_LIMIT_INFORMATION jobli; 
    jobli.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS; 
    jobli.ActiveProcessLimit = 1; 
    BOOL retval = SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &jobli, sizeof(jobli)); 

    PROCESS_INFORMATION pi; 
    if (retval) 
    { 
     STARTUPINFO si; 
     ZeroMemory(&si, sizeof(si)), si.cb = sizeof(si); 
     retval = CreateProcess(0, Cmdline, 0, 0, false, CREATE_SUSPENDED|CREATE_BREAKAWAY_FROM_JOB|CREATE_NEW_CONSOLE, 0, 0, &si, &pi); 
    } 
    if (retval) 
    { 
     if (AssignProcessToJobObject(hJob, pi.hProcess)) // This can fail if we are already in a job 
     { 
      ResumeThread(pi.hThread); 
      WaitForSingleObject(pi.hProcess, INFINITE); 
     } 
     else 
      TerminateProcess(pi.hProcess, ERROR_OPERATION_ABORTED); 
     CloseHandle(pi.hThread); 
     CloseHandle(pi.hProcess); 
    } 
    CloseHandle(hJob); 
    return retval; 
} 


int main(int argc, ...) 
{ 
    TCHAR cmd[] = TEXT("cmd.exe /k regedit"); // cmd.exe is our child, regedit is the grandchild spawned by cmd.exe 
    SpawnProcessAndTerminateGrandchildren(cmd); 
    return 0; 
} 

Если вы хотите больше контроля вы можете использовать JobObjectAssociateCompletionPortInformation так вы получите сообщение JOB_OBJECT_MSG_NEW_PROCESS каждый раз, создается новый дочерний процесс.