Skip to content

Commit

Permalink
wsudo: 5.0.0 some behavioral corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
fcharlie committed Jul 22, 2022
1 parent a29bfdf commit 99402db
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 143 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ else()
endif()

#
set(PRIVEXEC_VERSION_MAJOR 4)
set(PRIVEXEC_VERSION_MINOR 4)
set(PRIVEXEC_VERSION_PATCH 2)
set(PRIVEXEC_VERSION_MAJOR 5)
set(PRIVEXEC_VERSION_MINOR 0)
set(PRIVEXEC_VERSION_PATCH 0)
set(PACKAGE_VERSION "${PRIVEXEC_VERSION_MAJOR}.${PRIVEXEC_VERSION_MINOR}.${PRIVEXEC_VERSION_PATCH}")

string(TOLOWER "${CMAKE_C_COMPILER_ARCHITECTURE_ID}" COMPILER_ARCH_ID)
Expand Down
5 changes: 3 additions & 2 deletions Privexec/app.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ bool App::Initialize(HWND window) {

box.Append((int)wsudo::exec::privilege_t::appcontainer, L"AppContainer");
box.Append((int)wsudo::exec::privilege_t::mic, L"Mandatory Integrity Control");
box.Append((int)wsudo::exec::privilege_t::basic, L"Basic Inheritance Mode");
if (elevated) {
box.Append((int)wsudo::exec::privilege_t::standard, L"Not Elevated (UAC)", true);
box.Append((int)wsudo::exec::privilege_t::standard, L"Standard", true);
box.Append((int)wsudo::exec::privilege_t::elevated, L"Administrator");
box.Append((int)wsudo::exec::privilege_t::system, L"System");
box.Append((int)wsudo::exec::privilege_t::trustedinstaller, L"TrustedInstaller");
} else {
box.Append((int)wsudo::exec::privilege_t::standard, L"Not Elevated (UAC)");
box.Append((int)wsudo::exec::privilege_t::standard, L"Standard");
box.Append((int)wsudo::exec::privilege_t::elevated, L"Administrator", true);
}
HMENU hSystemMenu = ::GetSystemMenu(hWnd, FALSE);
Expand Down
36 changes: 22 additions & 14 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,33 +83,41 @@ wsudo is the console version of Privexec/AppExec. The detailed help is as follow
**wsudo usage:**

```txt
wsudo 😋 ♥ run the program with the specified permissions
wsudo 💖 5.0 run the program with the specified permissions
usage: wsudo command args...
-v|--version print version and exit
-h|--help print help information and exit
-V|--verbose Make the operation more talkative
-c|--cwd Use a working directory to launch the process.
-e|--env Use specific environment variables to start child processes.
-n|--nui Starts a separate window to run a specified program or command.
-H|--hide Hide child process window. not wait. (CREATE_NO_WINDOW)
-w|--wait Start application and wait for it to terminate.
-u|--user run as user (optional), support '-uX', '-u X', '--user=X', '--user X'
Supported user categories (Ignore case):
AppContainer MIC NoElevated
Administrator System TrustedInstaller
AppContainer MIC Basic
Standard Administrator System
TrustedInstaller
-n|--new-console Starts a separate window to run a specified program or command.
-H|--hide Hide child process window. not wait. (CREATE_NO_WINDOW)
-w|--wait Start application and wait for it to terminate.
-V|--verbose Make the operation more talkative
-x|--appx AppContainer AppManifest file path
-c|--cwd Use a working directory to launch the process.
-e|--env Set Environment Variable.
-L|--lpac Less Privileged AppContainer mode.
--disable-alias Disable Privexec alias, By default, if Privexec exists alias, use it.
--appname Set AppContainer Name
--appid Set AppContainer ID name (compatible --appname)
Select user can use the following flags:
|-a AppContainer |-M Mandatory Integrity Control|-U No Elevated(UAC)|
|-A Administrator |-S System |-T TrustedInstaller|
-a|--appcontainer AppContainer
-M|--mic Mandatory Integrity Control
-B|--basic Basic execution, permission inheritance mode (default)
-U|--standard Standard user no elevated (UAC)
-A|--administrator Administrator
-S|--system System
-T|--ti TrustedInstaller
Example:
wsudo -A "%SYSTEMROOT%/System32/WindowsPowerShell/v1.0/powershell.exe" -NoProfile
wsudo -A pwsh -NoProfile
wsudo -T cmd
wsudo -U -V --env CURL_SSL_BACKEND=schannel curl --verbose -I https://nghttp2.org
wsudo -U -V -eCURL_SSL_BACKEND=schannel curl --verbose -I https://nghttp2.org
wsudo -U -V CURL_SSL_BACKEND=schannel curl --verbose -I https://nghttp2.org
Builtin 'alias' command:
wsudo alias add ehs "notepad %SYSTEMROOT%/System32/drivers/etc/hosts" "Edit Hosts"
Expand Down
37 changes: 22 additions & 15 deletions ReadMe.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,38 +78,45 @@ AppExec 是一个启动 AppContainer 进程的程序,有一些开发者使用
wsudo 是 Privexec/AppExec 的控制台版本,详细使用帮助如下:

```txt
wsudo 😋 ♥ run the program with the specified permissions
wsudo 💖 5.0 run the program with the specified permissions
usage: wsudo command args...
-v|--version print version and exit
-h|--help print help information and exit
-V|--verbose Make the operation more talkative
-c|--cwd Use a working directory to launch the process.
-e|--env Use specific environment variables to start child processes.
-n|--nui Starts a separate window to run a specified program or command.
-H|--hide Hide child process window. not wait. (CREATE_NO_WINDOW)
-w|--wait Start application and wait for it to terminate.
-u|--user run as user (optional), support '-uX', '-u X', '--user=X', '--user X'
Supported user categories (Ignore case):
AppContainer MIC NoElevated
Administrator System TrustedInstaller
AppContainer MIC Basic
Standard Administrator System
TrustedInstaller
-n|--new-console Starts a separate window to run a specified program or command.
-H|--hide Hide child process window. not wait. (CREATE_NO_WINDOW)
-w|--wait Start application and wait for it to terminate.
-V|--verbose Make the operation more talkative
-x|--appx AppContainer AppManifest file path
-c|--cwd Use a working directory to launch the process.
-e|--env Set Environment Variable.
-L|--lpac Less Privileged AppContainer mode.
--disable-alias Disable Privexec alias, By default, if Privexec exists alias, use it.
--appname Set AppContainer Name
--appid Set AppContainer ID name (compatible --appname)
Select user can use the following flags:
|-a AppContainer |-M Mandatory Integrity Control|-U No Elevated(UAC)|
|-A Administrator |-S System |-T TrustedInstaller|
-a|--appcontainer AppContainer
-M|--mic Mandatory Integrity Control
-B|--basic Basic execution, permission inheritance mode (default)
-U|--standard Standard user no elevated (UAC)
-A|--administrator Administrator
-S|--system System
-T|--ti TrustedInstaller
Example:
wsudo -A "%SYSTEMROOT%/System32/WindowsPowerShell/v1.0/powershell.exe" -NoProfile
wsudo -A pwsh -NoProfile
wsudo -T cmd
wsudo -U -V --env CURL_SSL_BACKEND=schannel curl --verbose -I https://nghttp2.org
wsudo -U -V -eCURL_SSL_BACKEND=schannel curl --verbose -I https://nghttp2.org
wsudo -U -V CURL_SSL_BACKEND=schannel curl --verbose -I https://nghttp2.org
Builtin 'alias' command:
wsudo alias add ehs "notepad %SYSTEMROOT%/System32/drivers/etc/hosts" "Edit Hosts"
wsudo alias delete ehs
```

Privexec, AppExec, wsudo 启动命令时,命令行和和启动目录支持通过 `ExpandEnvironmentString` 推导.
Expand Down
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@
1. Privexec (GUI) AppContainer support Restricted Capabilities.
`Recommended Capabilities` can be selected at the same time as `Appmanifest`, the `Capabilities `will be merged
2. Privexec (GUI) Support Dropfiles. Appx edit box accept `*.xml;*.appmanifest` if it is activated. Command edit box accept other files.

## 2022-07-22

1. wsudo -U will create a process without privilege escalation. If it is currently running under the System account, it will fail to start the Store App with reduced privileges.(wsudo -U 会创建未提权的进程,如果当前运行在 System 账户下,降权启动 Store App 会失败。)
2. wsudo add -B --basic as default (permission inheritance mode)(wsudo 添加 `-B` `--basic` 作为默认执行模式,即继承父进程权限,而 -U 则总是启动未提权的进程。)
43 changes: 22 additions & 21 deletions lib/exec/elevator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,32 @@
#include <wtsapi32.h>

namespace wsudo::exec {

// bela::EqualsIgnoreCase
[[maybe_unused]] constexpr std::wstring_view WinLogonName = L"winlogon.exe";
// Get Current Process SessionID and Enable SeDebugPrivilege
bool PrepareElevate(DWORD &sid, bela::error_code &ec) {
bool prepare_elevate(DWORD &sid, bela::error_code &ec) {
if (!IsUserAdministratorsGroup()) {
ec = bela::make_error_code(1, L"current process not runing in administrator");
return false;
}
auto hToken = INVALID_HANDLE_VALUE;
constexpr DWORD flags = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY;
if (OpenProcessToken(GetCurrentProcess(), flags, &hToken) != TRUE) {
ec = bela::make_system_error_code(L"PrepareElevate<OpenProcessToken> ");
ec = bela::make_system_error_code(L"prepare_elevate<OpenProcessToken> ");
return false;
}
auto closer = bela::finally([&] { CloseHandle(hToken); });
DWORD Length = 0;
if (GetTokenInformation(hToken, TokenSessionId, &sid, sizeof(DWORD), &Length) != TRUE) {
ec = bela::make_system_error_code(L"PrepareElevate<GetTokenInformation> ");
ec = bela::make_system_error_code(L"prepare_elevate<GetTokenInformation> ");
return false;
}
TOKEN_PRIVILEGES tp;
LUID luid;

if (::LookupPrivilegeValueW(nullptr, SE_DEBUG_NAME, &luid) != TRUE) {

ec = bela::make_system_error_code(L"PrepareElevate<LookupPrivilegeValueW> ");
ec = bela::make_system_error_code(L"prepare_elevate<LookupPrivilegeValueW> ");
return false;
}

Expand All @@ -38,17 +38,17 @@ bool PrepareElevate(DWORD &sid, bela::error_code &ec) {
// Enable the privilege or disable all privileges.

if (::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr) != TRUE) {
ec = bela::make_system_error_code(L"PrepareElevate<AdjustTokenPrivileges> ");
ec = bela::make_system_error_code(L"prepare_elevate<AdjustTokenPrivileges> ");
return false;
}
if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
ec = bela::make_system_error_code(L"PrepareElevate<AdjustTokenPrivileges> ");
ec = bela::make_system_error_code(L"prepare_elevate<AdjustTokenPrivileges> ");
return false;
}
return true;
}

bool PrivilegesEnableAll(HANDLE hToken) {
bool privileges_enable_all(HANDLE hToken) {
if (hToken == INVALID_HANDLE_VALUE) {
return false;
}
Expand All @@ -72,9 +72,9 @@ bool PrivilegesEnableAll(HANDLE hToken) {
return (AdjustTokenPrivileges(hToken, FALSE, privs, 0, nullptr, nullptr) == TRUE);
}

bool PrivilegesEnableView(HANDLE hToken, const PrivilegeView *pv) {
bool privileges_view_enabled(HANDLE hToken, const privilege_view *pv) {
if (pv == nullptr) {
return PrivilegesEnableAll(hToken);
return privileges_enable_all(hToken);
}
for (const auto lpszPrivilege : pv->privis) {
TOKEN_PRIVILEGES tp;
Expand All @@ -99,22 +99,22 @@ bool PrivilegesEnableView(HANDLE hToken, const PrivilegeView *pv) {
return true;
}

bool Elevator::elevateimitate(bela::error_code &ec) {
bool PermissionAdjuster::elevate_imitate(bela::error_code &ec) {
HANDLE hExistingToken = INVALID_HANDLE_VALUE;
auto hProcess = ::OpenProcess(MAXIMUM_ALLOWED, FALSE, pid);
if (hProcess == INVALID_HANDLE_VALUE) {
ec = bela::make_system_error_code(L"Elevator::elevateimitate<OpenProcess> ");
ec = bela::make_system_error_code(L"PermissionAdjuster::elevate_imitate<OpenProcess> ");
return false;
}
auto hpdeleter = bela::finally([&] { CloseHandle(hProcess); });
if (OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &hExistingToken) != TRUE) {
ec = bela::make_system_error_code(L"Elevator::elevateimitate<OpenProcessToken> ");
ec = bela::make_system_error_code(L"PermissionAdjuster::elevate_imitate<OpenProcessToken> ");
return false;
}
auto htdeleter = bela::finally([&] { CloseHandle(hExistingToken); });
if (DuplicateTokenEx(hExistingToken, MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenImpersonation, &hToken) !=
TRUE) {
ec = bela::make_system_error_code(L"Elevator::elevateimitate<DuplicateTokenEx> ");
ec = bela::make_system_error_code(L"PermissionAdjuster::elevate_imitate<DuplicateTokenEx> ");
return false;
}
return true;
Expand Down Expand Up @@ -154,23 +154,24 @@ bool GetCurrentSessionId(DWORD &dwSessionId) {
}

// Improve self-generated permissions
bool Elevator::elevate(const PrivilegeView *pv, bela::error_code &ec) {
if (!PrepareElevate(sid, ec)) {
bool PermissionAdjuster::Elevate(const privilege_view *pv, bela::error_code &ec) {
if (!prepare_elevate(sid, ec)) {
return false;
}
if (!LookupSystemProcess(sid, pid)) {
ec = bela::make_error_code(1, L"Elevator::elevate unable lookup winlogon process pid");
ec = bela::make_error_code(1, L"Elevator::Elevate unable lookup winlogon process pid");
return false;
}
if (!elevateimitate(ec)) {
if (!elevate_imitate(ec)) {
return false;
}
if (!PrivilegesEnableView(hToken, pv)) {
ec = bela::make_error_code(1, L"Elevator::elevate unable enable privileges: ", pv == nullptr ? L"all" : pv->dump());
if (!privileges_view_enabled(hToken, pv)) {
ec = bela::make_error_code(1, L"Elevator::Elevate unable enable privileges: ",
pv == nullptr ? L"all" : pv->format());
return false;
}
if (SetThreadToken(nullptr, hToken) != TRUE) {
ec = bela::make_error_code(1, L"Elevator::elevate<SetThreadToken> ");
ec = bela::make_error_code(1, L"Elevator::Elevate<SetThreadToken> ");
return false;
}
return true;
Expand Down

0 comments on commit 99402db

Please sign in to comment.