mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
89a3546876
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@316 21ef857c-d57f-4fe0-8362-d861dc6d29cd
1386 lines
49 KiB
C#
1386 lines
49 KiB
C#
/*
|
|
* Process Hacker
|
|
*
|
|
* Copyright (C) 2008 wj32
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.ComponentModel;
|
|
|
|
namespace ProcessHacker
|
|
{
|
|
/// <summary>
|
|
/// Provides interfacing to the Win32 and Native APIs.
|
|
/// </summary>
|
|
public partial class Win32
|
|
{
|
|
public unsafe class Unsafe
|
|
{
|
|
/// <summary>
|
|
/// Converts a multi-string into a managed string array. A multi-string
|
|
/// consists of an array of null-terminated strings plus an extra null to
|
|
/// terminate the array.
|
|
/// </summary>
|
|
/// <param name="ptr">The pointer to the array.</param>
|
|
/// <returns>A string array.</returns>
|
|
public static string[] GetMultiString(IntPtr ptr)
|
|
{
|
|
List<string> list = new List<string>();
|
|
char* chptr = (char*)ptr.ToPointer();
|
|
StringBuilder currentString = new StringBuilder();
|
|
|
|
while (true)
|
|
{
|
|
while (*chptr != 0)
|
|
{
|
|
currentString.Append(*chptr);
|
|
chptr++;
|
|
}
|
|
|
|
string str = currentString.ToString();
|
|
|
|
if (str == "")
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
list.Add(str);
|
|
currentString = new StringBuilder();
|
|
}
|
|
}
|
|
|
|
return list.ToArray();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a generic Windows handle.
|
|
/// </summary>
|
|
public class Win32Handle : IDisposable
|
|
{
|
|
private bool _owned = true;
|
|
private bool _closed = false;
|
|
private int _handle;
|
|
|
|
public static implicit operator int(Win32Handle handle)
|
|
{
|
|
return handle.Handle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new, invalid handle. You must set the handle using the Handle property.
|
|
/// </summary>
|
|
protected Win32Handle()
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Creates a new handle using the specified value. The handle will be closed when
|
|
/// this object is disposed or garbage-collected.
|
|
/// </summary>
|
|
/// <param name="handle">The handle value.</param>
|
|
public Win32Handle(int handle)
|
|
{
|
|
_handle = handle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new handle using the specified value. If owned is set to false, the
|
|
/// handle will not be closed automatically.
|
|
/// </summary>
|
|
/// <param name="handle">The handle value.</param>
|
|
/// <param name="owned">Specifies whether the handle will be closed automatically.</param>
|
|
public Win32Handle(int handle, bool owned)
|
|
{
|
|
_handle = handle;
|
|
_owned = owned;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether this handle is closed.
|
|
/// </summary>
|
|
public bool Closed
|
|
{
|
|
get { return _closed; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether the handle will be automatically closed.
|
|
/// </summary>
|
|
public bool Owned
|
|
{
|
|
get { return _owned; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the handle value.
|
|
/// </summary>
|
|
public int Handle
|
|
{
|
|
get { return _handle; }
|
|
protected set { _handle = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Closes the handle. This method must not be called directly; instead,
|
|
/// override this method in a derived class if your handle must be closed
|
|
/// with a method other than CloseHandle.
|
|
/// </summary>
|
|
protected virtual void Close()
|
|
{
|
|
CloseHandle(_handle);
|
|
}
|
|
|
|
~Win32Handle()
|
|
{
|
|
this.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Closes the handle.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
if (!_closed && _owned)
|
|
{
|
|
_closed = true;
|
|
Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a Windows object that contains a token.
|
|
/// </summary>
|
|
public interface IWithToken
|
|
{
|
|
/// <summary>
|
|
/// Opens and returns the object's token.
|
|
/// </summary>
|
|
/// <returns>A handle to the token.</returns>
|
|
TokenHandle GetToken();
|
|
|
|
/// <summary>
|
|
/// Opens and returns the object's token.
|
|
/// </summary>
|
|
/// <param name="access">Specifies the desired access to the token.</param>
|
|
/// <returns>A handle to the token.</returns>
|
|
TokenHandle GetToken(TOKEN_RIGHTS access);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a handle to a Windows process.
|
|
/// </summary>
|
|
public class ProcessHandle : Win32Handle, IWithToken
|
|
{
|
|
/// <summary>
|
|
/// Creates a process handle using an existing handle.
|
|
/// The handle will not be closed automatically.
|
|
/// </summary>
|
|
/// <param name="Handle">The handle value.</param>
|
|
/// <returns></returns>
|
|
public static ProcessHandle FromHandle(int Handle)
|
|
{
|
|
return new ProcessHandle(Handle, false);
|
|
}
|
|
|
|
private ProcessHandle(int Handle, bool Owned)
|
|
: base(Handle, Owned)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Creates a new process handle.
|
|
/// </summary>
|
|
/// <param name="PID">The ID of the process to open.</param>
|
|
public ProcessHandle(int PID)
|
|
: this(PID, PROCESS_RIGHTS.PROCESS_ALL_ACCESS)
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Creates a new process handle.
|
|
/// </summary>
|
|
/// <param name="PID">The ID of the process to open.</param>
|
|
/// <param name="access">The desired access to the process.</param>
|
|
public ProcessHandle(int PID, PROCESS_RIGHTS access)
|
|
{
|
|
this.Handle = OpenProcess(access, 0, PID);
|
|
|
|
if (this.Handle == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Waits for the process.
|
|
/// </summary>
|
|
/// <param name="Timeout">The timeout of the wait.</param>
|
|
/// <returns>Either WAIT_OBJECT_0, WAIT_TIMEOUT or WAIT_FAILED.</returns>
|
|
public int Wait(int Timeout)
|
|
{
|
|
return WaitForSingleObject(this.Handle, Timeout);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Terminates the process.
|
|
/// </summary>
|
|
public void Terminate()
|
|
{
|
|
this.Terminate(0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Terminates the process, specifying the exit code.
|
|
/// </summary>
|
|
/// <param name="ExitCode">The exit code.</param>
|
|
public void Terminate(int ExitCode)
|
|
{
|
|
if (TerminateProcess(this.Handle, ExitCode) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens and returns a handle to the process' token.
|
|
/// </summary>
|
|
/// <returns>A handle to the process' token.</returns>
|
|
public TokenHandle GetToken()
|
|
{
|
|
return GetToken(TOKEN_RIGHTS.TOKEN_ALL_ACCESS);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens and returns a handle to the process' token.
|
|
/// </summary>
|
|
/// <param name="access">The desired access to the token.</param>
|
|
/// <returns>A handle to the process' token.</returns>
|
|
public TokenHandle GetToken(TOKEN_RIGHTS access)
|
|
{
|
|
return new TokenHandle(this, access);
|
|
}
|
|
}
|
|
|
|
public class ServiceHandle : Win32Handle
|
|
{
|
|
public static ServiceHandle FromHandle(int Handle)
|
|
{
|
|
return new ServiceHandle(Handle, false);
|
|
}
|
|
|
|
private ServiceHandle(int Handle, bool Owned)
|
|
: base(Handle, Owned)
|
|
{ }
|
|
|
|
public ServiceHandle(string ServiceName, SERVICE_RIGHTS access)
|
|
{
|
|
int manager = OpenSCManager(0, 0, SC_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
|
|
|
|
if (manager == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
this.Handle = OpenService(manager, ServiceName, access);
|
|
|
|
CloseServiceHandle(manager);
|
|
|
|
if (this.Handle == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public void Control(SERVICE_CONTROL control)
|
|
{
|
|
SERVICE_STATUS status = new SERVICE_STATUS();
|
|
|
|
if (ControlService(this.Handle, control, ref status) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
if (StartService(this.Handle, 0, 0) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public void Delete()
|
|
{
|
|
if (DeleteService(this.Handle) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
protected override void Close()
|
|
{
|
|
CloseServiceHandle(this.Handle);
|
|
}
|
|
}
|
|
|
|
public class ThreadHandle : Win32Handle, IWithToken
|
|
{
|
|
public static ThreadHandle FromHandle(int Handle)
|
|
{
|
|
return new ThreadHandle(Handle, false);
|
|
}
|
|
|
|
private ThreadHandle(int Handle, bool Owned)
|
|
: base(Handle, Owned)
|
|
{ }
|
|
|
|
public ThreadHandle(int TID, THREAD_RIGHTS access)
|
|
{
|
|
this.Handle = OpenThread(access, 0, TID);
|
|
|
|
if (this.Handle == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public int Wait(int Timeout)
|
|
{
|
|
return WaitForSingleObject(this.Handle, Timeout);
|
|
}
|
|
|
|
public void Suspend()
|
|
{
|
|
if (SuspendThread(this.Handle) == -1)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public void Resume()
|
|
{
|
|
if (ResumeThread(this.Handle) == -1)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public void Terminate()
|
|
{
|
|
this.Terminate(0);
|
|
}
|
|
|
|
public void Terminate(int ExitCode)
|
|
{
|
|
if (TerminateThread(this.Handle, ExitCode) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
public TokenHandle GetToken()
|
|
{
|
|
return GetToken(TOKEN_RIGHTS.TOKEN_ALL_ACCESS);
|
|
}
|
|
|
|
public TokenHandle GetToken(TOKEN_RIGHTS access)
|
|
{
|
|
return new TokenHandle(this, access);
|
|
}
|
|
}
|
|
|
|
public class TokenHandle : Win32Handle
|
|
{
|
|
public static TokenHandle FromHandle(int Handle)
|
|
{
|
|
return new TokenHandle(Handle, false);
|
|
}
|
|
|
|
private TokenHandle(int Handle, bool Owned)
|
|
: base(Handle, Owned)
|
|
{ }
|
|
|
|
public TokenHandle(ProcessHandle handle, TOKEN_RIGHTS access)
|
|
{
|
|
int h;
|
|
|
|
if (OpenProcessToken(handle.Handle, access, out h) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
this.Handle = h;
|
|
}
|
|
|
|
public TokenHandle(ThreadHandle handle, TOKEN_RIGHTS access)
|
|
{
|
|
int h;
|
|
|
|
if (OpenThreadToken(handle.Handle, access, false, out h) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
this.Handle = h;
|
|
}
|
|
|
|
public string GetUsername(bool IncludeDomain)
|
|
{
|
|
int retLen = 0;
|
|
|
|
GetTokenInformation(this.Handle, TOKEN_INFORMATION_CLASS.TokenUser, 0, 0, ref retLen);
|
|
|
|
IntPtr data = Marshal.AllocHGlobal(retLen);
|
|
|
|
try
|
|
{
|
|
if (GetTokenInformation(this.Handle, TOKEN_INFORMATION_CLASS.TokenUser, data,
|
|
retLen, ref retLen) == 0)
|
|
{
|
|
throw new Exception(Win32.GetLastErrorMessage());
|
|
}
|
|
|
|
TOKEN_USER user = PtrToStructure<TOKEN_USER>(data);
|
|
|
|
return GetAccountName(user.User.SID, IncludeDomain);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(data);
|
|
}
|
|
}
|
|
}
|
|
|
|
public delegate int EnumWindowsProc(int hwnd, int param);
|
|
public delegate int SymEnumSymbolsProc(SYMBOL_INFO pSymInfo, int SymbolSize, int UserContext);
|
|
public delegate int FunctionTableAccessProc64(int ProcessHandle, int AddrBase);
|
|
public delegate int GetModuleBaseProc64(int ProcessHandle, int Address);
|
|
|
|
public static Dictionary<byte, string> ObjectTypes = new Dictionary<byte, string>();
|
|
|
|
#region Consts
|
|
|
|
public const int ANYSIZE_ARRAY = 1;
|
|
public const int DONT_RESOLVE_DLL_REFERENCES = 0x1;
|
|
public const int ERROR_NO_MORE_ITEMS = 259;
|
|
public const int MAXIMUM_SUPPORTED_EXTENSION = 512;
|
|
public const int SEE_MASK_INVOKEIDLIST = 0xc;
|
|
public const uint SERVICE_NO_CHANGE = 0xffffffff;
|
|
public const uint SHGFI_ICON = 0x100;
|
|
public const uint SHGFI_LARGEICON = 0x0;
|
|
public const uint SHGFI_SMALLICON = 0x1;
|
|
public const int SID_SIZE = 0x1000;
|
|
public const int SIZE_OF_80387_REGISTERS = 72;
|
|
public const uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;
|
|
public const int SW_SHOW = 5;
|
|
public const int SYMBOL_NAME_MAXSIZE = 255;
|
|
public const int WAIT_ABANDONED = 0x80;
|
|
public const int WAIT_OBJECT_0 = 0x0;
|
|
public const int WAIT_TIMEOUT = 0x102;
|
|
|
|
#endregion
|
|
|
|
#region Errors
|
|
|
|
public static string GetErrorMessage(int ErrorCode)
|
|
{
|
|
try
|
|
{
|
|
throw new System.ComponentModel.Win32Exception(ErrorCode);
|
|
}
|
|
catch (System.ComponentModel.Win32Exception ex)
|
|
{
|
|
return ex.Message;
|
|
}
|
|
}
|
|
|
|
public static string GetLastErrorMessage()
|
|
{
|
|
return GetErrorMessage(Marshal.GetLastWin32Error());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Handles
|
|
|
|
public struct ObjectInformation
|
|
{
|
|
public OBJECT_BASIC_INFORMATION Basic;
|
|
public OBJECT_NAME_INFORMATION Name;
|
|
public string OrigName;
|
|
public string BestName;
|
|
public string TypeName;
|
|
}
|
|
|
|
public static SYSTEM_HANDLE_INFORMATION[] EnumHandles()
|
|
{
|
|
int length = 0x1000;
|
|
int retLength = 0;
|
|
int handles = 0;
|
|
IntPtr data = Marshal.AllocHGlobal(length);
|
|
SYSTEM_HANDLE_INFORMATION[] returnHandles;
|
|
|
|
while (ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS.SystemHandleInformation, data.ToInt32(),
|
|
length, ref retLength) == STATUS_INFO_LENGTH_MISMATCH)
|
|
{
|
|
length *= 2;
|
|
Marshal.FreeHGlobal(data);
|
|
data = Marshal.AllocHGlobal(length);
|
|
}
|
|
|
|
handles = Marshal.ReadInt32(data);
|
|
returnHandles = new SYSTEM_HANDLE_INFORMATION[handles];
|
|
|
|
for (int i = 0; i < handles; i++)
|
|
{
|
|
returnHandles[i] = PtrToStructure<SYSTEM_HANDLE_INFORMATION>(
|
|
new IntPtr(4 + data.ToInt32() + i * Marshal.SizeOf(typeof(SYSTEM_HANDLE_INFORMATION))));
|
|
}
|
|
|
|
Marshal.FreeHGlobal(data);
|
|
|
|
return returnHandles;
|
|
}
|
|
|
|
public static ObjectInformation GetHandleInfo(SYSTEM_HANDLE_INFORMATION handle)
|
|
{
|
|
using (ProcessHandle process = new ProcessHandle(handle.ProcessId, PROCESS_RIGHTS.PROCESS_DUP_HANDLE))
|
|
{
|
|
return GetHandleInfo(process, handle);
|
|
}
|
|
}
|
|
|
|
public static ObjectInformation GetHandleInfo(ProcessHandle process, SYSTEM_HANDLE_INFORMATION handle)
|
|
{
|
|
int object_handle = 0;
|
|
int retLength = 0;
|
|
|
|
if (ZwDuplicateObject(process.Handle, handle.Handle,
|
|
Program.CurrentProcess, ref object_handle, 0, 0, 0) != 0)
|
|
throw new Exception("Could not duplicate object!");
|
|
|
|
try
|
|
{
|
|
ObjectInformation info = new ObjectInformation();
|
|
|
|
ZwQueryObject(object_handle, OBJECT_INFORMATION_CLASS.ObjectBasicInformation,
|
|
0, 0, ref retLength);
|
|
|
|
if (retLength > 0)
|
|
{
|
|
IntPtr obiMem = Marshal.AllocHGlobal(retLength);
|
|
ZwQueryObject(object_handle, OBJECT_INFORMATION_CLASS.ObjectBasicInformation,
|
|
obiMem, retLength, ref retLength);
|
|
OBJECT_BASIC_INFORMATION obi = PtrToStructure<OBJECT_BASIC_INFORMATION>(obiMem);
|
|
Marshal.FreeHGlobal(obiMem);
|
|
info.Basic = obi;
|
|
}
|
|
|
|
if (ObjectTypes.ContainsKey(handle.ObjectTypeNumber))
|
|
{
|
|
info.TypeName = ObjectTypes[handle.ObjectTypeNumber];
|
|
}
|
|
else
|
|
{
|
|
ZwQueryObject(object_handle, OBJECT_INFORMATION_CLASS.ObjectTypeInformation,
|
|
0, 0, ref retLength);
|
|
|
|
if (retLength > 0)
|
|
{
|
|
IntPtr otiMem = Marshal.AllocHGlobal(retLength);
|
|
|
|
try
|
|
{
|
|
if (ZwQueryObject(object_handle, OBJECT_INFORMATION_CLASS.ObjectTypeInformation,
|
|
otiMem, retLength, ref retLength) != 0)
|
|
throw new Exception("ZwQueryObject failed");
|
|
OBJECT_TYPE_INFORMATION oti = PtrToStructure<OBJECT_TYPE_INFORMATION>(otiMem);
|
|
info.TypeName = ReadUnicodeString(oti.Name);
|
|
ObjectTypes.Add(handle.ObjectTypeNumber, info.TypeName);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(otiMem);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (info.TypeName == "File")
|
|
if ((int)handle.GrantedAccess == 0x0012019f)
|
|
throw new Exception("0x0012019f access is banned");
|
|
|
|
ZwQueryObject(object_handle, OBJECT_INFORMATION_CLASS.ObjectNameInformation,
|
|
0, 0, ref retLength);
|
|
|
|
if (retLength > 0)
|
|
{
|
|
IntPtr oniMem = Marshal.AllocHGlobal(retLength);
|
|
|
|
try
|
|
{
|
|
if (ZwQueryObject(object_handle, OBJECT_INFORMATION_CLASS.ObjectNameInformation,
|
|
oniMem, retLength, ref retLength) != 0)
|
|
throw new Exception("ZwQueryObject failed");
|
|
OBJECT_NAME_INFORMATION oni = PtrToStructure<OBJECT_NAME_INFORMATION>(oniMem);
|
|
|
|
info.OrigName = ReadUnicodeString(oni.Name);
|
|
info.Name = oni;
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(oniMem);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
switch (info.TypeName)
|
|
{
|
|
case "Key":
|
|
string hklmString = "\\registry\\machine";
|
|
string hkcrString = "\\registry\\machine\\software\\classes";
|
|
string hkcuString = "\\registry\\user\\" +
|
|
System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString().ToLower();
|
|
string hkcucrString = "\\registry\\user\\" +
|
|
System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString().ToLower() + "_classes";
|
|
string hkuString = "\\registry\\user";
|
|
|
|
if (info.OrigName.ToLower().StartsWith(hklmString))
|
|
info.BestName = "HKLM" + info.OrigName.Substring(hklmString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkcucrString))
|
|
info.BestName = "HKCU\\Software\\Classes" + info.OrigName.Substring(hkcucrString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkcuString))
|
|
info.BestName = "HKCU" + info.OrigName.Substring(hkcuString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkcrString))
|
|
info.BestName = "HKCR" + info.OrigName.Substring(hkcrString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkuString))
|
|
info.BestName = "HKU" + info.OrigName.Substring(hkuString.Length);
|
|
else
|
|
info.BestName = info.OrigName;
|
|
|
|
break;
|
|
|
|
case "Process":
|
|
{
|
|
int process_handle = 0;
|
|
int processId = 0;
|
|
|
|
if (ZwDuplicateObject(process.Handle, handle.Handle,
|
|
Program.CurrentProcess, ref process_handle,
|
|
(STANDARD_RIGHTS)PROCESS_RIGHTS.PROCESS_QUERY_INFORMATION, 0, 0) != 0)
|
|
throw new Exception("Could not duplicate process handle!");
|
|
|
|
try
|
|
{
|
|
if ((processId = GetProcessId(process_handle)) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
if (Program.HackerWindow.ProcessProvider.Dictionary.ContainsKey(processId))
|
|
info.BestName = Program.HackerWindow.ProcessProvider.Dictionary[processId].Name +
|
|
" (" + processId.ToString() + ")";
|
|
else
|
|
info.BestName = "Non-existent process (" + processId.ToString() + ")";
|
|
}
|
|
finally
|
|
{
|
|
CloseHandle(process_handle);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case "Thread":
|
|
{
|
|
int thread_handle = 0;
|
|
int processId = 0;
|
|
int threadId = 0;
|
|
|
|
if (ZwDuplicateObject(process.Handle, handle.Handle,
|
|
Program.CurrentProcess, ref thread_handle,
|
|
(STANDARD_RIGHTS)THREAD_RIGHTS.THREAD_QUERY_INFORMATION, 0, 0) != 0)
|
|
throw new Exception("Could not duplicate thread handle!");
|
|
|
|
try
|
|
{
|
|
if ((threadId = GetThreadId(thread_handle)) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
if ((processId = GetProcessIdOfThread(thread_handle)) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
if (Program.HackerWindow.ProcessProvider.Dictionary.ContainsKey(processId))
|
|
info.BestName = Program.HackerWindow.ProcessProvider.Dictionary[processId].Name +
|
|
" (" + processId.ToString() + "): " + threadId.ToString();
|
|
else
|
|
info.BestName = "Non-existent process (" + processId.ToString() + "): " +
|
|
threadId.ToString();
|
|
}
|
|
finally
|
|
{
|
|
CloseHandle(thread_handle);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case "Token":
|
|
{
|
|
int token_handle = 0;
|
|
|
|
if (ZwDuplicateObject(process.Handle, handle.Handle,
|
|
Program.CurrentProcess, ref token_handle,
|
|
(STANDARD_RIGHTS)TOKEN_RIGHTS.TOKEN_QUERY, 0, 0) != 0)
|
|
throw new Exception("Could not duplicate token handle!");
|
|
|
|
try
|
|
{
|
|
info.BestName = TokenHandle.FromHandle(token_handle).GetUsername(true);
|
|
}
|
|
finally
|
|
{
|
|
CloseHandle(token_handle);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
if (info.OrigName != null &&
|
|
info.OrigName != "")
|
|
{
|
|
info.BestName = info.OrigName;
|
|
}
|
|
else
|
|
{
|
|
info.BestName = null;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
if (info.OrigName != null &&
|
|
info.OrigName != "")
|
|
{
|
|
info.BestName = info.OrigName;
|
|
}
|
|
else
|
|
{
|
|
info.BestName = null;
|
|
}
|
|
}
|
|
|
|
return info;
|
|
}
|
|
finally
|
|
{
|
|
CloseHandle(object_handle);
|
|
}
|
|
|
|
throw new Exception("Failed");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Misc.
|
|
|
|
public static T PtrToStructure<T>(IntPtr data)
|
|
{
|
|
return (T)Marshal.PtrToStructure(data, typeof(T));
|
|
}
|
|
|
|
public static string ReadUnicodeString(UNICODE_STRING str)
|
|
{
|
|
if (str.Length == 0)
|
|
return null;
|
|
|
|
byte[] buf = new byte[str.Length];
|
|
int bytesRead = 0;
|
|
|
|
ReadProcessMemory(GetCurrentProcess(), str.Buffer, buf, str.Length, ref bytesRead);
|
|
|
|
return UnicodeEncoding.Unicode.GetString(buf);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Processes
|
|
|
|
public static string GetNameFromPID(int pid)
|
|
{
|
|
PROCESSENTRY32 proc = new PROCESSENTRY32();
|
|
int snapshot = 0;
|
|
|
|
snapshot = CreateToolhelp32Snapshot(SnapshotFlags.Process, pid);
|
|
|
|
if (snapshot == 0)
|
|
return "(error)";
|
|
|
|
proc.dwSize = Marshal.SizeOf(typeof(PROCESSENTRY32));
|
|
|
|
Process32First(snapshot, ref proc);
|
|
|
|
do
|
|
{
|
|
if (proc.th32ProcessID == pid)
|
|
return proc.szExeFile;
|
|
} while (Process32Next(snapshot, ref proc) != 0);
|
|
|
|
return "(unknown)";
|
|
}
|
|
|
|
public static string GetProcessCmdLine(ProcessHandle process)
|
|
{
|
|
return GetProcessPEBString(process, 66);
|
|
}
|
|
|
|
public static Icon GetProcessIcon(Process p)
|
|
{
|
|
Win32.SHFILEINFO shinfo = new Win32.SHFILEINFO();
|
|
|
|
try
|
|
{
|
|
if (Win32.SHGetFileInfo(Misc.GetRealPath(p.MainModule.FileName), 0, ref shinfo,
|
|
(uint)Marshal.SizeOf(shinfo),
|
|
Win32.SHGFI_ICON |
|
|
Win32.SHGFI_SMALLICON) == 0)
|
|
{
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
return Icon.FromHandle(shinfo.hIcon);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static string GetProcessImageFileName(ProcessHandle process)
|
|
{
|
|
return GetProcessPEBString(process, 58);
|
|
}
|
|
|
|
public static int GetProcessParent(int pid)
|
|
{
|
|
PROCESSENTRY32 proc = new PROCESSENTRY32();
|
|
int snapshot = 0;
|
|
|
|
snapshot = CreateToolhelp32Snapshot(SnapshotFlags.Process, pid);
|
|
|
|
if (snapshot == 0)
|
|
return -1;
|
|
|
|
proc.dwSize = Marshal.SizeOf(typeof(PROCESSENTRY32));
|
|
|
|
Process32First(snapshot, ref proc);
|
|
|
|
do
|
|
{
|
|
if (proc.th32ProcessID == pid)
|
|
return proc.th32ParentProcessID;
|
|
} while (Process32Next(snapshot, ref proc) != 0);
|
|
|
|
return -1;
|
|
}
|
|
|
|
public static string GetProcessPEBString(ProcessHandle process, int offset)
|
|
{
|
|
PROCESS_BASIC_INFORMATION basicInfo = new PROCESS_BASIC_INFORMATION();
|
|
int retLen = 0;
|
|
int pebBaseAddress = 0x7ffd7000;
|
|
|
|
if (ZwQueryInformationProcess(process.Handle, PROCESSINFOCLASS.ProcessBasicInformation,
|
|
ref basicInfo, Marshal.SizeOf(basicInfo), ref retLen) != 0)
|
|
pebBaseAddress = basicInfo.PebBaseAddress;
|
|
|
|
byte[] data2 = new byte[4];
|
|
|
|
// read address of parameter information block
|
|
if (ReadProcessMemory(process.Handle, basicInfo.PebBaseAddress + 16, data2, 4, ref retLen) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
int paramInfoAddrI = Misc.BytesToInt(data2, Misc.Endianness.Little);
|
|
|
|
// read length of string
|
|
if (ReadProcessMemory(process.Handle, paramInfoAddrI + offset, data2, 2, ref retLen) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
ushort strLength = Misc.BytesToUShort(data2, Misc.Endianness.Little);
|
|
byte[] stringData = new byte[strLength];
|
|
|
|
// read address of string
|
|
if (ReadProcessMemory(process.Handle, paramInfoAddrI + offset + 2, data2, 4, ref retLen) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
int strAddr = Misc.BytesToInt(data2, Misc.Endianness.Little);
|
|
|
|
// read string
|
|
if (ReadProcessMemory(process.Handle, strAddr, stringData, strLength, ref retLen) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
// return decoded unicode string
|
|
return UnicodeEncoding.Unicode.GetString(stringData).TrimEnd('\0');
|
|
}
|
|
|
|
public static int GetProcessSessionId(int ProcessId)
|
|
{
|
|
int sessionId = -1;
|
|
|
|
try
|
|
{
|
|
if (ProcessIdToSessionId(ProcessId, ref sessionId) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
catch
|
|
{
|
|
int handle = 0;
|
|
int token = 0;
|
|
int retLen = 0;
|
|
|
|
try
|
|
{
|
|
if ((handle = OpenProcess(PROCESS_RIGHTS.PROCESS_QUERY_INFORMATION, 0, ProcessId)) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
if (OpenProcessToken(handle, TOKEN_RIGHTS.TOKEN_QUERY,
|
|
out token) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenSessionId,
|
|
ref sessionId, 4, ref retLen) == 0)
|
|
{
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
CloseHandle(token);
|
|
CloseHandle(handle);
|
|
}
|
|
|
|
return sessionId;
|
|
}
|
|
|
|
return sessionId;
|
|
}
|
|
|
|
public static string GetProcessUsername(int handle, bool IncludeDomain)
|
|
{
|
|
using (TokenHandle token = new TokenHandle(ProcessHandle.FromHandle(handle), TOKEN_RIGHTS.TOKEN_QUERY))
|
|
return token.GetUsername(IncludeDomain);
|
|
}
|
|
|
|
public static bool IsBeingDebugged(int ProcessHandle)
|
|
{
|
|
int debugged = 0;
|
|
|
|
if (Win32.CheckRemoteDebuggerPresent(ProcessHandle, ref debugged) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
return debugged == 1;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Security
|
|
|
|
public static string GetAccountName(WTS_PROCESS_INFO info, bool IncludeDomain)
|
|
{
|
|
return GetAccountName(info.SID, IncludeDomain);
|
|
}
|
|
|
|
public static string GetAccountName(int SID, bool IncludeDomain)
|
|
{
|
|
StringBuilder name = new StringBuilder(255);
|
|
StringBuilder domain = new StringBuilder(255);
|
|
int namelen = 255;
|
|
int domainlen = 255;
|
|
SID_NAME_USE use = SID_NAME_USE.SidTypeUser;
|
|
|
|
if (LookupAccountSid(0, SID, name, ref namelen, domain, ref domainlen, ref use) == 0)
|
|
{
|
|
name.EnsureCapacity(namelen);
|
|
domain.EnsureCapacity(domainlen);
|
|
|
|
if (LookupAccountSid(0, SID, name, ref namelen, domain, ref domainlen, ref use) == 0)
|
|
{
|
|
if (name.ToString() == "" && domain.ToString() == "")
|
|
throw new Exception("Could not lookup account SID: " + Win32.GetLastErrorMessage());
|
|
}
|
|
}
|
|
|
|
if (IncludeDomain)
|
|
{
|
|
return ((domain.ToString() != "") ? domain.ToString() + "\\" : "") + name.ToString();
|
|
}
|
|
else
|
|
{
|
|
return name.ToString();
|
|
}
|
|
}
|
|
|
|
public static SID_NAME_USE GetAccountType(int SID)
|
|
{
|
|
StringBuilder name = new StringBuilder(255);
|
|
StringBuilder domain = new StringBuilder(255);
|
|
int namelen = 255;
|
|
int domainlen = 255;
|
|
SID_NAME_USE use = SID_NAME_USE.SidTypeUser;
|
|
|
|
if (LookupAccountSid(0, SID, name, ref namelen, domain, ref domainlen, ref use) == 0)
|
|
{
|
|
name.EnsureCapacity(namelen);
|
|
domain.EnsureCapacity(domainlen);
|
|
|
|
if (LookupAccountSid(0, SID, name, ref namelen, domain, ref domainlen, ref use) == 0)
|
|
{
|
|
if (name.ToString() == "" && domain.ToString() == "")
|
|
throw new Exception("Could not lookup account SID: " + Win32.GetLastErrorMessage());
|
|
}
|
|
}
|
|
|
|
return use;
|
|
}
|
|
|
|
public static string GetPrivilegeDisplayName(string PrivilegeName)
|
|
{
|
|
StringBuilder sb = null;
|
|
int size = 0;
|
|
int languageId = 0;
|
|
|
|
LookupPrivilegeDisplayName(0, PrivilegeName, sb, ref size, ref languageId);
|
|
sb = new StringBuilder(size);
|
|
LookupPrivilegeDisplayName(0, PrivilegeName, sb, ref size, ref languageId);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static string GetPrivilegeName(LUID Luid)
|
|
{
|
|
StringBuilder sb = null;
|
|
int size = 0;
|
|
|
|
LookupPrivilegeName(0, ref Luid, sb, ref size);
|
|
sb = new StringBuilder(size);
|
|
LookupPrivilegeName(0, ref Luid, sb, ref size);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static int OpenLocalPolicy(POLICY_RIGHTS DesiredAccess)
|
|
{
|
|
LSA_OBJECT_ATTRIBUTES attributes = new LSA_OBJECT_ATTRIBUTES();
|
|
int handle = 0;
|
|
|
|
if (LsaOpenPolicy(0, ref attributes, DesiredAccess, ref handle) != 0)
|
|
return 0;
|
|
|
|
return handle;
|
|
}
|
|
|
|
public static TOKEN_GROUPS ReadTokenGroups(TokenHandle TokenHandle, bool IncludeDomains)
|
|
{
|
|
int retLen = 0;
|
|
|
|
GetTokenInformation(TokenHandle.Handle, TOKEN_INFORMATION_CLASS.TokenGroups, 0, 0, ref retLen);
|
|
|
|
IntPtr data = Marshal.AllocHGlobal(retLen);
|
|
|
|
if (GetTokenInformation(TokenHandle.Handle, TOKEN_INFORMATION_CLASS.TokenGroups, data,
|
|
retLen, ref retLen) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
uint number = (uint)Marshal.ReadInt32(data);
|
|
TOKEN_GROUPS groups = new TOKEN_GROUPS();
|
|
|
|
groups.GroupCount = number;
|
|
groups.Groups = new SID_AND_ATTRIBUTES[number];
|
|
groups.Names = new string[number];
|
|
|
|
for (int i = 0; i < number; i++)
|
|
{
|
|
groups.Groups[i] = PtrToStructure<SID_AND_ATTRIBUTES>(
|
|
new IntPtr(data.ToInt32() + 4 + i * Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES))));
|
|
|
|
try
|
|
{
|
|
groups.Names[i] = GetAccountName(groups.Groups[i].SID, IncludeDomains);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
|
|
return groups;
|
|
}
|
|
|
|
public static TOKEN_PRIVILEGES ReadTokenPrivileges(TokenHandle TokenHandle)
|
|
{
|
|
int retLen = 0;
|
|
|
|
GetTokenInformation(TokenHandle.Handle, TOKEN_INFORMATION_CLASS.TokenPrivileges, 0, 0, ref retLen);
|
|
|
|
IntPtr data = Marshal.AllocHGlobal(retLen);
|
|
|
|
if (GetTokenInformation(TokenHandle.Handle, TOKEN_INFORMATION_CLASS.TokenPrivileges, data,
|
|
retLen, ref retLen) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
uint number = (uint)Marshal.ReadInt32(data);
|
|
TOKEN_PRIVILEGES privileges = new TOKEN_PRIVILEGES();
|
|
|
|
privileges.PrivilegeCount = number;
|
|
privileges.Privileges = new LUID_AND_ATTRIBUTES[number];
|
|
|
|
for (int i = 0; i < number; i++)
|
|
{
|
|
privileges.Privileges[i] = PtrToStructure<LUID_AND_ATTRIBUTES>(
|
|
new IntPtr(data.ToInt32() + 4 + i * Marshal.SizeOf(typeof(LUID_AND_ATTRIBUTES))));
|
|
}
|
|
|
|
return privileges;
|
|
}
|
|
|
|
public static void WriteTokenPrivilege(string PrivilegeName, SE_PRIVILEGE_ATTRIBUTES Attributes)
|
|
{
|
|
WriteTokenPrivilege(
|
|
ProcessHandle.FromHandle(Program.CurrentProcess).GetToken(), PrivilegeName, Attributes);
|
|
}
|
|
|
|
public static void WriteTokenPrivilege(TokenHandle TokenHandle, string PrivilegeName, SE_PRIVILEGE_ATTRIBUTES Attributes)
|
|
{
|
|
TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
|
|
|
|
tkp.Privileges = new LUID_AND_ATTRIBUTES[1];
|
|
|
|
if (LookupPrivilegeValue(null, PrivilegeName, ref tkp.Privileges[0].Luid) == 0)
|
|
throw new Exception("Invalid privilege name '" + PrivilegeName + "'.");
|
|
|
|
tkp.PrivilegeCount = 1;
|
|
tkp.Privileges[0].Attributes = Attributes;
|
|
|
|
AdjustTokenPrivileges(TokenHandle.Handle, 0, ref tkp, 0, 0, 0);
|
|
|
|
if (Marshal.GetLastWin32Error() != 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Services
|
|
|
|
public static Dictionary<string, ENUM_SERVICE_STATUS_PROCESS> EnumServices()
|
|
{
|
|
int manager = OpenSCManager(0, 0, SC_MANAGER_RIGHTS.SC_MANAGER_ENUMERATE_SERVICE);
|
|
|
|
if (manager == 0)
|
|
throw new Exception("Could not open service control manager: "
|
|
+ GetLastErrorMessage() + ".");
|
|
|
|
int requiredSize = 0;
|
|
int servicesReturned = 0;
|
|
int resume = 0;
|
|
|
|
// get required size
|
|
EnumServicesStatusEx(manager, 0, SERVICE_QUERY_TYPE.Win32 | SERVICE_QUERY_TYPE.Driver,
|
|
SERVICE_QUERY_STATE.All, ref servicesReturned // hack
|
|
, 0, ref requiredSize, ref servicesReturned,
|
|
ref resume, 0);
|
|
|
|
IntPtr data = Marshal.AllocHGlobal(requiredSize);
|
|
Dictionary<string, ENUM_SERVICE_STATUS_PROCESS> dictionary =
|
|
new Dictionary<string, ENUM_SERVICE_STATUS_PROCESS>();
|
|
|
|
try
|
|
{
|
|
if (EnumServicesStatusEx(manager, 0, SERVICE_QUERY_TYPE.Win32 | SERVICE_QUERY_TYPE.Driver,
|
|
SERVICE_QUERY_STATE.All, data,
|
|
requiredSize, ref requiredSize, ref servicesReturned,
|
|
ref resume, 0) == 0)
|
|
{
|
|
throw new Exception(GetLastErrorMessage());
|
|
}
|
|
|
|
for (int i = 0; i < servicesReturned; i++)
|
|
{
|
|
ENUM_SERVICE_STATUS_PROCESS service = PtrToStructure<ENUM_SERVICE_STATUS_PROCESS>(
|
|
new IntPtr(data.ToInt32() + Marshal.SizeOf(typeof(ENUM_SERVICE_STATUS_PROCESS)) * i));
|
|
|
|
dictionary.Add(service.ServiceName, service);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
CloseServiceHandle(manager);
|
|
Marshal.FreeHGlobal(data);
|
|
}
|
|
|
|
return dictionary;
|
|
}
|
|
|
|
public static QUERY_SERVICE_CONFIG GetServiceConfig(string ServiceName)
|
|
{
|
|
int manager = OpenSCManager(0, 0, SC_MANAGER_RIGHTS.SC_MANAGER_CONNECT);
|
|
|
|
if (manager == 0)
|
|
throw new Exception("Could not open service control manager: "
|
|
+ GetLastErrorMessage() + ".");
|
|
|
|
int handle = OpenService(manager, ServiceName, SERVICE_RIGHTS.SERVICE_QUERY_CONFIG);
|
|
|
|
if (handle == 0)
|
|
{
|
|
CloseServiceHandle(manager);
|
|
|
|
throw new Exception("Could not open service handle: "
|
|
+ GetLastErrorMessage() + ".");
|
|
}
|
|
|
|
int requiredSize = 0;
|
|
|
|
QueryServiceConfig(handle, 0, 0, ref requiredSize);
|
|
|
|
IntPtr data = Marshal.AllocHGlobal(requiredSize);
|
|
QUERY_SERVICE_CONFIG config;
|
|
|
|
try
|
|
{
|
|
if (QueryServiceConfig(handle, data, requiredSize, ref requiredSize) == 0)
|
|
{
|
|
throw new Exception("Could not get service configuration: " + GetLastErrorMessage());
|
|
}
|
|
|
|
config = PtrToStructure<QUERY_SERVICE_CONFIG>(data);
|
|
}
|
|
finally
|
|
{
|
|
CloseServiceHandle(handle);
|
|
CloseServiceHandle(manager);
|
|
Marshal.FreeHGlobal(data);
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Statistics
|
|
|
|
public static IO_COUNTERS GetProcessIoCounters(ProcessHandle process)
|
|
{
|
|
IO_COUNTERS counters = new IO_COUNTERS();
|
|
|
|
if (GetProcessIoCounters(process.Handle, ref counters) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
return counters;
|
|
}
|
|
|
|
public static ulong[] GetProcessTimes(ProcessHandle process)
|
|
{
|
|
ulong[] times = new ulong[4];
|
|
|
|
if (GetProcessTimes(process.Handle, ref times[0], ref times[1], ref times[2], ref times[3]) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
return times;
|
|
}
|
|
|
|
public static ulong[] GetSystemTimes()
|
|
{
|
|
ulong[] times = new ulong[3];
|
|
|
|
if (GetSystemTimes(ref times[0], ref times[1], ref times[2]) == 0)
|
|
throw new Exception(GetLastErrorMessage());
|
|
|
|
return times;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Terminal Server
|
|
|
|
public struct WtsProcess
|
|
{
|
|
public WTS_PROCESS_INFO Info;
|
|
public string Username;
|
|
public string UsernameWithDomain;
|
|
}
|
|
|
|
public static WTS_SESSION_INFO[] TSEnumSessions()
|
|
{
|
|
int sessions = 0;
|
|
int count = 0;
|
|
WTS_SESSION_INFO[] returnSessions;
|
|
|
|
WTSEnumerateSessions(0, 0, 1, ref sessions, ref count);
|
|
returnSessions = new WTS_SESSION_INFO[count];
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
returnSessions[i] = PtrToStructure<WTS_SESSION_INFO>(
|
|
new IntPtr(sessions + Marshal.SizeOf(typeof(WTS_SESSION_INFO)) * i));
|
|
}
|
|
|
|
WTSFreeMemory(sessions);
|
|
|
|
return returnSessions;
|
|
}
|
|
|
|
public static WtsProcess[] TSEnumProcesses()
|
|
{
|
|
int processes = 0;
|
|
int count = 0;
|
|
WtsProcess[] returnProcesses;
|
|
|
|
WTSEnumerateProcesses(0, 0, 1, ref processes, ref count);
|
|
returnProcesses = new WtsProcess[count];
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
returnProcesses[i].Info = PtrToStructure<WTS_PROCESS_INFO>(
|
|
new IntPtr(processes + Marshal.SizeOf(typeof(WTS_PROCESS_INFO)) * i));
|
|
|
|
try
|
|
{
|
|
if (returnProcesses[i].Info.SID == 0)
|
|
throw new Exception("Null SID pointer");
|
|
|
|
returnProcesses[i].Username = GetAccountName(returnProcesses[i].Info.SID, false);
|
|
}
|
|
catch
|
|
{ }
|
|
|
|
try
|
|
{
|
|
if (returnProcesses[i].Info.SID == 0)
|
|
throw new Exception("Null SID pointer");
|
|
|
|
returnProcesses[i].UsernameWithDomain = GetAccountName(returnProcesses[i].Info.SID, true);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
|
|
WTSFreeMemory(processes);
|
|
|
|
return returnProcesses;
|
|
}
|
|
|
|
public static string TSGetProcessUsername(int PID, bool IncludeDomain)
|
|
{
|
|
WtsProcess[] processes = TSEnumProcesses();
|
|
|
|
foreach (WtsProcess process in processes)
|
|
{
|
|
if (process.Info.ProcessID == PID)
|
|
{
|
|
if (IncludeDomain)
|
|
return process.UsernameWithDomain;
|
|
else
|
|
return process.Username;
|
|
}
|
|
}
|
|
|
|
throw new Exception("Process does not exist.");
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|