环境 windows7 + VS2008
以下为dll代码。我hook两个函数TerminateProcess与预期结果一样,SendMessageW时taskmgr.exe老是崩溃
高手看下是为啥,最好亲手调试一下,再得结论
////
//本程序hook任务管器的TerminateProcess,SendMessageW
//一般不hook SendMessageW因为消息一多且MySendMessageW代码又多的情况就会失去响应..
#include <windows.h>
#include <stdio.h>
HANDLE hEvent;     
DWORD IATAddr[2];
DWORD RealAddr[2];
DWORD MyApi[2];
DWORD WINAPI ThreadProc(LPVOID lpParameter);
BOOL IAThook(TCHAR DllName[], TCHAR FunName[], DWORD MyFunAddr, int nAPI);
BOOL WINAPI MyTerminateProcess(HANDLE hProcess, UINT uExitCode);
LRESULT WINAPI MySendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
void ShowError();
BOOL APIENTRY DllMain( HMODULE hModule, DWORD Reason, LPVOID lpReserved)
{
    switch (Reason)
    {
    case DLL_PROCESS_ATTACH: 
{
    HANDLE hThread = ::CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    if (hThread == NULL)
    {
ShowError();
return FALSE;
    }
}break;
    case DLL_THREAD_ATTACH:break;
    case DLL_THREAD_DETACH:break;
    case DLL_PROCESS_DETACH:break;
    }
    return TRUE;//返回TRUE表示DLL允许被加载。LoadLibrary将返回hModule的值
}DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    //hEvent = ::CreateEvent(NULL, FALSE, TRUE, "Rookit");
   // if (hEvent == NULL)
 //   {
// ShowError();
   // }
    MyApi[0] = (DWORD)MyTerminateProcess;
    MyApi[1] = (DWORD)MySendMessage;
    if (!IAThook("KERNEL32.dll", "TerminateProcess", MyApi[0], 0))
    {
return 0;
    }
    if (!IAThook("USER32.dll", "SendMessageW", MyApi[1], 1))
    {
return 0;
    }
    return 1;
}
BOOL IAThook(TCHAR DllName[], TCHAR FunName[], DWORD MyFunAddr, int nAPI)
{
    LPVOID pMap = GetModuleHandle(NULL);
    IMAGE_DOS_HEADER *pMZ = (IMAGE_DOS_HEADER *)pMap;
    IMAGE_NT_HEADERS *pPE = (IMAGE_NT_HEADERS *)((LPBYTE)pMap + pMZ->e_lfanew);
    IMAGE_DATA_DIRECTORY *pDirectory;
    pDirectory = &pPE->OptionalHeader.DataDirectory[1];  //第二成员为导入表
    IMAGE_IMPORT_DESCRIPTOR *pDescriptor; //指向DLL相关信息
    //pIDescriptor指向DLL信息的IMAGE_IMPORT_DESCRIPTOR数组,以全0成员结束
    pDescriptor = (IMAGE_IMPORT_DESCRIPTOR *)((LPBYTE)pMZ + pDirectory->VirtualAddress);
    IMAGE_THUNK_DATA * pData;
    DWORD * pAddr;              //函数在进程中加载地址
    IMAGE_IMPORT_BY_NAME *pName;
    while (pDescriptor->OriginalFirstThunk)  //PE未加载前FirstThunk与OriginalFIrstThunk功能一样
    {
if (strcmp(DllName, (char *)(LPBYTE(pMZ) + pDescriptor->Name)) == 0)
{
    //cout << "找到指定DLL!" << endl;
    pData = (IMAGE_THUNK_DATA *) ((LPBYTE)pMZ + pDescriptor->OriginalFirstThunk);
    pAddr = (DWORD *) ((LPBYTE)pMZ + pDescriptor->FirstThunk);
    while (pData ->u1.AddressOfData)
    {
pName = (IMAGE_IMPORT_BY_NAME *) ((LPBYTE)pMZ + pData->u1.AddressOfData);
if (strcmp(FunName, (char*)pName->Name) == 0)
{
    //cout << "找到指定API函数!" << endl;
    IATAddr[nAPI] = (DWORD)pAddr;    //指向[__jmp API@n]这一句路过jmp(e9)的地址
    RealAddr[nAPI] = *pAddr; //上面地址的内容
    if (!::WriteProcessMemory(GetCurrentProcess(), pAddr, &MyFunAddr, 4, NULL ))
    {
//ShowError();
::MessageBoxW(NULL, L"找到指定DLL与API,但写入内存时出错!", L"提示", MB_OK);
return FALSE;
    }
    ::MessageBoxW(NULL, L"修改成功!", L"提示", MB_ICONINFORMATION);
    return TRUE;
}
pData++;
pAddr++;
    }
    ::MessageBoxW(NULL, L"找到指定DLL但没发现指定导入函数!", L"提示!", MB_OK);
    return FALSE;
}
pDescriptor++;
    }
    ::MessageBoxW(NULL, L"没发现指定DLL", L"提示!", MB_OK);
    return FALSE;
}BOOL WINAPI MyTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
    if (!::WriteProcessMemory(GetCurrentProcess(), (LPVOID)IATAddr[0], &RealAddr[0], 4, NULL ))
    {
//ShowError();
::MessageBoxW(NULL, L"写入内存出错!", L"提示", MB_OK);
return FALSE ;
    }
    ::MessageBoxA(NULL, "系统正调用TerminateProcess杀进程,但被阻止了!", "HOOK", MB_ICONINFORMATION);
    //这边可调用真正的TerminateProcess()
    //::TerminateProcess(hProcess, uExitCode);
    if (!::WriteProcessMemory(GetCurrentProcess(), (LPVOID)IATAddr[0], &MyApi[0], 4, NULL ))
    {
//ShowError();
::MessageBoxW(NULL, L"写入内存出错!", L"提示", MB_OK);
return FALSE;
    }
    return TRUE;
}
LRESULT WINAPI MySendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
   // if (::WaitForSingleObject(hEvent, INFINITE) == WAIT_FAILED)
   // {
// ShowError();
//::ExitProcess(0xff);
    //}
    char buff[0xff] = {0};
    if (!::WriteProcessMemory(GetCurrentProcess(), (LPVOID)IATAddr[1], &RealAddr[1], 4, NULL ))
    {
//ShowError();
::MessageBoxW(NULL, L"写入内存出错!", L"提示", MB_OK);
return NULL ;
    }  //  if (Msg == WM_CLOSE)
    //{
//::MessageBoxA(NULL, "目标正发送WM_CLOSE", "HOOK", 0);
   // }
    ::SendMessageW(hWnd, Msg, wParam, lParam);
    if (!::WriteProcessMemory(GetCurrentProcess(), (LPVOID)IATAddr[1], &MyApi[1], 4, NULL ))
    {
//ShowError();
::MessageBoxW(NULL, L"写入内存出错!", L"提示", MB_OK);
return NULL;
    }
 //   if(!::SetEvent(hEvent))//通知状态
  //  {
// ShowError();
///::ExitProcess(0xff);
 //   }
    return 1234;
}
void ShowError()
{
    LPTSTR lpMsgBuf;
    ::FormatMessage( 
FORMAT_MESSAGE_ALLOCATE_BUFFER | 
FORMAT_MESSAGE_FROM_SYSTEM | 
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
::GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
(LPTSTR)&lpMsgBuf,
0,
NULL);
    ::MessageBox(NULL, lpMsgBuf, NULL, MB_OK | MB_ICONSTOP);
    ::LocalFree(lpMsgBuf);//释放操作系统开辟的缓冲区地址
}

解决方案 »

  1.   

    崩溃了看堆栈~看down在哪里了
      

  2.   

    问题找着了:原因是MySendMessage()中,我给随便返回了个值(retun 1234;)..结果任务管理器对这个返回值进行操作,导致崩溃。。所以MySendMessage()必须返回有意义的值这样就行:eg:
    int n = ::SendMessageW(hWnd, Msg, wParam, lParam); 
    return n;//这种返回值是有意义的。taskmgr.exe对此返回值进行操作时不会引去崩溃