将托管DLL注入本机进程问题

时间:2010-02-01 04:44:30

标签: dll process native managed inject

我需要在聊天程序中创建一个richedit控件(我正在尝试创建一个音乐机器人)。 我不知道如何在c / c ++中编码,但我能够使用c ++使用CLR Hosting将托管代码注入聊天程序。但是会出现夫妻问题。希望我能从这里得到一些帮助。

  1. 我的托管代码将在完成线程后退出。我需要让它继续运行
  2. 当我尝试使用SetWindowLong api和GWL_WNDPROC对richedit控件进行子类化时,聊天程序冻结了。
  3. 有人能指出我这样做的正确方法吗?或者甚至可以在托管代码中执行此操作?

    由于

3 个答案:

答案 0 :(得分:1)

这种东西取决于很多因素,很难开始。你能提供更多细节吗?

在一般级别,1:如果您使用ICLRRuntimeHost::ExecuteInDefaultAppDomain(pwzAssemblyPath, pwzTypeName, pwzMethodName, pwzArgument)来执行托管代码,那么只要pwzMethodName表示的方法完成,托管执行就会停止。如果你有其他任务要坚持不懈,并且不想在此期间暂停此调用,那么最好的办法就是让pwzMethodName在另一个线程上启动一些程序循环函数。

对于2,如果您将代码注入目标进程并与控件进行交互,则线程安全性可能是一个巨大的问题。我个人没有使用过SetWindowLong api,但它可能与从非调度程序线程修改控件有关。

答案 1 :(得分:0)

这是我的C#

public class Class1
{

    [DllImport("kernel32", SetLastError = true)]
    public static extern IntPtr LoadLibrary(string lpFileName);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", EntryPoint = "GetWindowLong", SetLastError = true)]
    public static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true)]
    public static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
    public static extern int SetWindowLong32(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
    public static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
    {
        if (IntPtr.Size == 8)
            return GetWindowLongPtr64(hWnd, nIndex);
        else
            return GetWindowLongPtr32(hWnd, nIndex);
    }

    public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
    {
        if (IntPtr.Size == 8)
            return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
        else
            return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
    }


    public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);


    public const int GWL_WNDPROC = -4;
    public const int HWND_MESSAGE = -3;
    public const int WM_LBUTTONDOWN = 513;


    public static int Test(String pwzArgument)
    {

        f = new Form1();
        f.Show();

        Process p = Process.GetCurrentProcess();

        string s = "Name: " + p.ProcessName + "\nTitle: " + p.MainWindowTitle +  "\nHandle: " + p.MainWindowHandle.ToString();


        Show(s);

        Show("Started");
        Subclasshwnd(p.MainWindowHandle);
        //For i = 0 To 100000000
        //' Show("Loop", "")
        //Threading.Thread.CurrentThread.Sleep("10000")
        //Next
        return 1;
    }



    public static void Show(string input)
    {
        MessageBox.Show(input);
        f.Settext(input +  "\n");
    }



    public static WndProcDelegate _WndProc;
    public static IntPtr _OldWndProc;
    public static IntPtr _hWnd;
    public static Form1 f;


    public static void Subclasshwnd(IntPtr hWnd)
    {

        _WndProc = new WndProcDelegate(WndProc);
       // _OldWndProc = GetWindowLongPtr(hWnd, GWL_WNDPROC);

       _OldWndProc=  SetWindowLongPtr(hWnd, GWL_WNDPROC,Marshal.GetFunctionPointerForDelegate(_WndProc));

       // Show(_OldWndProc.ToString());
    }

    // this is the new wndproc, just show a messagebox on left button down:
    public static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam,IntPtr lParam)
    {
        System.Diagnostics.Debug.WriteLine(msg);
        Show(msg.ToString());

        return CallWindowProc(_OldWndProc, hWnd, msg, wParam, lParam);
    }


}

这是我的C ++代码

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        MessageBox(0, L"Dll Injection Successful! ", L"Dll Injector", MB_ICONEXCLAMATION | MB_OK);      
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&StartTheDotNetRuntime, 0, 0, NULL);
        break;

    case DLL_THREAD_ATTACH:  break;
    case DLL_THREAD_DETACH:  break;
    case DLL_PROCESS_DETACH:

        break;
    }

    return TRUE;







 void StartTheDotNetRuntime()

{

    ICLRRuntimeHost *pClrHost = NULL;
    HRESULT hr = CorBindToRuntimeEx(NULL, L"wks", 0, CLSID_CLRRuntimeHost,IID_ICLRRuntimeHost, (PVOID*)&pClrHost);
    hr = pClrHost->Start();

    DWORD dwRet = 0;
    hr = pClrHost->ExecuteInDefaultAppDomain(L"ClassLibrary2.dll",L"ClassLibrary2.Class1", L"Test", L"MyParameter", &dwRet);   
    hr = pClrHost->Stop();    
    pClrHost->Release();
}

答案 2 :(得分:0)

另一种“更动态”的方法是在Managed C ++中编写可以注入的库。

托管C ++库可以导出本机函数以用于将其加载到另一个进程中。

只在该Managed C ++库中编写一些允许您加载额外库的代码。

该库可以重复用于注入未来的对象......

请参阅:http://www.vbib.be/index.php?name=PNphpBB2&file=viewtopic&p=38982