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
_________________
|
|