Partager via


Sample code for CreateRemoteThread in C#.

 
// Sample for CreateRemoteThread in C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace CreateThread
{
    class Program
    {
        #region standard imports from kernel32

        // Thread proc, to be used with Create*Thread
        public delegate int ThreadProc(IntPtr param);

        // Friendly version, marshals thread-proc as friendly delegate
        [DllImport("kernel32")]
        public static extern IntPtr CreateThread(
            IntPtr lpThreadAttributes,
            uint dwStackSize,
            ThreadProc lpStartAddress, // ThreadProc as friendly delegate
            IntPtr lpParameter,
            uint dwCreationFlags,
            out uint dwThreadId);

        // Marshal with ThreadProc's function pointer as a raw IntPtr.
        [DllImport("kernel32", EntryPoint="CreateThread")]
        public static extern IntPtr CreateThreadRaw(
            IntPtr lpThreadAttributes,
            uint dwStackSize,
            IntPtr lpStartAddress, // ThreadProc as raw IntPtr
            IntPtr lpParameter,
            uint dwCreationFlags,
            out uint dwThreadId);


        // CreateRemoteThread, since ThreadProc is in remote process, we must use a raw function-pointer.
        [DllImport("kernel32")]
        public static extern IntPtr CreateRemoteThread(        
          IntPtr hProcess,
          IntPtr lpThreadAttributes,
          uint dwStackSize,
          IntPtr lpStartAddress, // raw Pointer into remote process
          IntPtr lpParameter,
          uint dwCreationFlags,
          out uint lpThreadId
        );

        [DllImport("kernel32")]
        public static extern IntPtr GetCurrentProcess();
        
        const uint PROCESS_ALL_ACCESS = 0x000F0000 | 0x00100000 | 0xFFF;
        [DllImport("kernel32")]
        public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("kernel32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr hObject);



        [DllImport("kernel32")]
        public static extern 
        uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

        [DllImport("kernel32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);

        #endregion // standard imports from kernel32

        // stdcall        
        static int MyThreadProc(IntPtr param)
        {
            int pid = Process.GetCurrentProcess().Id;
            Console.WriteLine("Pid {0}: Inside my new thread!. Param={1}", pid, param.ToInt32());
            return 1;
        }

        // Helper to wait for a thread to exit and print its exit code
        static void WaitForThreadToExit(IntPtr hThread)
        {
            WaitForSingleObject(hThread, unchecked((uint)-1));

            uint exitCode;
            GetExitCodeThread(hThread, out exitCode);
            int pid = Process.GetCurrentProcess().Id;
            Console.WriteLine("Pid {0}: Thread exited with code: {1}", pid, exitCode);
        }

        // Main function 
        static void Main(string[] args)
        {
            int pid = Process.GetCurrentProcess().Id;
            if (args.Length == 0)
            {
                Console.WriteLine("Pid {0}:Started Parent process", pid);
                
                // Spawn the child
                string fileName = Process.GetCurrentProcess().MainModule.FileName.Replace(".vshost", "");                

                // Get thread proc as an IntPtr, which we can then pass to the 2nd-process.
                ThreadProc proc = new ThreadProc(MyThreadProc);
                IntPtr fpProc = Marshal.GetFunctionPointerForDelegate(proc);

                // Spin up the other process, and pass our pid and function pointer so that it can
                // use that to call CreateRemoteThraed
                string arg = String.Format("{0} {1}", pid, fpProc);
                ProcessStartInfo info = new ProcessStartInfo(fileName, arg);
                info.UseShellExecute = false; // share console, output is interlaces.
                Process processChild = Process.Start(info);
                    
                processChild.WaitForExit();
                return;
            }
            else
            {
                Console.WriteLine("Pid {0}:Started Child process", pid);
                uint pidParent = uint.Parse(args[0]);
                IntPtr fpProc = new IntPtr(int.Parse(args[1]));

                IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pidParent);

                uint dwThreadId;
                // Create a thread in the first process.
                IntPtr hThread = CreateRemoteThread(
                    hProcess,
                    IntPtr.Zero,
                    0,
                    fpProc, new IntPtr(6789),
                    0,
                    out dwThreadId);
                WaitForThreadToExit(hThread);
                return;
            }
        }

        // Other  variations of create thread
        static void OtherMain(string[] args)
        {
            IntPtr fpProc = IntPtr.Zero;

            ThreadProc proc = new ThreadProc(MyThreadProc);
            fpProc = Marshal.GetFunctionPointerForDelegate(proc);

            uint dwThreadId;
#if false
            IntPtr hThread = CreateThreadRaw(
                IntPtr.Zero,
                0,
                fpProc, new IntPtr(1234),
                0, // flags
                out dwThreadId);
#elif false
            IntPtr hThread = CreateThread(
                IntPtr.Zero,
                0,
                proc, new IntPtr(1234),
                0, // flags
                out dwThreadId);
#else
            IntPtr hThisProcess = GetCurrentProcess();
                    
            IntPtr hThread = CreateRemoteThread(        
                hThisProcess,
                IntPtr.Zero,
                0,
                fpProc, new IntPtr(5678),
                0,
                out dwThreadId);
#endif      
            WaitForThreadToExit(hThread);
        }
    }
}

Comments

  • Anonymous
    September 28, 2006
    If you want to create a new thread in your process in C#, you can use Thread.Start. But things are a...