WriteProcessMemory в процесс SYSTEM с включенным SeDebugPrivilege. (C, Vista) - PullRequest
7 голосов
/ 16 июля 2009

Я заинтересован в том, чтобы вставлять библиотеки DLL в процессы, принадлежащие SYSTEM, на моей машине Vista. Я собираюсь об этом, используя традиционный метод VirtualAllocEx, WriteProcessMemory и CreateRemoteThread. Однако, поскольку это будет работать в процессах SYSTEM, я включаю SeDebugPivilege в процессе внедрения, прежде чем открывать целевой процесс.


int EnableDebugPriv(LPCTSTR name) {
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    if(!OpenProcessToken(GetCurrentProcess(),
                         /*TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY*/
                         TOKEN_ALL_ACCESS,
                         &hToken))
        return 0;

    if(!LookupPrivilegeValue(NULL,name,&luid))
        return 0;

    tkp.PrivilegeCount=1;
    tkp.Privileges[0].Luid=luid;
    tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

    if(!AdjustTokenPrivileges(hToken,false,&tkp,sizeof(tkp),NULL,NULL))
    {
        printf("!AdjustTokenPrivileges - %d\n",GetLastError());
        return 0;
    }
    if(GetLastError()==ERROR_NOT_ALL_ASSIGNED)
    {
        return 0;
    }

    CloseHandle(hToken);
    return 1;
}

Где константа SE_DEBUG_NAME передается как имя.

После включения SeDebugPrivilege я прохожу процесс открытия целевого процесса, поиска LoadLibrary, выделения пространства, записи пути DLL в память и создания потока (проверяя все возвращаемые значения по пути):


if(NULL==(p=OpenProcess(PROCESS_ALL_ACCESS,FALSE,(DWORD)pid)))
...
if(NULL==(loadLib=(LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), 
                                         "LoadLibraryA")))
...
if(NULL==(dllBuff=(LPVOID)VirtualAllocEx(p,
                                         NULL,
                                         strlen(dllPath)+1,
                                         MEM_RESERVE|MEM_COMMIT,
                                         PAGE_READWRITE)))
...
if(NULL==WriteProcessMemory(p,
                            (LPVOID)dllBuff,
                            dllPath,
                            strlen(dllPath),
                            &written))
...
if(!CreateRemoteThread(p,
                       NULL,
                       NULL,
                       (LPTHREAD_START_ROUTINE)loadLib,
                       (LPVOID)dllBuff,
                       NULL,
                       NULL))
...

dllPath - это символ * пути DLL (очевидно), а pid - это PID целевого процесса. Оба эти значения принимаются через командную строку и проверяются перед использованием.

Проблема, с которой я столкнулся, заключается в том, что ничего не возвращает ошибки до CreateRemoteThread, который возвращает 8 («Недостаточно памяти»). ОДНАКО WriteProcessMemory НЕ записывает байты в процесс. После вызова записываемая переменная всегда равна 0. Байт не записывается, но функция не дает сбоя. Я не уверен, почему это происходит. Я посмотрел на другие привилегии, такие как SeRestorePrivilege, который обещает доступ на запись ко всем процессам, но ничего не работает.

Я запускаю эту программу с правами администратора.

Примечание: эта проблема WriteProcessMemory и CreateRemoteThread возникает только тогда, когда я запускаю эту программу для пользователей с более высокими привилегиями (SYSTEM, LOCAL SERVICE и т. Д. ...). Он отлично работает против программы, принадлежащей мне (те же привилегии).

Редактировать: вот ссылка на весь источник. http://pastebin.com/m77110d8e Там нет ничего другого, кроме базовой проверки ошибок, но, может быть, это поможет?

Ответы [ 2 ]

4 голосов
/ 16 июля 2009

Вы можете попробовать использовать RtlCreateUserThread вместо CreateRemoteThread. Эта подпрограмма не заботится о том, в каком сеансе находится целевой процесс. Просто помните, что поток должен вызвать RtlExitUserThread до его завершения. Эти потоки не очищаются после себя, как это делают CreateThread / CreateRemoteThread.

код реагирования может дать вам хорошее представление о том, что делают эти процедуры.

4 голосов
/ 16 июля 2009

Это связано с изоляцией сеанса в Vista или более поздних версиях Windows. Проверьте исходный код или разборку для инструментов сброса паролей, таких как Cain и Abel, которые подразумевают функциональность Vista. По сути, процесс тот же, но вы будете вызывать другую функцию для CreateRemoteThread (извините, я не думаю, что эта функция экспортируется, вам просто нужно ее найти, поэтому лучше всего разбирать работающее программное обеспечение).

...