/// <summary> /// Sets the specified window's show state. /// </summary> /// <param name="windowHandle">A handle to the window.</param> /// <param name="state">Controls how the window is to be shown.</param> /// <returns> /// If the window was previously visible, the return value is <c>true</c>, otherwise the return value is /// <c>false</c>. /// </returns> public static bool ShowWindow(IntPtr windowHandle, WindowStates state) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Change the state of the window return(User32.ShowWindow(windowHandle, state)); }
/// <summary> /// Retrieves the identifier of the thread that created the specified window. /// </summary> /// <param name="windowHandle">A handle to the window.</param> /// <returns>The return value is the identifier of the thread that created the window.</returns> public static int GetWindowThreadId(IntPtr windowHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Get the thread id return(User32.GetWindowThreadProcessId(windowHandle, out _)); }
/// <summary> /// Sends the specified message to a window or windows. /// The SendMessage function calls the window procedure for the specified window and does not return until the window /// procedure has processed the message. /// </summary> /// <param name="windowHandle">A handle to the window whose window procedure will receive the message.</param> /// <param name="message">The message to be sent.</param> /// <param name="wParam">Additional message-specific information.</param> /// <param name="lParam">Additional message-specific information.</param> /// <returns>The return value specifies the result of the message processing; it depends on the message sent.</returns> public static IntPtr SendMessage(IntPtr windowHandle, int message, IntPtr wParam, IntPtr lParam) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Send the message return(User32.SendMessage(windowHandle, message, wParam, lParam)); }
/// <summary> /// Flashes the specified window one time. It does not change the active state of the window. /// To flash the window a specified number of times, use the /// <see cref="FlashWindowEx(IntPtr, FlashWindowFlags, int, TimeSpan)" /> function. /// </summary> /// <param name="windowHandle">A handle to the window to be flashed. The window can be either open or minimized.</param> /// <returns> /// The return value specifies the window's state before the call to the <see cref="FlashWindow" /> function. /// If the window caption was drawn as active before the call, the return value is nonzero. Otherwise, the return value /// is zero. /// </returns> public static bool FlashWindow(IntPtr windowHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Flash the window return(User32.FlashWindow(windowHandle, true)); }
/// <summary> /// Places (posts) a message in the message queue associated with the thread that created the specified window and /// returns without waiting for the thread to process the message. /// </summary> /// <param name="windowHandle"> /// A handle to the window whose window procedure is to receive the message. The following /// values have special meanings. /// </param> /// <param name="message">The message to be posted.</param> /// <param name="wParam">Additional message-specific information.</param> /// <param name="lParam">Additional message-specific information.</param> public static void PostMessage(IntPtr windowHandle, int message, IntPtr wParam, IntPtr lParam) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Post the message if (!User32.PostMessage(windowHandle, message, wParam, lParam)) { throw new Win32Exception($"Couldn't post the message '{message}'."); } }
/// <summary> /// Sets the text of the specified window's title bar. /// </summary> /// <param name="windowHandle">A handle to the window whose text is to be changed.</param> /// <param name="title">The new title text.</param> public static void SetWindowText(IntPtr windowHandle, string title) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Set the text of the window's title bar if (!User32.SetWindowText(windowHandle, title)) { throw new Win32Exception("Couldn't set the text of the window's title bar."); } }
/// <summary> /// Sets the context for the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread whose context is to be set.</param> /// <param name="context"> /// A pointer to a <see cref="ThreadContext" /> structure that contains the context to be set in the /// specified thread. /// </param> public static void SetThreadContext(SafeMemoryHandle threadHandle, ThreadContext context) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Set the thread context if (!Kernel32.SetThreadContext(threadHandle, ref context)) { throw new Win32Exception("Couldn't set the thread context."); } }
/// <summary> /// Closes an open object handle. /// </summary> /// <param name="handle">A valid handle to an open object.</param> public static void CloseHandle(IntPtr handle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(handle, "handle"); // Close the handle if (!Kernel32.CloseHandle(handle)) { throw new Win32Exception($"Couldn't close he handle 0x{handle}."); } }
/// <summary> /// Retrieves the identifier of the process that created the window. /// </summary> /// <param name="windowHandle">A handle to the window.</param> /// <returns>The return value is the identifier of the process that created the window.</returns> public static int GetWindowProcessId(IntPtr windowHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Get the process id int processId; User32.GetWindowThreadProcessId(windowHandle, out processId); return(processId); }
/// <summary> /// Releases a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to a process.</param> /// <param name="address">A pointer to the starting address of the region of memory to be freed.</param> public static void Free(SafeMemoryHandle processHandle, IntPtr address) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(address, "address"); // Free the memory if (!Kernel32.VirtualFreeEx(processHandle, address, 0, MemoryReleaseFlags.Release)) { // If the memory wasn't correctly freed, throws an exception throw new Win32Exception($"The memory page 0x{address.ToString("X")} cannot be freed."); } }
/// <summary> /// Terminates a thread. /// </summary> /// <param name="threadHandle">A handle to the thread to be terminated.</param> /// <param name="exitCode">The exit code for the thread.</param> public static void TerminateThread(SafeMemoryHandle threadHandle, int exitCode) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Terminate the thread var ret = Kernel32.TerminateThread(threadHandle, exitCode); // If the function failed if (!ret) { throw new Win32Exception("Couldn't terminate the thread."); } }
/// <summary> /// Retrieves the name of the class to which the specified window belongs. /// </summary> /// <param name="windowHandle">A handle to the window and, indirectly, the class to which the window belongs.</param> /// <returns>The return values is the class name string.</returns> public static string GetClassName(IntPtr windowHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Get the window class name var stringBuilder = new StringBuilder(char.MaxValue); if (User32.GetClassName(windowHandle, stringBuilder, stringBuilder.Capacity) == 0) { throw new Win32Exception("Couldn't get the class name of the window or the window has no class name."); } return(stringBuilder.ToString()); }
/// <summary> /// Waits an infinite amount of time for the specified object to become signaled. /// </summary> /// <param name="handle">A handle to the object.</param> /// <returns>If the function succeeds, the return value indicates the event that caused the function to return.</returns> public static WaitValues WaitForSingleObject(SafeMemoryHandle handle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(handle, "handle"); // Wait for single object var ret = Kernel32.WaitForSingleObject(handle, 0xFFFFFFFF); // If the function failed if (ret == WaitValues.Failed) { throw new Win32Exception("The WaitForSingleObject function call failed."); } return(ret); }
/// <summary> /// Retrieves a descriptor table entry for the specified selector and thread. /// </summary> /// <param name="threadHandle">A handle to the thread containing the specified selector.</param> /// <param name="selector">The global or local selector value to look up in the thread's descriptor tables.</param> /// <returns>A pointer to an <see cref="LdtEntry" /> structure that receives a copy of the descriptor table entry.</returns> public static LdtEntry GetThreadSelectorEntry(SafeMemoryHandle threadHandle, uint selector) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Get the selector entry LdtEntry entry; if (Kernel32.GetThreadSelectorEntry(threadHandle, selector, out entry)) { return(entry); } // Else couldn't get the selector entry, throws an exception throw new Win32Exception($"Couldn't get the selector entry for this selector: {selector}."); }
/// <summary> /// Suspends the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread that is to be suspended.</param> /// <returns>The thread's previous suspend count.</returns> public static uint SuspendThread(SafeMemoryHandle threadHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Suspend the thread var ret = Kernel32.SuspendThread(threadHandle); // If the function failed if (ret == uint.MaxValue) { throw new Win32Exception("Couldn't suspend the thread."); } return(ret); }
/// <summary> /// Sets the show state and the restored, minimized, and maximized positions of the specified window. /// </summary> /// <param name="windowHandle">A handle to the window.</param> /// <param name="placement"> /// A pointer to the <see cref="WindowPlacement" /> structure that specifies the new show state and /// window positions. /// </param> public static void SetWindowPlacement(IntPtr windowHandle, WindowPlacement placement) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // If the debugger is attached and the state of the window is ShowDefault, there's an issue where the window disappears if (Debugger.IsAttached && placement.ShowCmd == WindowStates.ShowNormal) { placement.ShowCmd = WindowStates.Restore; } // Set the window placement if (!User32.SetWindowPlacement(windowHandle, ref placement)) { throw new Win32Exception("Couldn't set the window placement."); } }
/// <summary> /// Waits until the specified object is in the signaled state or the time-out interval elapses. /// </summary> /// <param name="handle">A handle to the object.</param> /// <param name="timeout"> /// The time-out interval. If this parameter is NULL, the function does not enter a wait state if the /// object is not signaled; it always returns immediately. /// </param> /// <returns>Indicates the <see cref="WaitValues" /> event that caused the function to return.</returns> public static WaitValues WaitForSingleObject(SafeMemoryHandle handle, TimeSpan?timeout) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(handle, "handle"); // Wait for single object var ret = Kernel32.WaitForSingleObject(handle, timeout.HasValue ? Convert.ToUInt32(timeout.Value.TotalMilliseconds) : 0); // If the function failed if (ret == WaitValues.Failed) { throw new Win32Exception("The WaitForSingleObject function call failed."); } return(ret); }
/// <summary> /// Sets the current position and size of the specified window. /// </summary> /// <param name="windowHandle">A handle to the window.</param> /// <param name="left">The x-coordinate of the upper-left corner of the window.</param> /// <param name="top">The y-coordinate of the upper-left corner of the window.</param> /// <param name="height">The height of the window.</param> /// <param name="width">The width of the window.</param> public static void SetWindowPlacement(IntPtr windowHandle, int left, int top, int height, int width) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Get a WindowPlacement structure of the current window var placement = GetWindowPlacement(windowHandle); // Set the values placement.NormalPosition.Left = left; placement.NormalPosition.Top = top; placement.NormalPosition.Height = height; placement.NormalPosition.Width = width; // Set the window placement SetWindowPlacement(windowHandle, placement); }
/// <summary> /// Retrieves the show state and the restored, minimized, and maximized positions of the specified window. /// </summary> /// <param name="windowHandle">A handle to the window.</param> /// <returns> /// The return value is a <see cref="WindowPlacement" /> structure that receives the show state and position /// information. /// </returns> public static WindowPlacement GetWindowPlacement(IntPtr windowHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Allocate a WindowPlacement structure WindowPlacement placement; placement.Length = Marshal.SizeOf(typeof(WindowPlacement)); // Get the window placement if (!User32.GetWindowPlacement(windowHandle, out placement)) { throw new Win32Exception("Couldn't get the window placement."); } return(placement); }
/// <summary> /// Flashes the specified window. It does not change the active state of the window. /// </summary> /// <param name="windowHandle">A handle to the window to be flashed. The window can be either opened or minimized.</param> /// <param name="flags">The flash status.</param> /// <param name="count">The number of times to flash the window.</param> /// <param name="timeout">The rate at which the window is to be flashed.</param> public static void FlashWindowEx(IntPtr windowHandle, FlashWindowFlags flags, int count, TimeSpan timeout) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // Create the data structure var flashInfo = new FlashInfo { Size = Marshal.SizeOf(typeof(FlashInfo)), Hwnd = windowHandle, Flags = flags, Count = count, Timeout = Convert.ToInt32(timeout.TotalMilliseconds) }; // Flash the window User32.FlashWindowEx(ref flashInfo); }
/// <summary> /// Reads an array of bytes in the memory form the target process. /// </summary> /// <param name="processHandle">A handle to the process with memory that is being read.</param> /// <param name="address">A pointer to the base address in the specified process from which to read.</param> /// <param name="size">The number of bytes to be read from the specified process.</param> /// <returns>The collection of read bytes.</returns> public static byte[] ReadBytes(SafeMemoryHandle processHandle, IntPtr address, int size) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(address, "address"); // Allocate the buffer var buffer = new byte[size]; int nbBytesRead; // Read the data from the target process if (Kernel32.ReadProcessMemory(processHandle, address, buffer, size, out nbBytesRead) && size == nbBytesRead) { return(buffer); } // Else the data couldn't be read, throws an exception throw new Win32Exception($"Couldn't read {size} byte(s) from 0x{address.ToString("X")}."); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region.</returns> public static IntPtr Allocate(SafeMemoryHandle processHandle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Allocate a memory page var ret = Kernel32.VirtualAllocEx(processHandle, IntPtr.Zero, size, allocationFlags, protectionFlags); // Check whether the memory page is valid if (ret != IntPtr.Zero) { return(ret); } // If the pointer isn't valid, throws an exception throw new Win32Exception($"Couldn't allocate memory of {size} byte(s)."); }
/// <summary> /// Brings the thread that created the specified window into the foreground and activates the window. /// The window is restored if minimized. Performs no action if the window is already activated. /// </summary> /// <param name="windowHandle">A handle to the window that should be activated and brought to the foreground.</param> /// <returns> /// If the window was brought to the foreground, the return value is <c>true</c>, otherwise the return value is /// <c>false</c>. /// </returns> public static void SetForegroundWindow(IntPtr windowHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(windowHandle, "windowHandle"); // If the window is already activated, do nothing if (GetForegroundWindow() == windowHandle) { return; } // Restore the window if minimized ShowWindow(windowHandle, WindowStates.Restore); // Activate the window if (!User32.SetForegroundWindow(windowHandle)) { throw new ApplicationException("Couldn't set the window to foreground."); } }
/// <summary> /// Creates a thread that runs in the virtual address space of another process. /// </summary> /// <param name="processHandle">A handle to the process in which the thread is to be created.</param> /// <param name="startAddress"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A pointer to a variable to be passed to the thread function.</param> /// <param name="creationFlags">The flags that control the creation of the thread.</param> /// <returns>A handle to the new thread.</returns> public static SafeMemoryHandle CreateRemoteThread(SafeMemoryHandle processHandle, IntPtr startAddress, IntPtr parameter, ThreadCreationFlags creationFlags = ThreadCreationFlags.Run) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(startAddress, "startAddress"); // Create the remote thread var ret = Kernel32.CreateRemoteThread(processHandle, IntPtr.Zero, 0, startAddress, parameter, creationFlags, out _); // If the thread is created if (!ret.IsClosed && !ret.IsInvalid) { return(ret); } // Else couldn't create thread, throws an exception throw new Win32Exception($"Couldn't create the thread at 0x{startAddress.ToString("X")}."); }
/// <summary> /// Changes the protection on a region of committed pages in the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory protection is to be changed.</param> /// <param name="address"> /// A pointer to the base address of the region of pages whose access protection attributes are to be /// changed. /// </param> /// <param name="size">The size of the region whose access protection attributes are changed, in bytes.</param> /// <param name="protection">The memory protection option.</param> /// <returns>The old protection of the region in a <see cref="MemoryBasicInformation" /> structure.</returns> public static MemoryProtectionFlags ChangeProtection(SafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protection) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(address, "address"); // Create the variable storing the old protection of the memory page MemoryProtectionFlags oldProtection; // Change the protection in the target process if (Kernel32.VirtualProtectEx(processHandle, address, size, protection, out oldProtection)) { // Return the old protection return(oldProtection); } // Else the protection couldn't be changed, throws an exception throw new Win32Exception( $"Couldn't change the protection of the memory at 0x{address.ToString("X")} of {size} byte(s) to {protection}."); }
/// <summary> /// etrieves information about the specified process. /// </summary> /// <param name="processHandle">A handle to the process to query.</param> /// <returns>A <see cref="ProcessBasicInformation" /> structure containg process information.</returns> public static ProcessBasicInformation NtQueryInformationProcess(SafeMemoryHandle processHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Create a structure to store process info var info = new ProcessBasicInformation(); // Get the process info var ret = Nt.NtQueryInformationProcess(processHandle, ProcessInformationClass.ProcessBasicInformation, ref info, info.Size, IntPtr.Zero); // If the function succeeded if (ret == 0) { return(info); } // Else, couldn't get the process info, throws an exception throw new ApplicationException($"Couldn't get the information from the process, error code '{ret}'."); }
/// <summary> /// Retrieves information about the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread to query.</param> /// <returns>A <see cref="ThreadBasicInformation" /> structure containg thread information.</returns> public static ThreadBasicInformation NtQueryInformationThread(SafeMemoryHandle threadHandle) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Create a structure to store thread info var info = new ThreadBasicInformation(); // Get the thread info var ret = Nt.NtQueryInformationThread(threadHandle, 0, ref info, MarshalType <ThreadBasicInformation> .Size, IntPtr.Zero); // If the function succeeded if (ret == 0) { return(info); } // Else, couldn't get the thread info, throws an exception throw new ApplicationException($"Couldn't get the information from the thread, error code '{ret}'."); }
/// <summary> /// Retrieves information about a range of pages within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory information is queried.</param> /// <param name="addressFrom">A pointer to the starting address of the region of pages to be queried.</param> /// <param name="addressTo">A pointer to the ending address of the region of pages to be queried.</param> /// <returns>A collection of <see cref="MemoryBasicInformation" /> structures.</returns> public static IEnumerable <MemoryBasicInformation> Query(SafeMemoryHandle processHandle, IntPtr addressFrom, IntPtr addressTo) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Convert the addresses to Int64 var numberFrom = addressFrom.ToInt64(); var numberTo = addressTo.ToInt64(); // The first address must be lower than the second if (numberFrom >= numberTo) { throw new ArgumentException("The starting address must be lower than the ending address.", "addressFrom"); } // Create the variable storing the result of the call of VirtualQueryEx int ret; // Enumerate the memory pages do { // Allocate the structure to store information of memory MemoryBasicInformation memoryInfo; // Get the next memory page ret = Kernel32.VirtualQueryEx(processHandle, new IntPtr(numberFrom), out memoryInfo, MarshalType <MemoryBasicInformation> .Size); // Increment the starting address with the size of the page numberFrom += memoryInfo.RegionSize; // Return the memory page if (memoryInfo.State != MemoryStateFlags.Free) { yield return(memoryInfo); } } while (numberFrom < numberTo && ret != 0); }
/// <summary> /// Retrieves the context of the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread whose context is to be retrieved.</param> /// <param name="contextFlags">Determines which registers are returned or set.</param> /// <returns>A <see cref="ThreadContext" /> structure that receives the appropriate context of the specified thread.</returns> public static ThreadContext GetThreadContext(SafeMemoryHandle threadHandle, ThreadContextFlags contextFlags = ThreadContextFlags.Full) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Allocate a thread context structure var context = new ThreadContext { ContextFlags = contextFlags }; // Set the context flag // Get the thread context if (Kernel32.GetThreadContext(threadHandle, ref context)) { return(context); } // Else couldn't get the thread context, throws an exception throw new Win32Exception("Couldn't get the thread context."); }
/// <summary> /// Writes data to an area of memory in a specified process. /// </summary> /// <param name="processHandle">A handle to the process memory to be modified.</param> /// <param name="address">A pointer to the base address in the specified process to which data is written.</param> /// <param name="byteArray">A buffer that contains data to be written in the address space of the specified process.</param> /// <returns>The number of bytes written.</returns> public static int WriteBytes(SafeMemoryHandle processHandle, IntPtr address, byte[] byteArray) { // Check if the handles are valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); HandleManipulator.ValidateAsArgument(address, "address"); // Create the variable storing the number of bytes written int nbBytesWritten; // Write the data to the target process if (Kernel32.WriteProcessMemory(processHandle, address, byteArray, byteArray.Length, out nbBytesWritten)) { // Check whether the length of the data written is equal to the inital array if (nbBytesWritten == byteArray.Length) { return(nbBytesWritten); } } // Else the data couldn't be written, throws an exception throw new Win32Exception($"Couldn't write {byteArray.Length} bytes to 0x{address.ToString("X")}"); }