HOOK钩子技术3 IATHook

来源:互联网 发布:台达plc编程软件安装 编辑:程序博客网 时间:2024/06/06 07:49

原理

如果程序中使用了静态链接库文件,那么PE文件中就会有关于这些函数的导入表的存在,程序通过调用IAT表来定位函数地址从而实现调用。如果将这些已经确定好的函数地址给替换成为恶意函数地址,那么就会欺骗 程序运行恶意函数。

编码测试

  • IDE: VS 2008
  • APP:DLL TYPE
  • OS: WINDOWS XP SP3
// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "stdafx.h"#include <windows.h>//定义函数指针,和CreateFileW一致typedef HANDLE ( WINAPI *CRETEFILEW)( LPCTSTR,               DWORD,                 DWORD ,                LPSECURITY_ATTRIBUTES, DWORD                , DWORD                , HANDLE                );CRETEFILEW dwCreateFileWAddr = 0;//msdn的搬运工T_T// HANDLE WINAPI CreateFile(//                       _In_     LPCTSTR               lpFileName,//                       _In_     DWORD                 dwDesiredAccess,//                       _In_     DWORD                 dwShareMode,//                       _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//                       _In_     DWORD                 dwCreationDisposition,//                       _In_     DWORD                 dwFlagsAndAttributes,//                       _In_opt_ HANDLE                hTemplateFile//                       );//fake func replace the one aboveHANDLE WINAPI myCreateFile(                           _In_     LPCTSTR               lpFileName,                           _In_     DWORD                 dwDesiredAccess,                           _In_     DWORD                 dwShareMode,                           _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,                           _In_     DWORD                 dwCreationDisposition,                           _In_     DWORD                 dwFlagsAndAttributes,                           _In_opt_ HANDLE                hTemplateFile                           ){    WCHAR wFileName[MAX_PATH] ={0};    wcscpy(wFileName,lpFileName);    if (wcscmp(wcslwr(wFileName),L"c:\\test.txt")==0)    {        if (MessageBoxW(NULL,L"OPEN FILE?",L"NOTICE",MB_YESNO)==IDYES)        {            return   dwCreateFileWAddr(                             //为什么没有用createFileW,而使用的是dwCreateFile呢,因为iat已经被劫持了,否则就成了递归,永远到不了真正的实现了。                lpFileName,                dwDesiredAccess,                dwShareMode,                lpSecurityAttributes,                dwCreationDisposition,                dwFlagsAndAttributes,                hTemplateFile                );        }         else        {            return INVALID_HANDLE_VALUE;        }    }     else    {        return dwCreateFileWAddr(            lpFileName,            dwDesiredAccess,            dwShareMode,            lpSecurityAttributes,            dwCreationDisposition,            dwFlagsAndAttributes,            hTemplateFile            );    }}VOID HookNotePadIAT(){    //get iid_addr     HMODULE notepad_module = GetModuleHandleA(NULL);    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)notepad_module;    PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)notepad_module+pDosHeader->e_lfanew);    DWORD RVA_FirstIID = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;    PIMAGE_IMPORT_DESCRIPTOR pIID=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)notepad_module+RVA_FirstIID);    //PIMAGE_IMPORT_DESCRIPTOR pIIDtemp =pIID;    //real addr of "CreateFileW"    HMODULE handle=LoadLibraryA("kernel32.dll");    DWORD dwFuncAddr = (DWORD)GetProcAddress(handle,"CreateFileW");    //find the IID remains 'kernel32.dll'    BOOL isExist = FALSE;    while (pIID->Name)    {        char* dllname=(char*)(pIID->Name+(DWORD)notepad_module);        char szName[MAXBYTE]={0};        strcpy(szName,dllname);        if (strcmp(strlwr(szName),"kernel32.dll")==0) //wrong here KERNEL32.dll        {            isExist = TRUE;            break;        }        pIID++;    }    //check the iat addr is right ?    if (isExist==TRUE)    {        isExist= FALSE;        PIMAGE_THUNK_DATA pIAT=(PIMAGE_THUNK_DATA)(pIID->FirstThunk+(DWORD)notepad_module); //forget the baseimage...        while (pIAT->u1.Function)        {            DWORD* pAddr=(DWORD*)(&pIAT->u1.Function); //get IAT addr            if (*pAddr == dwFuncAddr)         //check contents of iat if right.            {                printf("isExist\n");                isExist=TRUE;                         dwCreateFileWAddr = (CRETEFILEW)*pAddr;    //real addr.                DWORD dwMyHookAddr = (DWORD) myCreateFile;                WriteProcessMemory(GetCurrentProcess(),(LPVOID)pAddr,&dwMyHookAddr,sizeof(DWORD),NULL); //replace the iat content                break;            }            pIAT++;        }    }}BOOL APIENTRY DllMain( HMODULE hModule,                      DWORD  ul_reason_for_call,                      LPVOID lpReserved                      ){    switch (ul_reason_for_call)    {    case DLL_PROCESS_ATTACH:        HookNotePadIAT();        break;    }    return TRUE;}

编码说明

上述代码原理:
1. 首先找到第一个IID的地址,用pIID 来保存。
2. 遍历IID,通过查找name字段 ,来确定程序中目标函数所在的DLL在导入表中,找到的IID指针用pIID来表示。
3. 用动态调用的方式得到目标函数的地址,保存为dwFuncAddr
4. 读取PIID 指向的IAT表,检查IAT表中的内容和动态获取的地址是否一致。
5. 内存中替换,写入伪造的函数地址。

注意

  • 在恶意函数中,有时候必须要实现被挂钩函数的功能。在inlineHook 中,通过unhook操作来恢复内存。而在IAT挂钩中,首先保存了原来的函数入口地址。不管使用什么方式挂钩,原来的内容一定要通过一个变量保存下来。

  • 编译与运行过程出现的问题:

    1. 在查询IID的时候, if (strcmp(strlwr(szName),"kernel32.dll")==0) //wrong here KERNEL32.dll 之前没有转小写,调试后发现kernel32.dll为KERNEL32.dll
    2. while (pIAT->u1.Function) 测试错误,调试之后发现问题是pIAT 忘了没有加基址,FirstThunk 是个RVA
    3. 不同类型的指针在使用时一定需要转化,一般而言,函数指针在赋值的时候必须转化。
    4. DLL主函数中:case不一定要全写,本例中就写了一个目标消息DLL_PROCESS_ATTACH 这也是可以的。

证明

打开notepad.exe后用dlljector.exe注入此进程

C:\Documents and Settings\Administrator\桌面>DLLInjector.exe C:\VC6\MyProjects\iatHook_dll\Debug\iatHook_dll.dll 456

有意思的是选中文件的时候也会调用CreateFileW.
选中文件的时候也有
弹窗选择否之后,返回INVALID_HANDLE_VALUE ,也即打开失败。
选择否的时候不能正确打开

0 0
原创粉丝点击