Example #1
0
        /// <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
            AHandleManipulator.ValidateAsArgument(windowHandle, "windowHandle");

            // Send the message
            return(User32.SendMessage(windowHandle, message, wParam, lParam));
        }
Example #2
0
        /// <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
            AHandleManipulator.ValidateAsArgument(windowHandle, "windowHandle");

            // Change the state of the window
            return(User32.ShowWindow(windowHandle, state));
        }
Example #3
0
        /// <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
            AHandleManipulator.ValidateAsArgument(windowHandle, "windowHandle");

            // Flash the window
            return(User32.FlashWindow(windowHandle, true));
        }
Example #4
0
        /// <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
            AHandleManipulator.ValidateAsArgument(windowHandle, "windowHandle");

            // Get the thread id
            int trash;

            return(User32.GetWindowThreadProcessId(windowHandle, out trash));
        }
Example #5
0
        /// <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
            AHandleManipulator.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.");
            }
        }
Example #6
0
        /// <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(ASafeMemoryHandle threadHandle, ThreadContext context)
        {
            // Check if the handle is valid
            AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle");

            // Set the thread context
            if (!Kernel32.SetThreadContext(threadHandle, ref context))
            {
                throw new Win32Exception("Couldn't set the thread context.");
            }
        }
Example #7
0
        /// <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
            AHandleManipulator.ValidateAsArgument(windowHandle, "windowHandle");

            // Post the message
            if (!User32.PostMessage(windowHandle, message, wParam, lParam))
            {
                throw new Win32Exception($"Couldn't post the message '{message}'.");
            }
        }
Example #8
0
        /// <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
            AHandleManipulator.ValidateAsArgument(handle, "handle");

            // Close the handle
            if (!Kernel32.CloseHandle(handle))
            {
                throw new Win32Exception($"Couldn't close he handle 0x{handle}.");
            }
        }
Example #9
0
        /// <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
            AHandleManipulator.ValidateAsArgument(windowHandle, "windowHandle");

            // Get the process id
            int processId;

            User32.GetWindowThreadProcessId(windowHandle, out processId);

            return(processId);
        }
Example #10
0
        /// <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(ASafeMemoryHandle processHandle, IntPtr address)
        {
            // Check if the handles are valid
            AHandleManipulator.ValidateAsArgument(processHandle, "processHandle");
            AHandleManipulator.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.");
            }
        }
Example #11
0
        /// <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(ASafeMemoryHandle threadHandle, int exitCode)
        {
            // Check if the handle is valid
            AHandleManipulator.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.");
            }
        }
Example #12
0
        /// <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
            AHandleManipulator.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());
        }
Example #13
0
        /// <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(ASafeMemoryHandle threadHandle, int selector)
        {
            // Check if the handle is valid
            AHandleManipulator.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}.");
        }
Example #14
0
        /// <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(ASafeMemoryHandle handle)
        {
            // Check if the handle is valid
            AHandleManipulator.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);
        }
Example #15
0
        public static Boolean ChangeProtection(ASafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protection, out MemoryProtectionFlags oldProtection)
        {
            // Check if the handles are valid
            AHandleManipulator.ValidateAsArgument(processHandle, "processHandle");
            AHandleManipulator.ValidateAsArgument(address, "address");

            // Change the protection in the target process
            if (Kernel32.VirtualProtectEx(processHandle, address, size, protection, out oldProtection))
            {
                // Return the old protection
                return(true);
            }

            // Else the protection couldn't be changed
            return(false);
        }
Example #16
0
        /// <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 int SuspendThread(ASafeMemoryHandle threadHandle)
        {
            // Check if the handle is valid
            AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle");

            // Suspend the thread
            var ret = Kernel32.SuspendThread(threadHandle);

            // If the function failed
            if (ret == int.MaxValue)
            {
                throw new Win32Exception("Couldn't suspend the thread.");
            }

            return(ret);
        }
Example #17
0
        /// <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
            AHandleManipulator.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.");
            }
        }
Example #18
0
        /// <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
            AHandleManipulator.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);
        }
Example #19
0
        /// <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(ASafeMemoryHandle handle, TimeSpan?timeout)
        {
            // Check if the handle is valid
            AHandleManipulator.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);
        }
Example #20
0
        /// <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
            AHandleManipulator.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);
        }
Example #21
0
        /// <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
            AHandleManipulator.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);
        }
Example #22
0
        /// <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(ASafeMemoryHandle processHandle, IntPtr address, int size)
        {
            // Check if the handles are valid
            AHandleManipulator.ValidateAsArgument(processHandle, "processHandle");
            AHandleManipulator.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")}.");
        }
Example #23
0
        public static IntPtr Allocate(ASafeMemoryHandle processHandle, IntPtr address, int size,
                                      MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite,
                                      MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit)
        {
            // Check if the handle is valid
            AHandleManipulator.ValidateAsArgument(processHandle, "processHandle");

            // Allocate a memory page
            var ret = Kernel32.VirtualAllocEx(processHandle, address, 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).");
        }
Example #24
0
        /// <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
            AHandleManipulator.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.");
            }
        }
Example #25
0
        /// <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(ASafeMemoryHandle processHandle)
        {
            // Check if the handle is valid
            AHandleManipulator.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}'.");
        }
Example #26
0
        /// <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 ASafeMemoryHandle CreateRemoteThread(ASafeMemoryHandle processHandle, IntPtr startAddress,
                                                           IntPtr parameter, ThreadCreationFlags creationFlags = ThreadCreationFlags.Run)
        {
            // Check if the handles are valid
            AHandleManipulator.ValidateAsArgument(processHandle, "processHandle");
            AHandleManipulator.ValidateAsArgument(startAddress, "startAddress");

            // Create the remote thread
            int threadId;
            var ret = Kernel32.CreateRemoteThread(processHandle, IntPtr.Zero, 0, startAddress, parameter, creationFlags,
                                                  out threadId);

            // 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")}.");
        }
Example #27
0
        /// <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(ASafeMemoryHandle threadHandle)
        {
            // Check if the handle is valid
            AHandleManipulator.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}'.");
        }
Example #28
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(ASafeMemoryHandle threadHandle,
                                                     ThreadContextFlags contextFlags = ThreadContextFlags.Full)
        {
            // Check if the handle is valid
            AHandleManipulator.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.");
        }
Example #29
0
        /// <summary>
        ///     Retrieves the termination status of the specified thread.
        /// </summary>
        /// <param name="threadHandle">A handle to the thread.</param>
        /// <returns>
        ///     Nullable type: the return value is A pointer to a variable to receive the thread termination status or
        ///     <code>null</code> if it is running.
        /// </returns>
        public static IntPtr?GetExitCodeThread(ASafeMemoryHandle threadHandle)
        {
            // Check if the handle is valid
            AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle");

            // Create the variable storing the output exit code
            IntPtr exitCode;

            // Get the exit code of the thread
            if (!Kernel32.GetExitCodeThread(threadHandle, out exitCode))
            {
                throw new Win32Exception("Couldn't get the exit code of the thread.");
            }

            // If the thread is still active
            if (exitCode == new IntPtr(259))
            {
                return(null);
            }

            return(exitCode);
        }
Example #30
0
        /// <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(ASafeMemoryHandle processHandle, IntPtr address, byte[] byteArray)
        {
            // Check if the handles are valid
            AHandleManipulator.ValidateAsArgument(processHandle, "processHandle");
            AHandleManipulator.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")}");
        }