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

发布于 2024-08-19 11:17:22 字数 299 浏览 13 评论 0原文

我需要在聊天程序中对 Richedit 控件进行子类化(我正在尝试制作一个音乐机器人)。 我不知道如何用 c/c++ 编码,但我能够使用 C++ 将托管代码注入到使用 CLR 托管的聊天程序中。但出现了一些问题。希望我能从这里得到一些帮助。

  1. 我的托管代码将在完成线程后退出。我需要保持它运行
  2. 当我尝试使用 SetWindowLong api 和 GWL_WNDPROC 子类化 richedit 控件时,聊天程序冻结了。

有人能指出我正确的方法吗?或者甚至可以在托管代码中执行此操作吗?

谢谢

I need to subclass a richedit control in a chat program (I am trying to make a musicbot).
I dont know how to code in c/c++ but i was able to use c++ to inject a managed code into the chat program using CLR Hosting. But couple problems occurs. Hopefully I can get some help from here.

  1. My managed code would exit after it finished the thread. I need to keep it running
  2. When I tried to subclass the richedit control using SetWindowLong api and GWL_WNDPROC the chat program froze.

Could someone point me to a right way to do this? Or is it even possible to do this in managed code?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浮世清欢 2024-08-26 11:17:22

这类事情取决于很多因素,并且可能很难开展。你能提供更多细节吗?

一般来说,对于 1:如果您使用 ICLRRuntimeHost::ExecuteInDefaultAppDomain(pwzAssemblyPath, pwzTypeName, pwzMethodName, pwzArgument) 来执行托管代码,则一旦指定的方法,托管执行就会停止由pwzMethodName完成。如果您想要持久执行其他任务,并且不想让此调用同时挂起,那么最好的选择是让 pwzMethodName 在另一个线程上启动一些程序循环函数。

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

This sort of stuff depends on a lot of factors and can be hard to get going. Can you provide more details?

At a general level, for 1: If you are using ICLRRuntimeHost::ExecuteInDefaultAppDomain(pwzAssemblyPath, pwzTypeName, pwzMethodName, pwzArgument) to execute your managed code, then the managed execution will stop as soon as the method denoted by pwzMethodName finishes. If you have other tasks you want to do persistently, and don't want to have this call hang in the meantime, your best bet is to have pwzMethodName start up some program loop function on another thread.

As for 2, if you're injecting code into a target process and interacting with controls, thread safety can be a huge issue. I personally haven't used SetWindowLong api but it could be something to do with modifying controls from a non-dispatcher thread.

用心笑 2024-08-26 11:17:22

这是我的 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();
}

Here is My 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);
    }


}

And here is my C++ code

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();
}
记忆で 2024-08-26 11:17:22

另一种“更动态”的方法是用托管 C++ 编写一个可以注入的库。

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

仅在托管 C++ 库中编写一些允许您加载额外库的代码。

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

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

Another "More Dynamic" way is to write a library in Managed C++ that can be injected.

A managed C++ library can export native functions to use for loading it into another process.

Only write some code in that Managed C++ library that allows you to load extra libraries.

That library can be re-used to inject future objects...

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文