12

私は C++ の初心者 (3 ~ 4 か月) で、Windows のフックについて学習しようとしています。挿入しようとしている DLL にバグがあり、しばらくすると、DllMain が呼び出されていないことに気付きました。StackOverflow のほぼすべてのスレッドを調べましたが、問題がわかりません。変数を 5 に初期化し、DllMain で変数を 1 に変更して、変数を関数に出力することで、そのことがわかりました。変数は決して変化しません。コードは次のとおりです。

int i = 5;

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved  )
{
    i=1;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        hDll  = (HINSTANCE) hModule;

        break;

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

    }

    return TRUE;
}

bool InstallHook(){
    cout << "INSTALLING HOOK... " << endl;
    cout << i << endl;
    hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) CBTProc, hDll, 0);
    return hHook != NULL;
}

そして、これが私のDLLのロードです...

typedef bool (*InstallHook)();
typedef void (*UninstallHook)();
InstallHook ih;
UninstallHook uh;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            uh();
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    // Bunch of code to initialize a simple window until this: 
    HINSTANCE hDll = LoadLibrary("e:\\projects\\DLL\\ToInject.dll");
    ih = (InstallHook)GetProcAddress(hDll, "InstallHook");
    uh = (UninstallHook)GetProcAddress(hDll, "UninstallHook");
    if (!ih()){
        cout << "SUCCESS" << endl;
    }else{
        cout << "FAILED" << endl;
    }
    // other stuff to create a window
    return Msg.wParam;
}

出力:

INSTALLING HOOK... 
5 // We can see here that the DLL never changed the value of i to 1.
SUCCESS
UNINSTALL HOOK...
4

3 に答える 3

9

次の手順に従って、実用的な例を作成します(これはビジュアルスタジオ用です)。

  • 新しいコンソールアプリケーションを作成します。
  • DLLを確認してください。
  • これをdllmain.cppに配置します。

dllmain.cpp

// dllmain.cpp : Defines the entry point for the DLL application.

#include "stdafx.h"
#include <string>

std::string test = "not Loaded"; 

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    test = "loaded"; //You also change on this location the value of a variable
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        MessageBoxA(NULL,"test","test",NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" __declspec (dllexport) bool example()
{
    MessageBoxA(NULL,test.c_str(),"test",NULL);
    return true;
}
  • コードをコンパイルし、リリースモードになっていることを確認します。
  • 新しいコンソールアプリケーションを作成します。
  • 空のプロジェクトを確認してください。
  • main.cppという名前の新しいファイルを作成します。
  • これをファイルにコピーします。

Main.cpp

#include <windows.h>

typedef bool (*testFunction)();

testFunction dllFunction;

int main()
{

    HINSTANCE hDll = LoadLibraryA("example.dll");
    if(hDll)
    {
        dllFunction = (testFunction)GetProcAddress(hDll, "example");
        dllFunction();
    }

    return 0;
}
  • プロジェクトをビルドし、リリースモードになっていることを確認します。
  • リリースフォルダに作成したDLLをコンソールアプリケーションからコピーします。
  • プログラムを実行します。

ここで動作します。テストでMessageBoxを取得し、ロードで1回取得します。このコードを自分のコードと比較できます。問題を見つけていただければ幸いです。

于 2013-01-11T07:30:50.343 に答える
2

同じプログラムにaWinMainとaが表示されます。cout作成したプロジェクトの種類を説明してください。

ここでフックの例を見ることができます-http://www.codeproject.com/Articles/5002/Mousey-Roll-Over-and-Park

于 2013-01-11T07:39:35.860 に答える
2
extern "C" BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved  )

C++ でコンパイルする場合は、DllMain 関数の前に " extern "C" " を追加する必要があります。

于 2016-12-04T06:51:19.527 に答える