Skip to content

Commit 70e869d

Browse files
committed
add sudo utility
1 parent e2911c6 commit 70e869d

File tree

8 files changed

+431
-0
lines changed

8 files changed

+431
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
.vs/
22
bin/
33
obj/
4+
Release/
5+
Debug/
6+
x64/
7+
*.aps
8+
*.vcxproj.user

FunUtils.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirBrowser", "DirBrowser\Di
99
EndProject
1010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "separate-console", "separate-console\separate-console.csproj", "{4A112556-38F8-473B-9BA1-A8FA58338FD9}"
1111
EndProject
12+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sudo", "sudo\sudo.vcxproj", "{98578377-F8C7-4851-B746-11F7243AAAFA}"
13+
EndProject
1214
Global
1315
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1416
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
2729
{4A112556-38F8-473B-9BA1-A8FA58338FD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
2830
{4A112556-38F8-473B-9BA1-A8FA58338FD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
2931
{4A112556-38F8-473B-9BA1-A8FA58338FD9}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{98578377-F8C7-4851-B746-11F7243AAAFA}.Debug|Any CPU.ActiveCfg = Debug|Win32
33+
{98578377-F8C7-4851-B746-11F7243AAAFA}.Debug|Any CPU.Build.0 = Debug|Win32
34+
{98578377-F8C7-4851-B746-11F7243AAAFA}.Release|Any CPU.ActiveCfg = Release|Win32
35+
{98578377-F8C7-4851-B746-11F7243AAAFA}.Release|Any CPU.Build.0 = Release|Win32
3036
EndGlobalSection
3137
GlobalSection(SolutionProperties) = preSolution
3238
HideSolutionNode = FALSE

sudo/resource.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//{{NO_DEPENDENCIES}}
2+
// Microsoft Visual C++ generated include file.
3+
// Used by resource.rc
4+
//
5+
#define IDI_ICON1 107
6+
#define IDC_BUTTON3 1003
7+
8+
// Next default values for new objects
9+
//
10+
#ifdef APSTUDIO_INVOKED
11+
#ifndef APSTUDIO_READONLY_SYMBOLS
12+
#define _APS_NEXT_RESOURCE_VALUE 108
13+
#define _APS_NEXT_COMMAND_VALUE 40001
14+
#define _APS_NEXT_CONTROL_VALUE 1002
15+
#define _APS_NEXT_SYMED_VALUE 101
16+
#endif
17+
#endif

sudo/resource.rc

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Microsoft Visual C++ generated resource script.
2+
//
3+
#pragma code_page(65001)
4+
5+
#include "resource.h"
6+
7+
#define APSTUDIO_READONLY_SYMBOLS
8+
/////////////////////////////////////////////////////////////////////////////
9+
//
10+
// Generated from the TEXTINCLUDE 2 resource.
11+
//
12+
#include "winres.h"
13+
14+
/////////////////////////////////////////////////////////////////////////////
15+
#undef APSTUDIO_READONLY_SYMBOLS
16+
17+
/////////////////////////////////////////////////////////////////////////////
18+
// Neutral resources
19+
20+
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
21+
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
22+
23+
#ifdef APSTUDIO_INVOKED
24+
/////////////////////////////////////////////////////////////////////////////
25+
//
26+
// TEXTINCLUDE
27+
//
28+
29+
1 TEXTINCLUDE
30+
BEGIN
31+
"resource.h\0"
32+
END
33+
34+
2 TEXTINCLUDE
35+
BEGIN
36+
"#include ""winres.h""\r\n"
37+
"\0"
38+
END
39+
40+
3 TEXTINCLUDE
41+
BEGIN
42+
"\r\n"
43+
"\0"
44+
END
45+
46+
#endif // APSTUDIO_INVOKED
47+
48+
49+
/////////////////////////////////////////////////////////////////////////////
50+
//
51+
// Version
52+
//
53+
54+
VS_VERSION_INFO VERSIONINFO
55+
FILEVERSION 1,0,0,0
56+
PRODUCTVERSION 1,0,0,0
57+
FILEFLAGSMASK 0x3fL
58+
#ifdef _DEBUG
59+
FILEFLAGS 0x1L
60+
#else
61+
FILEFLAGS 0x0L
62+
#endif
63+
FILEOS 0x40004L
64+
FILETYPE 0x1L
65+
FILESUBTYPE 0x0L
66+
BEGIN
67+
BLOCK "StringFileInfo"
68+
BEGIN
69+
BLOCK "040904b0"
70+
BEGIN
71+
VALUE "FileDescription", "sudo"
72+
VALUE "FileVersion", "1.0.0.0"
73+
VALUE "LegalCopyright", "mrexodia.re"
74+
VALUE "ProductName", "sudo"
75+
VALUE "ProductVersion", "1.0.0.0"
76+
END
77+
END
78+
BLOCK "VarFileInfo"
79+
BEGIN
80+
VALUE "Translation", 0x409, 1200
81+
END
82+
END
83+
84+
#endif // Neutral resources
85+
/////////////////////////////////////////////////////////////////////////////
86+
87+
88+
/////////////////////////////////////////////////////////////////////////////
89+
// Neutral (Default) (unknown sub-lang: 0x8) resources
90+
91+
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ZZZ)
92+
LANGUAGE LANG_NEUTRAL, 0x8
93+
94+
/////////////////////////////////////////////////////////////////////////////
95+
//
96+
// Icon
97+
//
98+
99+
// Icon with lowest ID value placed first to ensure application icon
100+
// remains consistent on all systems.
101+
IDI_ICON1 ICON "uac.ico"
102+
103+
#endif // Neutral (Default) (unknown sub-lang: 0x8) resources
104+
/////////////////////////////////////////////////////////////////////////////
105+
106+
107+
108+
#ifndef APSTUDIO_INVOKED
109+
/////////////////////////////////////////////////////////////////////////////
110+
//
111+
// Generated from the TEXTINCLUDE 3 resource.
112+
//
113+
114+
115+
/////////////////////////////////////////////////////////////////////////////
116+
#endif // not APSTUDIO_INVOKED
117+

sudo/sudo.cpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#include <Windows.h>
2+
#include <cstdio>
3+
#include <vector>
4+
5+
static bool IsProcessElevated()
6+
{
7+
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
8+
PSID SecurityIdentifier;
9+
if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &SecurityIdentifier))
10+
return 0;
11+
12+
BOOL IsAdminMember;
13+
if (!CheckTokenMembership(NULL, SecurityIdentifier, &IsAdminMember))
14+
IsAdminMember = FALSE;
15+
16+
FreeSid(SecurityIdentifier);
17+
return !!IsAdminMember;
18+
}
19+
20+
class RedirectWow
21+
{
22+
PVOID oldValue = NULL;
23+
BOOL(WINAPI* wow64DisableRedirection)(PVOID);
24+
BOOL(WINAPI* wow64RevertRedirection)(PVOID);
25+
26+
public:
27+
RedirectWow()
28+
{
29+
wow64DisableRedirection = (decltype(wow64DisableRedirection))GetProcAddress(GetModuleHandleW(L"kernel32"), "Wow64DisableWow64FsRedirection");
30+
wow64RevertRedirection = (decltype(wow64RevertRedirection))GetProcAddress(GetModuleHandleW(L"kernel32"), "Wow64RevertWow64FsRedirection");
31+
if (wow64DisableRedirection)
32+
wow64DisableRedirection(&oldValue);
33+
}
34+
35+
RedirectWow(const RedirectWow&) = delete;
36+
RedirectWow(RedirectWow&&) = delete;
37+
RedirectWow& operator=(const RedirectWow&) = delete;
38+
39+
~RedirectWow()
40+
{
41+
if (oldValue)
42+
wow64RevertRedirection(oldValue);
43+
}
44+
};
45+
46+
int wmain(int argc, wchar_t* argv[])
47+
{
48+
RedirectWow redirectWow;
49+
50+
// Helper functions for functioning printf
51+
auto printf = [](const char* fmt, auto... args)
52+
{
53+
char msg[1024] = "";
54+
sprintf_s(msg, fmt, args...);
55+
DWORD w = 0;
56+
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, strlen(msg), &w, nullptr);
57+
};
58+
auto puts = [&printf](const char* str)
59+
{
60+
printf("%s\n", str);
61+
};
62+
63+
// Get rid of application from command line
64+
auto commandLine = GetCommandLineW();
65+
{
66+
if (*commandLine == L'\"')
67+
{
68+
commandLine++;
69+
while (*commandLine++ != L'\"');
70+
commandLine++;
71+
}
72+
else
73+
{
74+
while (*commandLine != L' ' && *commandLine != L'\0')
75+
commandLine++;
76+
}
77+
while (*commandLine == L' ')
78+
commandLine++;
79+
if (!*commandLine)
80+
commandLine = nullptr;
81+
}
82+
83+
if (!IsProcessElevated())
84+
{
85+
// Restart sudo elevated
86+
SHELLEXECUTEINFOW ShExecInfo = { 0 };
87+
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
88+
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
89+
ShExecInfo.hwnd = GetConsoleWindow();
90+
ShExecInfo.lpVerb = L"runas";
91+
ShExecInfo.lpFile = argv[0];
92+
ShExecInfo.lpParameters = commandLine;
93+
ShExecInfo.lpDirectory = NULL;
94+
ShExecInfo.nShow = SW_HIDE;
95+
ShExecInfo.hInstApp = NULL;
96+
if (!ShellExecuteExW(&ShExecInfo))
97+
{
98+
auto lastError = GetLastError();
99+
if (lastError == ERROR_CANCELLED)
100+
puts("Elevation canceled by user");
101+
else
102+
printf("ShellExecuteExW failed (LastError: %u)\n", GetLastError());
103+
return EXIT_FAILURE;
104+
}
105+
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
106+
DWORD ExitCode = 0;
107+
if (!GetExitCodeProcess(ShExecInfo.hProcess, &ExitCode))
108+
ExitCode = 1;
109+
CloseHandle(ShExecInfo.hProcess);
110+
return ExitCode;
111+
}
112+
else
113+
{
114+
// Get rid of the hidden console and attach to the parent sudo's console
115+
FreeConsole();
116+
AttachConsole(ATTACH_PARENT_PROCESS);
117+
118+
// Construct final command line for cmd
119+
std::vector<wchar_t> finalCommandLine;
120+
auto append = [&finalCommandLine](const wchar_t* str)
121+
{
122+
auto length = wcslen(str);
123+
for (size_t i = 0; i < length; i++)
124+
finalCommandLine.push_back(str[i]);
125+
};
126+
if (commandLine)
127+
{
128+
append(L"cmd.exe /C ");
129+
append(commandLine);
130+
}
131+
else
132+
{
133+
append(L"cmd.exe");
134+
}
135+
finalCommandLine.push_back(L'\0');
136+
137+
// Create cmd instance
138+
STARTUPINFOW si = { sizeof(si) };
139+
PROCESS_INFORMATION pi = { 0 };
140+
if (!CreateProcessW(nullptr, finalCommandLine.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi))
141+
{
142+
printf("CreateProcessW failed (LastError: %u)\n", GetLastError());
143+
return EXIT_FAILURE;
144+
}
145+
WaitForSingleObject(pi.hProcess, INFINITE);
146+
DWORD ExitCode = 0;
147+
if (!GetExitCodeProcess(pi.hProcess, &ExitCode))
148+
ExitCode = 1;
149+
CloseHandle(pi.hProcess);
150+
CloseHandle(pi.hThread);
151+
return ExitCode;
152+
}
153+
}

0 commit comments

Comments
 (0)