diff --git a/.gitignore b/.gitignore index 07b26ed..e8259e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ .vs/ bin/ obj/ +Release/ +Debug/ +x64/ +*.aps +*.vcxproj.user diff --git a/FunUtils.sln b/FunUtils.sln index c1166d9..5d29e20 100644 --- a/FunUtils.sln +++ b/FunUtils.sln @@ -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 @@ -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 diff --git a/sudo/resource.h b/sudo/resource.h new file mode 100644 index 0000000..3f027e8 --- /dev/null +++ b/sudo/resource.h @@ -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 diff --git a/sudo/resource.rc b/sudo/resource.rc new file mode 100644 index 0000000..1c5890e --- /dev/null +++ b/sudo/resource.rc @@ -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 + diff --git a/sudo/sudo.cpp b/sudo/sudo.cpp new file mode 100644 index 0000000..7029470 --- /dev/null +++ b/sudo/sudo.cpp @@ -0,0 +1,153 @@ +#include +#include +#include + +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 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; + } +} \ No newline at end of file diff --git a/sudo/sudo.vcxproj b/sudo/sudo.vcxproj new file mode 100644 index 0000000..7edbc53 --- /dev/null +++ b/sudo/sudo.vcxproj @@ -0,0 +1,96 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + 16.0 + Win32Proj + {98578377-f8c7-4851-b746-11f7243aaafa} + sudo + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sudo/sudo.vcxproj.filters b/sudo/sudo.vcxproj.filters new file mode 100644 index 0000000..5b3fb0d --- /dev/null +++ b/sudo/sudo.vcxproj.filters @@ -0,0 +1,37 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/sudo/uac.ico b/sudo/uac.ico new file mode 100644 index 0000000..14e21e1 Binary files /dev/null and b/sudo/uac.ico differ