下面的2个函数我是照抄windows程序设计上的...可是居然每用。
一个是打印全部导入的函数,另外一个是修改PE文件的导入表的MessageBoxA这个函数....
可是问题是 打印全部导入函数的回报错.还有修改PE文件的也回找不到MessageBoxA这个函数...为什么...!
#include <windows.h>
#include <iostream>///这个HOOK API是借助修改PE文件的导入表来替换MESSAGEBOX的函数地址来实现的using namespace std;//挂钩指定模块hmod对MESSAGEBOXA的调用
BOOL SetHook(HMODULE hMod);
//定义messageboxa的函数原形
typedef int (WINAPI *PFUNC)(HWND, LPCSTR,LPCSTR,UINT);PROC g_orgProc = (PROC)MessageBoxA;//保存函数的地址
//这个函数打印了导入的所有函数
void PrintAllImportFunc(HMODULE hMod)
{
    IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)hMod;//PE文件是从64字节的DOS头开始的
    //DOS头里的E_lfanew是NT头的offset量,加上hmod就得到了NT头的地址
    //然后NT头里先是4字节的“PE00”字符,然后是20字节的饿不止到什么,再然后是OPTINAL头
    IMAGE_OPTIONAL_HEADER *pOptHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew+24);
    //在OPTINAL头里保存了很多的信息,这里是得到导入表的地址
    IMAGE_IMPORT_DESCRIPTOR *pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod+pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    while(pImportDes->FirstThunk)
    {
        char* pszDllName = (char*)(BYTE*)hMod + pImportDes->Name;
        cout<<"模块名称:"<<pszDllName<<endl;
        //一个IMAGE_THUNK_DATA是一个双字,它指定了一个导入函数
        IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod+pImportDes->OriginalFirstThunk);
        int n=0;
        while(pThunk->u1.Function)
        {
            //取得函数名称.hint/name表前2个字节是函数序号,后面的是名称
            char *pszFuncName = (char*)((BYTE*)pThunk->u1.AddressOfData+2);
            //取得函数地址,IAT就是一个DWORD叔祖
            PDWORD lpAddr = (DWORD*)((BYTE*)hMod+pImportDes->FirstThunk)+n;
            //打印
            printf("从此模块导入的函数: %-25s",pszFuncName);
            printf("函数地址: %X\n", lpAddr);
            n++;
            pThunk++;
        }
        cout<<endl;
        pImportDes++;
    }}int WINAPI MyMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCation, UINT type)
{
    return ((PFUNC)g_orgProc)(hWnd, "new function","Demo",type);
}BOOL SetHook(HMODULE hMod)
{
    IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)hMod;//PE文件是从64字节的DOS头开始的
    //DOS头里的E_lfanew是NT头的offset量,加上hmod就得到了NT头的地址
    //然后NT头里先是4字节的“PE00”字符,然后是20字节的饿不止到什么,再然后是OPTINAL头
    IMAGE_OPTIONAL_HEADER *pOptHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew+24);
    //得到导入表的地址
    IMAGE_IMPORT_DESCRIPTOR *pImportDes = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod+pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);    //在导入表中寻找USER32.DLL模块,因为MESSAGEBOXA是从USER32.DLL里导出的
    while(pImportDes->FirstThunk)//导入表的FirstThunk指向一个导入表的数组,以\0为结尾
    {
        char* pszDllName = (char*)((BYTE*)hMod+pImportDes->Name);
        if(strcmp(pszDllName,"USER32.dll")==0)
        {
            break;
        }
        pImportDes++;
    }    if(pImportDes->FirstThunk)
    {
        //一个IMAGE——THUNK-DATA结构是一个DWORD,它指定了一个导入函数
        //导入地址表其实是一个IMAGE_THUNK_DATA的数组,也就是DWORD数组
        IMAGE_THUNK_DATA *pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod+pImportDes->FirstThunk);        while(pThunk->u1.Function)//这个应该是导入模块的函数地址
        {
            //lpAddr指向的内存保存了函数地址
            DWORD *lpAddr = (DWORD*)&(pThunk->u1.Function);            if(*lpAddr == (DWORD)g_orgProc)//如果这个函数是MESSAGEBOXA的话
            {
                //修改IAT表项,让原本的饿函数地址变成自定义的函数
                //相当于语句*lpAddr = (DWORD)MyMessageBox;
                //不过在RELEASE版本里面因为lpAddr志向的是 只度的所以在写入内存之前要先修改它所在页的属性
                DWORD dwOldProtect;
                MEMORY_BASIC_INFORMATION mbi;
                VirtualQuery(lpAddr,&mbi,sizeof(mbi));//得到lpAddr制向的页的属性
                VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);//修改保护模式
                DWORD* lpNewProc = (DWORD*)MyMessageBox;
                ::WriteProcessMemory(GetCurrentProcess(),lpAddr,lpNewProc,sizeof(DWORD),NULL);
                VirtualProtect(lpAddr,sizeof(DWORD),dwOldProtect,0);
                return true;
            }            pThunk++;
        }
        cout<<"没有找到对应的函数"<<endl;
    }
    else
        cout<<"没有找到USER32.DLL";
    return false;
}int main()
{    ::MessageBox(NULL, "old function","Demo",0);
    SetHook(GetModuleHandle(NULL));
    ::MessageBox(NULL,"old function","Demo",0);
    PrintAllImportFunc(GetModuleHandle(NULL));
    return 0;
}