diff --git a/src/process.c b/src/process.c index c7163d00..1bdb4552 100644 --- a/src/process.c +++ b/src/process.c @@ -51,9 +51,11 @@ PF_TYPE_DECL(NTAPI, NTSTATUS, NtQuerySystemInformation, (SYSTEM_INFORMATION_CLAS PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryObject, (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG)); PF_TYPE_DECL(NTAPI, NTSTATUS, NtDuplicateObject, (HANDLE, HANDLE, HANDLE, PHANDLE, ACCESS_MASK, ULONG, ULONG)); PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenProcess, (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenProcessToken, (HANDLE, ACCESS_MASK, PHANDLE)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtAdjustPrivilegesToken, (HANDLE, BOOLEAN, PTOKEN_PRIVILEGES, ULONG, PTOKEN_PRIVILEGES, PULONG)); PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE)); -PVOID PhHeapHandle = NULL; +static PVOID PhHeapHandle = NULL; /* * Convert an NT Status to an error message @@ -67,6 +69,8 @@ static char* NtStatusError(NTSTATUS Status) { static char unknown[32]; switch (Status) { + case STATUS_SUCCESS: + return "Operation Successful"; case STATUS_UNSUCCESSFUL: return "Operation Failed"; case STATUS_BUFFER_OVERFLOW: @@ -548,3 +552,50 @@ out: PhDestroyHeap(); return bFound; } + +/** + * Increase the privileges of the current application. + * + * \return TRUE if the request was successful. + */ +BOOL EnablePrivileges(void) +{ + // List of the privileges we require. A list of requestable privileges can + // be obtained at https://technet.microsoft.com/en-us/library/dn221963.aspx + const DWORD requestedPrivileges[] = { + SE_DEBUG_PRIVILEGE, + }; + NTSTATUS status = STATUS_NOT_IMPLEMENTED; + HANDLE tokenHandle; + + PF_INIT_OR_OUT(NtClose, NtDll); + PF_INIT_OR_OUT(NtOpenProcessToken, NtDll); + PF_INIT_OR_OUT(NtAdjustPrivilegesToken, NtDll); + + status = pfNtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &tokenHandle); + + if (NT_SUCCESS(status)) { + CHAR privilegesBuffer[FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges) + + sizeof(LUID_AND_ATTRIBUTES) * ARRAYSIZE(requestedPrivileges)]; + PTOKEN_PRIVILEGES privileges; + ULONG i; + + privileges = (PTOKEN_PRIVILEGES)privilegesBuffer; + privileges->PrivilegeCount = ARRAYSIZE(requestedPrivileges); + + for (i = 0; i < privileges->PrivilegeCount; i++) { + privileges->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED; + privileges->Privileges[i].Luid.HighPart = 0; + privileges->Privileges[0].Luid.LowPart = requestedPrivileges[i]; + } + + status = pfNtAdjustPrivilegesToken(tokenHandle, FALSE, privileges, 0, NULL, NULL); + + pfNtClose(tokenHandle); + } + +out: + if (!NT_SUCCESS(status)) + ubprintf("NOTE: Could not set process privileges: %s", NtStatusError(status)); + return NT_SUCCESS(status); +} diff --git a/src/process.h b/src/process.h index ae33d34f..bfc96263 100644 --- a/src/process.h +++ b/src/process.h @@ -233,5 +233,44 @@ typedef struct _RTL_HEAP_PARAMETERS #define HEAP_CLASS_8 0x00008000 // CSR port heap #define HEAP_CLASS_MASK 0x0000f000 -#define PF_INIT_OR_SET_STATUS(proc, name) do {PF_INIT(proc, name); \ - if (pf##proc == NULL) status = STATUS_NOT_IMPLEMENTED; } while(0) +// Privileges + +#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) +#define SE_CREATE_TOKEN_PRIVILEGE (2L) +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L) +#define SE_LOCK_MEMORY_PRIVILEGE (4L) +#define SE_INCREASE_QUOTA_PRIVILEGE (5L) +#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L) +#define SE_TCB_PRIVILEGE (7L) +#define SE_SECURITY_PRIVILEGE (8L) +#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L) +#define SE_LOAD_DRIVER_PRIVILEGE (10L) +#define SE_SYSTEM_PROFILE_PRIVILEGE (11L) +#define SE_SYSTEMTIME_PRIVILEGE (12L) +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L) +#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) +#define SE_CREATE_PAGEFILE_PRIVILEGE (15L) +#define SE_CREATE_PERMANENT_PRIVILEGE (16L) +#define SE_BACKUP_PRIVILEGE (17L) +#define SE_RESTORE_PRIVILEGE (18L) +#define SE_SHUTDOWN_PRIVILEGE (19L) +#define SE_DEBUG_PRIVILEGE (20L) +#define SE_AUDIT_PRIVILEGE (21L) +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L) +#define SE_CHANGE_NOTIFY_PRIVILEGE (23L) +#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L) +#define SE_UNDOCK_PRIVILEGE (25L) +#define SE_SYNC_AGENT_PRIVILEGE (26L) +#define SE_ENABLE_DELEGATION_PRIVILEGE (27L) +#define SE_MANAGE_VOLUME_PRIVILEGE (28L) +#define SE_IMPERSONATE_PRIVILEGE (29L) +#define SE_CREATE_GLOBAL_PRIVILEGE (30L) +#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L) +#define SE_RELABEL_PRIVILEGE (32L) +#define SE_INC_WORKING_SET_PRIVILEGE (33L) +#define SE_TIME_ZONE_PRIVILEGE (34L) +#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L) +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE + +#define PF_INIT_OR_SET_STATUS(proc, name) do {PF_INIT(proc, name); \ + if ((pf##proc == NULL) && (NT_SUCCESS(status))) status = STATUS_NOT_IMPLEMENTED; } while(0) diff --git a/src/rufus.c b/src/rufus.c index e1e3f582..ce57a09a 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -3157,7 +3157,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine hMainInstance = hInstance; // Initialize COM for folder selection - IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); + IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)); // Some dialogs have Rich Edit controls and won't display without this if (GetLibraryHandle("Riched20") == NULL) { @@ -3167,6 +3167,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // Set the Windows version GetWindowsVersion(); + // Increase the application privileges (SE_DEBUG_PRIVILEGE), so that we can report + // the Windows Services preventing access to the disk or volume we want to format. + EnablePrivileges(); + // We use local group policies rather than direct registry manipulation // 0x9e disables removable and fixed drive notifications lgp_set = SetLGP(FALSE, &existing_key, ep_reg, "NoDriveTypeAutorun", 0x9e); diff --git a/src/rufus.h b/src/rufus.h index 7d158f7e..d2a2b981 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -500,6 +500,7 @@ extern char* GetCurrentMUI(void); extern BOOL SetFormatPromptHook(void); extern void ClrFormatPromptHook(void); extern BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf); +extern BOOL EnablePrivileges(void); DWORD WINAPI FormatThread(void* param); DWORD WINAPI SaveImageThread(void* param); diff --git a/src/rufus.rc b/src/rufus.rc index 2d164c22..acc97947 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 2.15.1104" +CAPTION "Rufus 2.15.1105" FONT 8, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -334,8 +334,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,15,1104,0 - PRODUCTVERSION 2,15,1104,0 + FILEVERSION 2,15,1105,0 + PRODUCTVERSION 2,15,1105,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -352,13 +352,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.15.1104" + VALUE "FileVersion", "2.15.1105" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.15.1104" + VALUE "ProductVersion", "2.15.1105" END END BLOCK "VarFileInfo"