Note
  • Introduction
  • PWN
    • __libc_csu_init函数的通用gadget
    • _int_malloc源码分析
    • _IO_FILE利用思路总结
    • C++ 虚表分析
    • Fast_bin笔记
    • house_of_force
    • House_of_Roman
    • Linux_ShellCode
    • Return-to-dl-resolve原理及利用
    • Unlink利用原理
    • Unsorted_Bin_Attack
    • 获取libc方法
    • 利用main_arena泄露libc基址
    • 整数溢出
    • 重写.fini_array函数指针
    • Windows_SEH利用
  • Windows_Operating_System
    • Dll隐藏
    • Dll注入之远程线程注入
    • IAT_HOOK原理实现
    • Windows下通用ShellCode原理
    • 代码注入
    • inline_hook框架
    • 32位程序调用64位函数原理
    • 调试原理
    • Windows异常处理初探
    • Windows_SEH利用
  • Windows_Kernel
    • MSR_HOOK
    • SSDT_HOOK
  • Virus_Analysis
  • Program
    • Dll的生成与使用
  • Miscellaneous
    • ctf笔记
    • 常见算法特征总结
    • ELF文件笔记
  • Linux_Operating_System
    • 系统调用
    • 分页机制
    • 调试原理
    • linux无文件执行elf
    • egg hunter
    • 缺失的动态链接库
  • Linux_Kernel
    • KERNEL_PWN状态切换原理及KPTI绕过
  • IOT
    • IOT调试环境搭建
    • mips_arm汇编学习
    • Cisco RV160W系列路由器漏洞:从1day分析到0day挖掘
  • Symbolic_Execution
    • angr初探
    • angr_进阶
  • Fuzz
    • UAF_overflow_check
    • intel-pin
  • CVE
    • Cisco RV160W系列路由器漏洞:从1day分析到0day挖掘
  • Assembly
    • Junk_Code_Analysis
    • opcode
  • Andriod_Security
Powered by GitBook
On this page
  • 0x00 原理简介
  • 0x01 代码实现
  • 0x02 完整代码
  • 0x03实验结果

Was this helpful?

  1. Windows_Operating_System

IAT_HOOK原理实现

0x00 原理简介

IAT(Import Address Table,输入地址表):当PE文件装入的时候,Windows加载器的工作之一就是定位所有被输入的函数和数据,并且让正在被装入的文件可以使用那些地址,输入函数就是被程序调用但其执行代码又不在程序中的函数,这些函数的代码位于相关的dll等文件中,当然只有被程序调用到的函数才会出现在IAT中(EAT是PE中所有导出的函数或者变量,注意区别,一般的EXE文件不会有导出表,但并不是说EXE不能导出函数或者变量)。HOOK IAT就是钩住感兴趣的函数,然后改变程序的执行流程或者对该函数进行监控。

0x01 代码实现

1,HOOK函数MessageBox,首先定义一个用于替换的MyMessageBox函数。

int WINAPI MyMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
{
    char lpNewText[]="修改后的内容";
    typedef int (WINAPI *PFNMESSAGEBOX)(HWND,LPCSTR,LPCSTR,UINT);
    int ret=((PFNMESSAGEBOX)g_dwOldAddr)(hWnd,lpNewText,lpCaption,uType);
    return ret;
}

2,得到模块基址,并找到该PE模块中IAT表的位置

dwImageBase=(DWORD)::GetModuleHandle(NULL);
pNtHeader=(PIMAGE_NT_HEADERS)(dwImageBase+((PIMAGE_DOS_HEADER)dwImageBase)->e_lfanew);
pImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase+pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

3,遍历IAt表,找到要HOOK的MessageBox函数地址,找到后先修改内存页的属性为PAGE_READWRITE,再修改当前位置为MyMessageBox函数地址,恢复内存页属性。

while(pImportDescriptor->FirstThunk!=0 && bFlag == FALSE)
{
    pFuncAddr=(PDWORD)(dwImageBase+pImportDescriptor->FirstThunk);

    while(*pFuncAddr)
    {
        if(dwOldAddr == *pFuncAddr)
        {
            VirtualProtect(pFuncAddr,sizeof(DWORD),PAGE_READWRITE,&dwOldProtect);
            *pFuncAddr=dwNewAddr;
            VirtualProtect(pFuncAddr,sizeof(DWORD),dwOldProtect,0);
            bFlag=TRUE; 
            break;
        }
        pFuncAddr=(PDWORD)((DWORD)pFuncAddr+sizeof(DWORD));
    }
    pImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDescriptor+sizeof(IMAGE_IMPORT_DESCRIPTOR));
}

0x02 完整代码

这是个dll文件

#include "stdafx.h"
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<Tlhelp32.h.>

DWORD g_dwIATHookFlag=0; // #HOOK状态 (1 HOOK  0 未HOOK)
DWORD g_dwOldAddr;
DWORD g_dwNewAddr;

BOOL SetIATHook(DWORD dwOldAddr,DWORD dwNewAddr)
{
    BOOL bFlag =FALSE;
    DWORD dwImageBase=0;
    PDWORD pFuncAddr=NULL;
    PIMAGE_NT_HEADERS pNtHeader =NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor=NULL;
    DWORD dwOldProtect=0;

    // #得到模块基址
    dwImageBase=(DWORD)::GetModuleHandle(NULL);
    pNtHeader=(PIMAGE_NT_HEADERS)(dwImageBase+((PIMAGE_DOS_HEADER)dwImageBase)->e_lfanew);
    pImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase+pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    // #遍历IAt表 找到这个函数地址
    while(pImportDescriptor->FirstThunk!=0 && bFlag == FALSE)
    {
        pFuncAddr=(PDWORD)(dwImageBase+pImportDescriptor->FirstThunk);

        while(*pFuncAddr)
        {
            // #找到要HOOK的函数,先修改内存的属性
            if(dwOldAddr == *pFuncAddr)
            {
                VirtualProtect(pFuncAddr,sizeof(DWORD),PAGE_READWRITE,&dwOldProtect);
                *pFuncAddr=dwNewAddr;
                // #恢复内存页属性
                VirtualProtect(pFuncAddr,sizeof(DWORD),dwOldProtect,0);
                bFlag=TRUE; 
                break;
            }
            pFuncAddr=(PDWORD)((DWORD)pFuncAddr+sizeof(DWORD));
        }
        pImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDescriptor+sizeof(IMAGE_IMPORT_DESCRIPTOR));
    }
    g_dwOldAddr=dwOldAddr;
    g_dwNewAddr=dwNewAddr;
    g_dwIATHookFlag=1;
    return bFlag;
}


BOOL UnIATHook()
{
    BOOL bFlag =FALSE;
    DWORD dwImageBase=0;
    PDWORD pFuncAddr=NULL;
    PIMAGE_NT_HEADERS pNtHeader=NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor =NULL;
    DWORD dwOldProtect =0;
    // #判断是否HOOK
    if(!g_dwIATHookFlag)
    {
        OutputDebugString("UnIATHook失败:尚未进行IAT HOOK!");
        return bFlag;
    }
    // #得到模块基址
    dwImageBase=(DWORD)::GetModuleHandle(NULL);
    pNtHeader=(PIMAGE_NT_HEADERS)(dwImageBase+((PIMAGE_DOS_HEADER)dwImageBase)->e_lfanew);
    pImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase+pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    // #遍历IAt表 找到这个函数地址
    while(pImportDescriptor->FirstThunk!=0 && bFlag == FALSE)
    {
        pFuncAddr=(PDWORD)(dwImageBase+pImportDescriptor->FirstThunk);

        while(*pFuncAddr)
        {
            // #找到要HOOK的函数,先修改内存的属性
            if(g_dwNewAddr == *pFuncAddr)
            {
                // #找到被HOOK的函数
                VirtualProtect(pFuncAddr,sizeof(DWORD),PAGE_READWRITE,&dwOldProtect);
                *pFuncAddr=g_dwNewAddr;
                // #恢复内存页属性
                VirtualProtect(pFuncAddr,sizeof(DWORD),dwOldProtect,0);
                bFlag=TRUE;
                break;
            }
            pFuncAddr++;
        }
        pImportDescriptor =(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDescriptor+sizeof(IMAGE_IMPORT_DESCRIPTOR));
    }
    // #修改状态
    g_dwOldAddr=0;
    g_dwNewAddr=0;
    g_dwIATHookFlag=0;
    return bFlag;
}

int WINAPI MyMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
{
    char lpNewText[]="修改后的内容";
    // #定义MessageBox函数指针
    typedef int (WINAPI *PFNMESSAGEBOX)(HWND,LPCSTR,LPCSTR,UINT);
    // #执行真正的函数
    int ret=((PFNMESSAGEBOX)g_dwOldAddr)(hWnd,lpNewText,lpCaption,uType);
    return ret;
}

DWORD WINAPI ThreadProc(LPVOID lParam)
{
    // #保存原函数的地址
    DWORD pOldFuncAddr=(DWORD)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA");
    // #安装或者卸载HOOK
    if(!g_dwIATHookFlag)
    {
        SetIATHook(pOldFuncAddr,(DWORD)MyMessageBox);
    }
    else
    {
        UnIATHook();
    }
    return 0;
}
BOOL APIENTRY DllMain( HANDLE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved
                      )
{


    switch (ul_reason_for_call)

    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,NULL);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

0x03实验结果

  • 实验环境: win10

单击程序Help的Register,随便输入注册账号和密码

PreviousDll注入之远程线程注入NextWindows下通用ShellCode原理

Last updated 5 years ago

Was this helpful?

对象程序:

crackme.exe