有没有办法在C ++ / CLI中从钩子程序返回自定义对象或自定义对象列表?

时间:2011-05-19 17:08:06

标签: .net c#-4.0 c++-cli hook code-injection

我正在挂钩简单的托管进程并将动态SPY DLL注入到进程中以从中收集信息,并且还需要将此信息发送到其他进程。

为此,我使用一个注入库,它可以将消息发送到托管进程的主窗口过程。我需要获取所有控件的列表作为列表,这些列表位于挂钩进程中。为此我的钩子程序不能返回一些“对象”除外。这是我的注入器Hook过程代码和此钩子过程的调用者。

Object^ MessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    try
    {
        if (nCode == HC_ACTION)
        {
            if (pCW->message == WM_INVOKEREMOTE)
            {
                // NOTE: This libary is probably loaded by Windows using some "LoadFrom"
                // resembling approach when the hook is installed. Appearantly, this causes
                // the CLR to be unable to find it when deserializing (even though we are
                // actually executing it in this moment!), so we need to help it. See
                // http://discuss.develop.com/archives/wa.exe?A2=ind0303a&L=dotnet-clr&D=0&T=0&P=10291
                AppDomain^ currentDomain = AppDomain::CurrentDomain;
                currentDomain->AssemblyResolve += gcnew ResolveEventHandler(HelperClass::ResolveRequestMessageAssembly);
                RequestMessage^ msg = (RequestMessage^)Deserialize();
                currentDomain->AssemblyResolve -= gcnew ResolveEventHandler(HelperClass::ResolveRequestMessageAssembly);

                // We need the path, otherwise the assembly have to be in the search path for the application in which it is injected
                String^ assemblyFile = Path::Combine(Path::GetDirectoryName(Assembly::GetExecutingAssembly()->Location), msg->AssemblyFile);
                Assembly^ assembly = Assembly::LoadFrom(assemblyFile);

                Type^ type = assembly->GetType(msg->TypeName);

                Object^ retVal = type->InvokeMember(msg->MethodName, BindingFlags::Static | BindingFlags::Public | BindingFlags::InvokeMethod, nullptr, nullptr, msg->Args);
                //Serialize(retVal);
            }
        }
    }
    catch(Object^ ex)
    {
        // No need to make a reference to System.Windows.Forms assembly just to show a
        // messagebox, we just need to make a string conversion
        IntPtr ptr = Marshal::StringToHGlobalUni(ex->ToString());
        LPCTSTR error = reinterpret_cast<LPCTSTR>(ptr.ToPointer());
        ::MessageBox(NULL, error, L"InvokeRemote Failed", MB_ICONERROR | MB_OK);
        Marshal::FreeHGlobal(ptr);
        Serialize(nullptr);
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

调用MessageHookProc

====================

Object^ Injector::InvokeRemote(IntPtr hWnd, String^ assemblyFile, String^ typeName, String^ methodName, array<Object^>^ args)
{
    RequestMessage^ msg = gcnew RequestMessage();
    msg->AssemblyFile = assemblyFile;
    msg->TypeName = typeName;
    msg->MethodName = methodName;
    msg->Args = args;
    ::Serialize(msg);

    HINSTANCE hinstDLL = LoadLibrary((LPCTSTR) _T("InjectLib.dll"));
    DWORD threadID = GetWindowThreadProcessId((HWND)hWnd.ToPointer(), NULL);
    HOOKPROC procAddress = (HOOKPROC)GetProcAddress(hinstDLL, "MessageHookProc");
    HHOOK messageHookHandle = SetWindowsHookEx(WH_CALLWNDPROC, procAddress, hinstDLL, threadID);

    // This forces it to be loaded into the target adress space
    // CALLS ACTUALLY THE HOOK PROCEDURE BY SENDING MESSAGE TO MAIN WINDOW OF HOOKED PROCESSS.
    // ==========================================================================
    SendMessage((HWND)hWnd.ToPointer(), WM_INVOKEREMOTE, 0, 0);   

    ::UnhookWindowsHookEx(messageHookHandle);
    // Object^ retVal = Deserialize();
    return retVal;
}

所以在这里我不希望以这种方式序列化对象,它们必须从钩子程序中被RETUNRED,然后这个调用者应该能够将这些对象传递给其他一些模块或进程。

问候
乌斯曼

1 个答案:

答案 0 :(得分:0)

您需要将数据序列化为一些不使用指针的编码,因为这些指针在任何其他进程中都没有意义。然后你可以使用任何形式的IPC,例如命名管道,用于将编码数据传输到其他进程。