From d0ab25e521fdb050c3b2bc09539f651be396ced1 Mon Sep 17 00:00:00 2001
From: Spencer McIntyre <zeroSteiner@gmail.com>
Date: Fri, 28 Oct 2022 15:54:46 -0400
Subject: [PATCH 1/3] Close memory and handle leaks

---
 .../source/extensions/incognito/list_tokens.c | 142 +++++++++---------
 1 file changed, 73 insertions(+), 69 deletions(-)

diff --git a/c/meterpreter/source/extensions/incognito/list_tokens.c b/c/meterpreter/source/extensions/incognito/list_tokens.c
index 2ea062cf..eef5ecb1 100644
--- a/c/meterpreter/source/extensions/incognito/list_tokens.c
+++ b/c/meterpreter/source/extensions/incognito/list_tokens.c
@@ -194,87 +194,90 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
 					{
 						LPWSTR lpwsType = NULL;
 						lpwsType = GetObjectInfo(hObject, ObjectTypeInformation);
-						if ((lpwsType != NULL) && !wcscmp(lpwsType, L"Token") && ImpersonateLoggedOnUser(hObject) != 0)
+						if (lpwsType)
 						{
-							// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
-							// also revert to self after getting new token context
-							// only process if it was impersonation or higher
-							OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2);
-							RevertToSelf();
-							if (is_impersonation_token(hObject2))
+							if (wcscmp(lpwsType, L"Token") && (ImpersonateLoggedOnUser(hObject)))
 							{
-								// Reallocate space if necessary
-								if (*num_tokens_enum >= token_list_size)
+								// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
+								// also revert to self after getting new token context
+								// only process if it was impersonation or higher
+								OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2);
+								RevertToSelf();
+								if (is_impersonation_token(hObject2))
 								{
-									token_list_size *= 2;
-									token_list = (SavedToken*)realloc(token_list, token_list_size*sizeof(SavedToken));
-									if (!token_list)
+									// Reallocate space if necessary
+									if (*num_tokens_enum >= token_list_size)
 									{
-										goto cleanup;
-									}
-								}
-
-								token_list[*num_tokens_enum].token = hObject;
-								get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
-
-								if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
-								{
-									if (((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount > 0)
-									{
-										for (j = 0; j < ((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount; j++)
+										token_list_size *= 2;
+										token_list = (SavedToken*)realloc(token_list, token_list_size * sizeof(SavedToken));
+										if (!token_list)
 										{
-											returned_name_length = BUF_SIZE;
-											LookupPrivilegeNameW(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[j].Luid), privilege_name, &returned_name_length);
-											if (wcscmp(privilege_name, L"SeAssignPrimaryTokenPrivilege") == 0)
+											goto cleanup;
+										}
+									}
+
+									token_list[*num_tokens_enum].token = hObject;
+									get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
+
+									if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
+									{
+										if (((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount > 0)
+										{
+											for (j = 0; j < ((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount; j++)
 											{
-												token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeCreateTokenPrivilege") == 0)
-											{
-												token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeTcbPrivilege") == 0)
-											{
-												token_privs->SE_TCB_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeTakeOwnershipPrivilege") == 0)
-											{
-												token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeBackupPrivilege") == 0)
-											{
-												token_privs->SE_BACKUP_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeRestorePrivilege") == 0)
-											{
-												token_privs->SE_RESTORE_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeDebugPrivilege") == 0)
-											{
-												token_privs->SE_DEBUG_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeImpersonatePrivilege") == 0)
-											{
-												token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeRelabelPrivilege") == 0)
-											{
-												token_privs->SE_RELABEL_PRIVILEGE = TRUE;
-											}
-											else if (wcscmp(privilege_name, L"SeLoadDriverPrivilege") == 0)
-											{
-												token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
+												returned_name_length = BUF_SIZE;
+												LookupPrivilegeNameW(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[j].Luid), privilege_name, &returned_name_length);
+												if (wcscmp(privilege_name, L"SeAssignPrimaryTokenPrivilege") == 0)
+												{
+													token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeCreateTokenPrivilege") == 0)
+												{
+													token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeTcbPrivilege") == 0)
+												{
+													token_privs->SE_TCB_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeTakeOwnershipPrivilege") == 0)
+												{
+													token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeBackupPrivilege") == 0)
+												{
+													token_privs->SE_BACKUP_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeRestorePrivilege") == 0)
+												{
+													token_privs->SE_RESTORE_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeDebugPrivilege") == 0)
+												{
+													token_privs->SE_DEBUG_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeImpersonatePrivilege") == 0)
+												{
+													token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeRelabelPrivilege") == 0)
+												{
+													token_privs->SE_RELABEL_PRIVILEGE = TRUE;
+												}
+												else if (wcscmp(privilege_name, L"SeLoadDriverPrivilege") == 0)
+												{
+													token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
+												}
 											}
 										}
 									}
-								}
 
-								(*num_tokens_enum)++;
+									(*num_tokens_enum)++;
+								}
+								CloseHandle(hObject2);
 							}
-							CloseHandle(hObject2);
+							free(lpwsType);
 						}
-						else
-						{
+						else {
 							CloseHandle(hObject);
 						}
 					}
@@ -353,6 +356,7 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
 				{
 					dprintf("[INCOGNITO] Failed next level impersonation with %u (%x)", GetLastError(), GetLastError());
 				}
+				CloseHandle(process);
 			}
 
 			dprintf("[INCOGNITO] Moving to next process from %p", pProcessInfo);

From 80e8b721efb0959117be17cc079097bb1dfd1a04 Mon Sep 17 00:00:00 2001
From: Spencer McIntyre <zeroSteiner@gmail.com>
Date: Thu, 10 Nov 2022 15:34:18 -0500
Subject: [PATCH 2/3] Close the handle when it wasn't copied

Close the hObject handle when it wasn't copied into token_list.
---
 .../source/extensions/incognito/list_tokens.c | 134 ++++++++++--------
 1 file changed, 75 insertions(+), 59 deletions(-)

diff --git a/c/meterpreter/source/extensions/incognito/list_tokens.c b/c/meterpreter/source/extensions/incognito/list_tokens.c
index eef5ecb1..b35ba357 100644
--- a/c/meterpreter/source/extensions/incognito/list_tokens.c
+++ b/c/meterpreter/source/extensions/incognito/list_tokens.c
@@ -189,8 +189,7 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
 				{
 					hObject = NULL;
 
-					if (DuplicateHandle(process, (HANDLE)(DWORD_PTR)((i + 1) * 4),
-						GetCurrentProcess(), &hObject, MAXIMUM_ALLOWED, FALSE, 0x02) != FALSE)
+					if (DuplicateHandle(process, (HANDLE)(DWORD_PTR)((i + 1) * 4), GetCurrentProcess(), &hObject, MAXIMUM_ALLOWED, FALSE, 0x02))
 					{
 						LPWSTR lpwsType = NULL;
 						lpwsType = GetObjectInfo(hObject, ObjectTypeInformation);
@@ -273,8 +272,14 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
 
 									(*num_tokens_enum)++;
 								}
+								else {
+									CloseHandle(hObject);
+								}
 								CloseHandle(hObject2);
 							}
+							else {
+								CloseHandle(hObject);
+							}
 							free(lpwsType);
 						}
 						else {
@@ -285,76 +290,87 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
 
 				// Also process primary
 				// if has impersonate privs, only needs read access
-				if (OpenProcessToken(process, MAXIMUM_ALLOWED, &hObject) && ImpersonateLoggedOnUser(hObject))
+				if (OpenProcessToken(process, MAXIMUM_ALLOWED, &hObject))
 				{
-					// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
-					// also revert to self after getting new token context
-					// only process if it was impersonation or higher
-					if (OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2))
-					{
-						RevertToSelf();
-						if (is_impersonation_token(hObject2))
+					if (ImpersonateLoggedOnUser(hObject)) {
+						// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
+						// also revert to self after getting new token context
+						// only process if it was impersonation or higher
+						if (OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2))
 						{
-							token_list[*num_tokens_enum].token = hObject;
-							get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
-							(*num_tokens_enum)++;
-
-							if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
+							RevertToSelf();
+							if (is_impersonation_token(hObject2))
 							{
-								for (i = 0; i < ((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount; i++)
+								token_list[*num_tokens_enum].token = hObject;
+								get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
+								(*num_tokens_enum)++;
+
+								if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
 								{
-									returned_name_length = BUF_SIZE;
-									LookupPrivilegeNameW(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[i].Luid), privilege_name, &returned_name_length);
-									if (wcscmp(privilege_name, L"SeAssignPrimaryTokenPrivilege") == 0)
+									for (i = 0; i < ((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount; i++)
 									{
-										token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeCreateTokenPrivilege") == 0)
-									{
-										token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeTcbPrivilege") == 0)
-									{
-										token_privs->SE_TCB_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeTakeOwnershipPrivilege") == 0)
-									{
-										token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeBackupPrivilege") == 0)
-									{
-										token_privs->SE_BACKUP_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeRestorePrivilege") == 0)
-									{
-										token_privs->SE_RESTORE_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeDebugPrivilege") == 0)
-									{
-										token_privs->SE_DEBUG_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeImpersonatePrivilege") == 0)
-									{
-										token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeRelabelPrivilege") == 0)
-									{
-										token_privs->SE_RELABEL_PRIVILEGE = TRUE;
-									}
-									else if (wcscmp(privilege_name, L"SeLoadDriverPrivilege") == 0)
-									{
-										token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
+										returned_name_length = BUF_SIZE;
+										LookupPrivilegeNameW(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[i].Luid), privilege_name, &returned_name_length);
+										if (wcscmp(privilege_name, L"SeAssignPrimaryTokenPrivilege") == 0)
+										{
+											token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeCreateTokenPrivilege") == 0)
+										{
+											token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeTcbPrivilege") == 0)
+										{
+											token_privs->SE_TCB_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeTakeOwnershipPrivilege") == 0)
+										{
+											token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeBackupPrivilege") == 0)
+										{
+											token_privs->SE_BACKUP_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeRestorePrivilege") == 0)
+										{
+											token_privs->SE_RESTORE_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeDebugPrivilege") == 0)
+										{
+											token_privs->SE_DEBUG_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeImpersonatePrivilege") == 0)
+										{
+											token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeRelabelPrivilege") == 0)
+										{
+											token_privs->SE_RELABEL_PRIVILEGE = TRUE;
+										}
+										else if (wcscmp(privilege_name, L"SeLoadDriverPrivilege") == 0)
+										{
+											token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
+										}
 									}
 								}
 							}
+							else {
+								CloseHandle(hObject);
+							}
+							CloseHandle(hObject2);
 						}
-
-						CloseHandle(hObject2);
+						else {
+							CloseHandle(hObject);
+						}
+					}
+					else {
+						dprintf("[INCOGNITO] Failed next level impersonation, ImpersonateLoggedOnUser failed with %u (%x)", GetLastError(), GetLastError());
+						CloseHandle(hObject);
 					}
 				}
 				else
 				{
-					dprintf("[INCOGNITO] Failed next level impersonation with %u (%x)", GetLastError(), GetLastError());
+					dprintf("[INCOGNITO] Failed next level impersonation, OpenProcessToken failed with %u (%x)", GetLastError(), GetLastError());
 				}
 				CloseHandle(process);
 			}

From f5bae3b63cf72d8929604eff5914738cb573bbec Mon Sep 17 00:00:00 2001
From: Grant Willcox <gwillcox@rapid7.com>
Date: Thu, 10 Nov 2022 15:56:05 -0600
Subject: [PATCH 3/3] Cleanup handles if memory allocation fails before exiting
 get_token_list

---
 c/meterpreter/source/extensions/incognito/list_tokens.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/c/meterpreter/source/extensions/incognito/list_tokens.c b/c/meterpreter/source/extensions/incognito/list_tokens.c
index b35ba357..02d8da7d 100644
--- a/c/meterpreter/source/extensions/incognito/list_tokens.c
+++ b/c/meterpreter/source/extensions/incognito/list_tokens.c
@@ -211,6 +211,9 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
 										token_list = (SavedToken*)realloc(token_list, token_list_size * sizeof(SavedToken));
 										if (!token_list)
 										{
+											CloseHandle(hObject2);
+											CloseHandle(hObject);
+											CloseHandle(process);
 											goto cleanup;
 										}
 									}