写了第一个勾IAT的APIHOOK 手上事太多 没空写遍历进程部分了

来源:互联网 发布:数据库设置主键自增 编辑:程序博客网 时间:2024/04/27 14:53
看了两天PE结构
照两年前看的<advance windows> 抄的 加了点注释
没有写成dll,HOOK自己的ExitProcess(),永远不退出

------------------------------------------
// MyApiHook.cpp : Defines the entry point for the application.
//

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

#pragma comment(lib,"Dbghelp.lib")


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     // TODO: Place code here.
    PROC pfnOrig = GetProcAddress(GetModuleHandle("Kernel32"), "ExitProcess");
    HMODULE hModCaller = GetModuleHandle("MyApiHook.exe");

    void ReplaceIATEntryInOneMod(PCTSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller);
    int CALLBACK MyExitProcess();

    ReplaceIATEntryInOneMod(
        "Kernel32.dll",
        pfnOrig,
        MyExitProcess,
        hModCaller);

    return 0;
}

int CALLBACK MyExitProcess()
{
    MessageBox(NULL,"HOOK Success!","",MB_OK);
    ExitProcess(0);
    return 1;
}

//这里PROC定义为无参数,返回值为int的函数指针 typedef int (*PROC)()
//使用的时候要hook只需要给函数名赋值就可以了
void ReplaceIATEntryInOneMod(PCTSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hModCaller)
{
    ULONG ulSize;
    //dump IAT,失败则返回
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
                                                hModCaller,
                                                TRUE,
                                                IMAGE_DIRECTORY_ENTRY_IMPORT,
                                                &ulSize);
    if(NULL == pImportDesc)
    {
        return;
    }

    //遍历导入地址表中有那些模块名称,并与要求操作的模块名称比较,若找到,则提前退出循环
    for (;pImportDesc->Name;pImportDesc++)
    {
        PSTR pszModName = (PSTR)((PBYTE)hModCaller + pImportDesc->Name);
        if(0 == lstrcmpiA(pszModName,pszCalleeModName))
            break;
    }
   
    //该模块并没有导入其他模块
    if(0 == pImportDesc->Name)
        return;

    //取得导入表在内存中的实际映射地址数组
    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModCaller + pImportDesc->FirstThunk);
    //遍历导入表
    for (;pThunk->u1.Function;pThunk++)
    {
        //取得当前导入函数地址
        PROC* ppfn = (PROC*) &pThunk->u1.Function;
        //判断这个函数是不是我们要hook的对象
        BOOL bfFound = (*ppfn == pfnCurrent);
       
        //HOOK掉原来的API地址 把跳转地址改写为我们要执行的函数地址
        if (bfFound)
        {
            WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL);
            return;
        }
    }
}