zoukankan      html  css  js  c++  java
  • IAT Hook

    @author: dlive

    0X01 IAT Hook的优缺点

    优点:工作原理与实现都比较简单

    缺点:如果想钩取的API不在目标进程的IAT中,那么就无法使用该技术进行钩取操作。即如果要钩取的API是由程序动态加载DLL文件而的得以使用的,那么我们将无法使用这项技术钩取它。

    0x02 IAT Hook的工作原理

    程序开始运行时,PE装载器会将user32.SetWindowTextW()的API地址(77D0960E)记录到该地址(01001110 [calc.exe的IAT区域])。

    IAT Hook的流程: 首先向calc.exe注入hookiat.dll,然后修改calc.exe内存IAT区域SetWindowTextW对应的地址为hookiat.dll中攻击者自定义的函数地址,这样当calc.exe调用SetWindowTextW时会跳转至hookiat.dll中的Hook函数,Hook函数执行到最后时调用SetWindowTextW API即可在完成该API正常功能的情况下监控API的参数和返回结果。(当然攻击者可以选择不执行SetWindowTextW的功能)

    0x03 IAT Hook代码分析

    DllMain

    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	switch( fdwReason )
    	{
    		case DLL_PROCESS_ATTACH : 
                // 获取original API的地址
               	g_pOrgFunc = GetProcAddress(GetModuleHandle(L"user32.dll"), 
                                            "SetWindowTextW");
    
                // # hook
            	// MySetWindowTextW并未定义成导出函数
    			hook_iat("user32.dll", g_pOrgFunc, (PROC)MySetWindowTextW);
    			break;
    
    		case DLL_PROCESS_DETACH :
                // # unhook
                hook_iat("user32.dll", (PROC)MySetWindowTextW, g_pOrgFunc);
    			break;
    	}
    
    	return TRUE;
    }
    

    代码比较简单,在DLL加载的时候获取SetWindowTextW的地址然后存放在全局变量中,因为被注入进程已经加载了user32.dll,所以直接GetModuleHandle获取其句柄即可(但最好先判断dll是否加载,若没有加载使用LoadLibrary加载DLL)

    MySetWindowTextW

    BOOL WINAPI MySetWindowTextW(HWND hWnd, LPWSTR lpString)
    {
        wchar_t* pNum = L"零一二三四五六七八九";
        wchar_t temp[2] = {0,};
        int i = 0, nLen = 0, nIndex = 0;
    
        nLen = wcslen(lpString);
        for(i = 0; i < nLen; i++)
        {
            // 阿拉伯数字转换为中文
            if( L'0' <= lpString[i] && lpString[i] <= L'9' )
            {
                temp[0] = lpString[i];
                nIndex = _wtoi(temp);
                lpString[i] = pNum[nIndex];
            }
        }
    
        // 调用user32!SetWindowTextW(),参数为修改后的字符串缓冲区
        return ((PFSETWINDOWTEXTW)g_pOrgFunc)(hWnd, lpString);
    }
    

    hook_iat

    // hook_iat
    // 修改IAT中的数据
    // 将IAT中 pfnOrg 修改为 pfnNew
    BOOL hook_iat(LPCSTR szDllName, PROC pfnOrg, PROC pfnNew)
    {
    	HMODULE hMod;
    	LPCSTR szLibName;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc; 
    	PIMAGE_THUNK_DATA pThunk;
    	DWORD dwOldProtect, dwRVA;
    	PBYTE pAddr;
    
        // hMod, pAddr = ImageBase of calc.exe
        //             = VA to MZ signature (IMAGE_DOS_HEADER)
    	hMod = GetModuleHandle(NULL);
    	pAddr = (PBYTE)hMod;
    
        // pAddr = VA to PE signature (IMAGE_NT_HEADERS)
    	pAddr += *((DWORD*)&pAddr[0x3C]);
    
        // dwRVA = RVA to IMAGE_IMPORT_DESCRIPTOR Table
    	dwRVA = *((DWORD*)&pAddr[0x80]);
    
        // pImportDesc = VA to IMAGE_IMPORT_DESCRIPTOR Table
    	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hMod+dwRVA);
    	
      	// IMAGE_IMPORT_DESCRIPTOR[] 以空的IMAGE_IMPORT_DESCRIPTOR为结尾
    	for( ; pImportDesc->Name; pImportDesc++ )
    	{
            // szLibName = VA to IMAGE_IMPORT_DESCRIPTOR.Name
    		szLibName = (LPCSTR)((DWORD)hMod + pImportDesc->Name);
    		if( !_stricmp(szLibName, szDllName) )
    		{
                // pThunk = IMAGE_IMPORT_DESCRIPTOR.FirstThunk
                //        = VA to IAT(Import Address Table)
    			pThunk = (PIMAGE_THUNK_DATA)((DWORD)hMod + 
                                             pImportDesc->FirstThunk);
    
                // pThunk->u1.Function = VA to API
              	// IAT Thunk 数组以空IAT Thunk为结尾
    			for( ; pThunk->u1.Function; pThunk++ )
    			{
    				if( pThunk->u1.Function == (DWORD)pfnOrg )
    				{
                        // 修改内存属性为 E R W
    					VirtualProtect((LPVOID)&pThunk->u1.Function, 
                                       4, 
                                       PAGE_EXECUTE_READWRITE, 
                                       &dwOldProtect);
    
                        // 修改IAT值为新的函数地址
                        pThunk->u1.Function = (DWORD)pfnNew;
    					
                        // 恢复内存属性为只读
                        VirtualProtect((LPVOID)&pThunk->u1.Function, 
                                       4, 
                                       dwOldProtect, 
                                       &dwOldProtect);						
    
    					return TRUE;
    				}
    			}
    		}
    	}
    
    	return FALSE;
    }
    

    IAT Hook的步骤如下:

    calc.exe的ImageBase的地址 -> Image_Nt_Headers地址 -> Image_Import_Descriptor结构体组成的数组的起始地址(其中存储着DLL名称,IAT数组的起始地址)-> 通过DLL名称找到user32.dll对应的Image_Import_Descriptor -> 找到对应的IAT数组起始地址 -> 遍历IAT找到SetWindowTextW对应的条目,修改其值为MySetWindowTextW

  • 相关阅读:
    luogu P3704 [SDOI2017]数字表格
    「雅礼集训 2018 Day4」Magic(分治NTT)
    「清华集训 2017」小 Y 和恐怖的奴隶主
    [WC2019]数树(树形dp+多项式exp)
    「FJWC2020Day5-zzq」lg (容斥)
    BoundedOptimization TopCoder
    MapGuessing TopCoder
    线性递推(Berlekamp-Massey 算法)
    杜教筛小记
    「余姚中学 2019 联测 Day 6」解码
  • 原文地址:https://www.cnblogs.com/dliv3/p/6398960.html
Copyright © 2011-2022 走看看