Skip to content

Commit

Permalink
add sudo utility
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexodia committed May 23, 2020
1 parent e2911c6 commit 70e869d
Show file tree
Hide file tree
Showing 8 changed files with 431 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.vs/
bin/
obj/
Release/
Debug/
x64/
*.aps
*.vcxproj.user
6 changes: 6 additions & 0 deletions FunUtils.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DirBrowser", "DirBrowser\Di
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "separate-console", "separate-console\separate-console.csproj", "{4A112556-38F8-473B-9BA1-A8FA58338FD9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sudo", "sudo\sudo.vcxproj", "{98578377-F8C7-4851-B746-11F7243AAAFA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -27,6 +29,10 @@ Global
{4A112556-38F8-473B-9BA1-A8FA58338FD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A112556-38F8-473B-9BA1-A8FA58338FD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A112556-38F8-473B-9BA1-A8FA58338FD9}.Release|Any CPU.Build.0 = Release|Any CPU
{98578377-F8C7-4851-B746-11F7243AAAFA}.Debug|Any CPU.ActiveCfg = Debug|Win32
{98578377-F8C7-4851-B746-11F7243AAAFA}.Debug|Any CPU.Build.0 = Debug|Win32
{98578377-F8C7-4851-B746-11F7243AAAFA}.Release|Any CPU.ActiveCfg = Release|Win32
{98578377-F8C7-4851-B746-11F7243AAAFA}.Release|Any CPU.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
17 changes: 17 additions & 0 deletions sudo/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by resource.rc
//
#define IDI_ICON1 107
#define IDC_BUTTON3 1003

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1002
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
117 changes: 117 additions & 0 deletions sudo/resource.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Microsoft Visual C++ generated resource script.
//
#pragma code_page(65001)

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Neutral resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "sudo"
VALUE "FileVersion", "1.0.0.0"
VALUE "LegalCopyright", "mrexodia.re"
VALUE "ProductName", "sudo"
VALUE "ProductVersion", "1.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// Neutral (Default) (unknown sub-lang: 0x8) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ZZZ)
LANGUAGE LANG_NEUTRAL, 0x8

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "uac.ico"

#endif // Neutral (Default) (unknown sub-lang: 0x8) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

153 changes: 153 additions & 0 deletions sudo/sudo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include <Windows.h>
#include <cstdio>
#include <vector>

static bool IsProcessElevated()
{
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID SecurityIdentifier;
if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &SecurityIdentifier))
return 0;

BOOL IsAdminMember;
if (!CheckTokenMembership(NULL, SecurityIdentifier, &IsAdminMember))
IsAdminMember = FALSE;

FreeSid(SecurityIdentifier);
return !!IsAdminMember;
}

class RedirectWow
{
PVOID oldValue = NULL;
BOOL(WINAPI* wow64DisableRedirection)(PVOID);
BOOL(WINAPI* wow64RevertRedirection)(PVOID);

public:
RedirectWow()
{
wow64DisableRedirection = (decltype(wow64DisableRedirection))GetProcAddress(GetModuleHandleW(L"kernel32"), "Wow64DisableWow64FsRedirection");
wow64RevertRedirection = (decltype(wow64RevertRedirection))GetProcAddress(GetModuleHandleW(L"kernel32"), "Wow64RevertWow64FsRedirection");
if (wow64DisableRedirection)
wow64DisableRedirection(&oldValue);
}

RedirectWow(const RedirectWow&) = delete;
RedirectWow(RedirectWow&&) = delete;
RedirectWow& operator=(const RedirectWow&) = delete;

~RedirectWow()
{
if (oldValue)
wow64RevertRedirection(oldValue);
}
};

int wmain(int argc, wchar_t* argv[])
{
RedirectWow redirectWow;

// Helper functions for functioning printf
auto printf = [](const char* fmt, auto... args)
{
char msg[1024] = "";
sprintf_s(msg, fmt, args...);
DWORD w = 0;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, strlen(msg), &w, nullptr);
};
auto puts = [&printf](const char* str)
{
printf("%s\n", str);
};

// Get rid of application from command line
auto commandLine = GetCommandLineW();
{
if (*commandLine == L'\"')
{
commandLine++;
while (*commandLine++ != L'\"');
commandLine++;
}
else
{
while (*commandLine != L' ' && *commandLine != L'\0')
commandLine++;
}
while (*commandLine == L' ')
commandLine++;
if (!*commandLine)
commandLine = nullptr;
}

if (!IsProcessElevated())
{
// Restart sudo elevated
SHELLEXECUTEINFOW ShExecInfo = { 0 };
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = GetConsoleWindow();
ShExecInfo.lpVerb = L"runas";
ShExecInfo.lpFile = argv[0];
ShExecInfo.lpParameters = commandLine;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
if (!ShellExecuteExW(&ShExecInfo))
{
auto lastError = GetLastError();
if (lastError == ERROR_CANCELLED)
puts("Elevation canceled by user");
else
printf("ShellExecuteExW failed (LastError: %u)\n", GetLastError());
return EXIT_FAILURE;
}
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
DWORD ExitCode = 0;
if (!GetExitCodeProcess(ShExecInfo.hProcess, &ExitCode))
ExitCode = 1;
CloseHandle(ShExecInfo.hProcess);
return ExitCode;
}
else
{
// Get rid of the hidden console and attach to the parent sudo's console
FreeConsole();
AttachConsole(ATTACH_PARENT_PROCESS);

// Construct final command line for cmd
std::vector<wchar_t> finalCommandLine;
auto append = [&finalCommandLine](const wchar_t* str)
{
auto length = wcslen(str);
for (size_t i = 0; i < length; i++)
finalCommandLine.push_back(str[i]);
};
if (commandLine)
{
append(L"cmd.exe /C ");
append(commandLine);
}
else
{
append(L"cmd.exe");
}
finalCommandLine.push_back(L'\0');

// Create cmd instance
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
if (!CreateProcessW(nullptr, finalCommandLine.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi))
{
printf("CreateProcessW failed (LastError: %u)\n", GetLastError());
return EXIT_FAILURE;
}
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD ExitCode = 0;
if (!GetExitCodeProcess(pi.hProcess, &ExitCode))
ExitCode = 1;
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return ExitCode;
}
}
Loading

0 comments on commit 70e869d

Please sign in to comment.