我写了一个全局键盘挂钩的dll,在DllMain入口的DLL_PROCESS_ATTACH分支条件中安装键盘挂钩,记录用户按键到一个文件。
在另一个Exe文件中采用LoadLibrary()加载这个dll,可以成功记录按键。但是采用进程插入的方法,把这个dll插入的explorer.exe中时,挂钩却实效了,尽管SetWindowsHookEx()显示执行成功了,但是系统却并没有调用挂钩的CALLBACK函数。也就无法记录按键了。请问各位知道这是什么原因吗?另外,同样的过程注入一个普通的dll却是成功的,百思不得其解!

解决方案 »

  1.   

    // InjectDll.cpp : Defines the entry point for the application.
    //#include "stdafx.h"//函数前置声明
    BOOL CreateRemoteThreadLoadDll(LPCWSTR lpwLibFile, DWORD dwProcessId);
    BOOL CreateRemoteThreadUnloadDll(LPCWSTR lpwLibFile, DWORD dwProcessId);
    BOOL EnableDebugPrivilege(VOID);
    void GetWorkPath( TCHAR szPath[], int nSize );//全局变量声明
    HANDLE hProcessSnap=NULL;  //进程快照句柄
    DWORD dwRemoteProcessId;   //目标进程ID
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
      // TODO: Place code here.
    //提升权限
    //EnableDebugPrivilege();

    PROCESSENTRY32 pe32={0};

    //打开进程快照
    hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

    if(hProcessSnap==(HANDLE)-1)
    {
    MessageBox(NULL,"打开进程快照失败","",MB_OK);
    return -1;
    }  //失败返回
    pe32.dwSize=sizeof(PROCESSENTRY32);

    if(Process32First(hProcessSnap,&pe32)) //获取第一个进程
    {
    do{
    char  te[MAX_PATH];
    strcpy(te,pe32.szExeFile);
    if(_strnicmp(te,"notepad.exe",11)==0)
    {
    dwRemoteProcessId=pe32.th32ProcessID;
    break;
    }  
    }  
    while(Process32Next(hProcessSnap,&pe32));//获取下一个进程
    }
    else
    {
    MessageBox(NULL,"取第一个进程失败","",MB_OK);
    return -1;
    }
        
    char  filename[MAX_PATH];
    strcpy(filename,"");
    GetWorkPath(filename,MAX_PATH);
    strcat(filename,"\\KBHook.dll");
    WCHAR wsz[MAX_PATH];
    swprintf(wsz, L"%S", filename);
    LPCWSTR p = wsz;
    if(CreateRemoteThreadLoadDll(p,dwRemoteProcessId))
    //MessageBox(NULL,"Inject OK!","",MB_OK);
    //CreateRemoteThreadUnloadDll(p,dwRemoteProcessId);
    return 0;
    }
    BOOL CreateRemoteThreadLoadDll(LPCWSTR lpwLibFile, DWORD dwProcessId)
    {
    BOOL bRet = FALSE;
    HANDLE hProcess = NULL, hThread = NULL;
    PWSTR pszLibRemoteFile = NULL;

    __try
    {
    hProcess = OpenProcess(
    PROCESS_CREATE_THREAD |
    PROCESS_VM_OPERATION |
    PROCESS_VM_WRITE,
    FALSE, dwProcessId);

    if (hProcess == NULL)
    __leave;

    int cch = 1 + lstrlenW(lpwLibFile);
    int cb = cch * sizeof(WCHAR);

    pszLibRemoteFile = (PWSTR)VirtualAllocEx(
    hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
    if (pszLibRemoteFile == NULL)
    __leave;

    BOOL bw = WriteProcessMemory(hProcess, pszLibRemoteFile, 
    (PVOID)lpwLibFile, cb, NULL);
    if (!bw)
    __leave;

    PTHREAD_START_ROUTINE pfnThreadRnt = (PTHREAD_START_ROUTINE)
    GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    if (pfnThreadRnt == NULL)
    __leave;

    hThread = CreateRemoteThread(hProcess, NULL, 0,
    pfnThreadRnt, pszLibRemoteFile, 0, NULL);
    if (hThread == NULL)
    __leave;

    WaitForSingleObject(hThread, INFINITE);

    bRet = TRUE;
    }__finally
    {
    if (pszLibRemoteFile != NULL)
    VirtualFreeEx(hProcess, pszLibRemoteFile, 0, MEM_RELEASE);

    if (hThread != NULL)
    CloseHandle(hThread);

    if (hProcess != NULL)
    CloseHandle(hProcess);
    }

    return bRet;
    }
    BOOL CreateRemoteThreadUnloadDll(LPCWSTR lpwLibFile, DWORD dwProcessId)
    {
    BOOL bRet = FALSE;
    HANDLE hProcess = NULL, hThread = NULL;
    HANDLE hSnapshot = NULL;

    __try
    {
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
    if (hSnapshot == NULL)
    __leave;
    MODULEENTRY32W me = {sizeof(MODULEENTRY32W)};
    BOOL bFound = FALSE;
    BOOL bMoreMods = Module32FirstW(hSnapshot, &me);
    for (; bMoreMods; bMoreMods = Module32NextW(hSnapshot, &me))
    {
    bFound = (lstrcmpiW(me.szModule, lpwLibFile) == 0) ||
    (lstrcmpiW(me.szExePath, lpwLibFile) == 0);
    if (bFound)
    break;
    }

    if (!bFound)
    __leave;

    hProcess = OpenProcess(
    PROCESS_CREATE_THREAD |
    PROCESS_VM_OPERATION,
    FALSE, dwProcessId);

    if (hProcess == NULL)
    __leave;

    PTHREAD_START_ROUTINE pfnThreadRnt = (PTHREAD_START_ROUTINE)
    GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
    if (pfnThreadRnt == NULL)
    __leave;

    hThread = CreateRemoteThread(hProcess, NULL, 0,
    pfnThreadRnt, me.modBaseAddr, 0, NULL);
    if (hThread == NULL)
    __leave;

    WaitForSingleObject(hThread, INFINITE);

    bRet = TRUE;
    }__finally
    {
    if (hSnapshot != NULL)
    CloseHandle(hSnapshot);

    if (hThread != NULL)
    CloseHandle(hThread);

    if (hProcess != NULL)
    CloseHandle(hProcess);
    }

    return bRet;
    }BOOL EnableDebugPrivilege()
    {
    HANDLE hToken;
    BOOL fOk=FALSE;
    if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
        {
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount=1;
    if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid))
    MessageBox(NULL,"Can't lookup privilege value.","",MB_OK);
    tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))
    MessageBox(NULL,"Can't adjust privilege value.","",MB_OK);
    fOk=(GetLastError()==ERROR_SUCCESS);
    CloseHandle(hToken);
        }
    return fOk;
    }
    void GetWorkPath( char szPath[], int nSize )
    {
    GetModuleFileName( NULL, szPath, nSize );
    char *p = strrchr( szPath, '\\' ); 
    *p = 0;
    }
      

  2.   

    解决了,原来键盘挂钩不能再dll加载的时候安装,在dll加载后单独开一个线程,在其中安装就行了!
      

  3.   

    其实你必将钩子注入呢,你的程序中安装钩子,一样可以锁explore.exe呀。