samuri25404 Grandmaster Cheater
  Reputation: 7
  Joined: 04 May 2007 Posts: 955 Location: Why do you care?
  | 
		
			
				 Posted: Tue Jan 29, 2008 10:19 pm    Post subject: [C#] Static Dll Injector | 
				       | 
			 
			
				
  | 
			 
			
				REEDIT: The Dll Injector has been fixed!
 
 
I've created a static dll injector class (if you didn't get by the title, :p). 
 
 
So, here it is:
 
 
 	  | Code: | 	 		  
 
using System;
 
using System.Diagnostics;
 
using System.Runtime.InteropServices;
 
 
//This is used to actually inject the specific DLL into the selected process
 
 
namespace InjectMe
 
{
 
    public static class Inject
 
    {
 
        private static class WINAPI
 
        {
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern IntPtr OpenProcess(
 
                UInt32 dwDesiredAccess, 
 
                Int32 bInheritHandle, 
 
                UInt32 dwProcessId);
 
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern Int32 CloseHandle(
 
                IntPtr hObject);
 
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern IntPtr GetProcAddress(
 
                IntPtr hModule,
 
                string lpProcName);
 
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern IntPtr GetModuleHandle(
 
                string lpModuleName);
 
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern IntPtr VirtualAllocEx(
 
                IntPtr hProcess,
 
                IntPtr lpAddress,
 
                IntPtr dwSize,
 
                uint flAllocationType,
 
                uint flProtect);
 
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern Int32 WriteProcessMemory(
 
                IntPtr hProcess, 
 
                IntPtr lpBaseAddress, 
 
                byte[] buffer, 
 
                uint size, 
 
                out IntPtr lpNumberOfBytesWritten);
 
 
            [DllImport("kernel32.dll", SetLastError = true)]
 
            public static extern IntPtr CreateRemoteThread(
 
                IntPtr hProcess,
 
                IntPtr lpThreadAttribute,
 
                IntPtr dwStackSize,
 
                IntPtr lpStartAddress,
 
                IntPtr lpParameter,
 
                uint dwCreationFlags,
 
                IntPtr lpThreadId);
 
 
            public static class VAE_Enums
 
            {
 
                public enum AllocationType
 
                {
 
                    MEM_COMMIT = 0x1000,
 
                    MEM_RESERVE = 0x2000,
 
                    MEM_RESET = 0x80000,
 
                }
 
 
                public enum ProtectionConstants
 
                {
 
                    PAGE_EXECUTE = 0X10,
 
                    PAGE_EXECUTE_READ = 0X20,
 
                    PAGE_EXECUTE_READWRITE = 0X40,
 
                    PAGE_EXECUTE_WRITECOPY = 0X80,
 
                    PAGE_NOACCESS = 0X01
 
                }
 
            }
 
        }        
 
 
        public static bool DoInject(
 
            Process pToBeInjected, 
 
            string sDllPath, 
 
            out string sError)
 
        {
 
            IntPtr hwnd = IntPtr.Zero;
 
            if (!CRT(pToBeInjected, sDllPath, out sError, out hwnd)) //CreateRemoteThread
 
            {
 
                //close the handle, since the method wasn't able to get to that
 
                if (hwnd != (IntPtr)0)
 
                    WINAPI.CloseHandle(hwnd);
 
                return false;
 
            }
 
            int wee = Marshal.GetLastWin32Error();
 
            return true;
 
        }
 
 
        private static bool CRT(
 
            Process pToBeInjected,
 
            string sDllPath,
 
            out string sError,
 
            out IntPtr hwnd)
 
        {
 
            sError = String.Empty; //in case we encounter no errors
 
 
            IntPtr hndProc = WINAPI.OpenProcess(
 
                (0x2 | 0x8 | 0x10 | 0x20 | 0x400), //create thread, query info, operation
 
                //write, and read
 
                1, 
 
                (uint)pToBeInjected.Id);
 
 
            hwnd = hndProc;
 
 
            if (hndProc == (IntPtr)0) 
 
            {
 
                sError = "Unable to attatch to process.\n";
 
                sError += "Error code: " + Marshal.GetLastWin32Error();
 
                return false;
 
            }
 
 
            IntPtr lpLLAddress = WINAPI.GetProcAddress(
 
                WINAPI.GetModuleHandle("kernel32.dll"),
 
                "LoadLibraryA");
 
 
            if (lpLLAddress == (IntPtr)0)
 
            {
 
                sError = "Unable to find address of \"LoadLibraryA\".\n";
 
                sError += "Error code: " + Marshal.GetLastWin32Error();
 
                return false;
 
            }
 
 
            IntPtr lpAddress = WINAPI.VirtualAllocEx(
 
                hndProc,
 
                (IntPtr)null,
 
                (IntPtr)sDllPath.Length, //520 bytes should be enough
 
                (uint)WINAPI.VAE_Enums.AllocationType.MEM_COMMIT |
 
                (uint)WINAPI.VAE_Enums.AllocationType.MEM_RESERVE,
 
                (uint)WINAPI.VAE_Enums.ProtectionConstants.PAGE_EXECUTE_READWRITE);
 
 
            if (lpAddress == (IntPtr)0)
 
            {
 
                if (lpAddress == (IntPtr)0)
 
                {
 
                    sError = "Unable to allocate memory to target process.\n";
 
                    sError += "Error code: " + Marshal.GetLastWin32Error();
 
                    return false;
 
                }
 
            }
 
 
            byte[] bytes = CalcBytes(sDllPath);
 
            IntPtr ipTmp = IntPtr.Zero;
 
 
            WINAPI.WriteProcessMemory(
 
                hndProc,
 
                lpAddress,
 
                bytes,
 
                (uint)bytes.Length,
 
                out ipTmp);
 
 
            if (Marshal.GetLastWin32Error() != 0)
 
            {
 
                sError = "Unable to write memory to process.";
 
                sError += "Error code: " + Marshal.GetLastWin32Error();
 
                return false;
 
            }
 
 
            IntPtr ipThread = WINAPI.CreateRemoteThread(
 
                hndProc,
 
                (IntPtr)null,
 
                (IntPtr)0,
 
                lpLLAddress,
 
                lpAddress,
 
                0,
 
                (IntPtr)null);
 
 
            if (ipThread == (IntPtr)0)
 
            {
 
                sError = "Unable to load dll into memory.";
 
                sError += "Error code: " + Marshal.GetLastWin32Error();
 
                return false;
 
            }
 
 
            return true;
 
        }
 
 
        private static byte[] CalcBytes(string sToConvert)
 
        {
 
            byte[] bRet = System.Text.Encoding.ASCII.GetBytes(sToConvert);
 
            return bRet;
 
        }
 
    }
 
}
 
 | 	  
 
 
I've created a sample application using this class.
 
 
Here's a screenshot:
 
 
[img=http://img169.imageshack.us/img169/3048/picthingtq3.png][/img]
 
 
Basically, you load the app, browse to your dll, select your application, and click inject.
 
 
~~
 
 
Here's the code for the Main form:
 
 
 	  | Code: | 	 		  
 
using System;
 
using System.Diagnostics;
 
using System.ComponentModel;
 
using System.Windows.Forms;
 
 
namespace InjectMe
 
{
 
    public partial class MainUI : Form
 
    {
 
        public MainUI()
 
        {
 
            InitializeComponent();
 
        }
 
 
        public static Process pApplication = null;
 
        public static string  sApplication = String.Empty;
 
 
        private void BtnBrowseDll_Click(object sender, EventArgs e)
 
        {
 
            OpenFileDialog ofd = new OpenFileDialog();
 
            ofd.Filter = "Dynamic Link Library|*.dll";
 
            ofd.FileOk += new CancelEventHandler(dll_FileOk);
 
            ofd.ShowDialog();            
 
        }
 
 
        private void dll_FileOk(object sender, CancelEventArgs e)
 
        {
 
            OpenFileDialog ofd = (OpenFileDialog)sender;
 
            TxtDllPath.Text = ofd.FileName;
 
 
            //now dispose of the object
 
 
            ofd.Dispose();            
 
        }
 
 
        private void BtnBrowseApp_Click(object sender, EventArgs e)
 
        {
 
            ProcFrm pf = new ProcFrm();
 
            pf.ShowDialog(this);
 
            TxtApp.Text = sApplication; //It will wait for pf to close, and before pf
 
            //closes, it will have set sApplication
 
        }
 
 
        private void BtnInject_Click(object sender, EventArgs e)
 
        {
 
            string sError = String.Empty;
 
            if (!Inject.DoInject(pApplication, TxtDllPath.Text, out sError))
 
                MessageBox.Show("The following error occured while injecting the \n" +
 
                    "dll into the application: \n" +
 
                    sError);
 
        }
 
    }
 
}
 
 | 	  
 
 
Here's the code to the Process Form:
 
 
 	  | Code: | 	 		  
 
using System;
 
using System.Diagnostics;
 
using System.Windows.Forms;
 
 
//This class is used to select the process to inject the dll into
 
 
namespace InjectMe
 
{
 
    public partial class ProcFrm : Form
 
    {
 
        public ProcFrm()
 
        {
 
            InitializeComponent();
 
        }
 
 
        private void ProcFrm_Load(object sender, EventArgs e)
 
        {
 
            //populate the list box with all the running processes
 
 
            string sLstItem = String.Empty;
 
 
            foreach (Process p in Process.GetProcesses())
 
            {
 
                sLstItem = p.Id.ToString();
 
                sLstItem = sLstItem.PadLeft(8, '0');
 
                sLstItem = sLstItem + " " + p.ProcessName;
 
                LstProcs.Items.Add(sLstItem);
 
            }
 
            
 
            //now sort
 
 
            LstProcs.Sorted = true; //Some event handler somewhere sorts
 
            //the list box when this is changed to true
 
        }
 
 
        private void LstProcs_DoubleClick(object sender, EventArgs e)
 
        {
 
            BtnSelect_Click(null, null); //=D
 
        }
 
 
        private void BtnSelect_Click(object sender, EventArgs e)
 
        {
 
            if (LstProcs.SelectedIndex == -1)
 
                return;
 
 
            string sPID = String.Empty;
 
            string[] saData = ((string)LstProcs.Items[LstProcs.SelectedIndex]).Split(' ');
 
            sPID = saData[0]; //it'll be "xxxxxxxx procname"
 
            int iPID = int.Parse(sPID);
 
 
            MainUI.pApplication = Process.GetProcessById(iPID);
 
 
            if (MainUI.pApplication != null) 
 
                MainUI.sApplication = MainUI.pApplication.ProcessName;
 
 
            this.Close(); //done with this form
 
        }
 
    }
 
}
 
 | 	  
 
 
CREDITS
 
 
Wiccaan:
 
 
For creating a post about the Dll stuff on Extalia. Since I'm no good at C++, I had to use his code to make a sample Dll to inject into minesweeper 
 
 
MSDN:
 
 
For helping out with all the API crap. =)
 
 
Me:
 
 
For working on this so much. =P
 _________________
  | 
			 
		  |