兵刃想必大家都知道吧。一个不错的ROOTKIT和病毒检测工具。它的自身保护比较简单,就是INLINE HOOK了两个函数。
1.NtOpenProcess
2.NtTerminateProcess
我这天没事情干,就看了看兵刃,发现它的SSDT HOOK检测不错。于是就想自己来实现。实现它要几个方便的技术
1. 如何获取原始地址表
2. 怎么知道谁HOOD的
3. 如何将服务号于具体函数对应
反正只是一个练习,没技术含量。高手就别BS了。
其中大部分是R3的,只有获取内存中SSDT表的部分是R0,也只是一小部分
代码写的很垃圾,寄存器乱用了。也没注释
第一点:如何获取原始地址表
先用ZwQuerySystemInformation查看内核文件
然后静态分析内核文件,得到KeServiceDescriptorTable,然后通过重定位表来确定KiServiceTable,然后就可以得到原始表了(其中涉及到PE文件方面的内容)
找KiServiceTable网上已经开源了,但是那是C的,由于我的C和我的英语一样,单词认识,句子就…………,所以就用汇编写了个,给和我一样对C不熟悉的用。
FindKiServiceTable proc uses ebx esi edi _hKernel,_dwRVAKsdt
mov esi,_hKernel
assume esi:ptr IMAGE_DOS_HEADER
mov edi,[esi].e_lfanew
add edi,_hKernel
assume edi:ptr IMAGE_NT_HEADERS
.if [edi].OptionalHeader.DataDirectory[8*5].VirtualAddress
mov esi,[edi].OptionalHeader.DataDirectory[8*5].VirtualAddress
add esi,_hKernel
assume esi:ptr IMAGE_BASE_RELOCATION
.while [esi].VirtualAddress
cld
lodsd ;eax=[esi].VirtualAddress
mov ebx,eax
lodsd ;eax=[esi].sizeofblock
sub eax,sizeof IMAGE_BASE_RELOCATION
shr eax,1
mov ecx,eax ;eax=重定位数量
xor edi,edi
.repeat
push ecx
push ebx
lodsw ;取重定位项
mov cx,ax
and cx,0f000h ;取高四位,为3时候表示32位需要重定位
.if cx==03000h
and ax,0fffh ;取低12位
movzx eax,ax
add eax,ebx
add eax,_hKernel
mov ebx,eax ;ebx=eax,是现在重定位位置
mov eax,[eax] ;eax,要重定位的数据
mov edi,_hKernel
assume edi:ptr IMAGE_DOS_HEADER
add edi,[edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
sub eax,[edi].OptionalHeader.ImageBase
.if eax==_dwRVAKsdt
mov ax,[ebx-2]
.if ax==05c7h
mov ebx,[ebx+4]
sub ebx,[edi].OptionalHeader.ImageBase ; EBX=KiServiceTable的RVA
mov eax,ebx
ret
.endif
.endif
.else
mov eax,-1
.endif
pop ebx
pop ecx
.untilcxz
.endw
.endif
mov eax,FALSE
ret
FindKiServiceTable endp
下面讲讲第二点,
如何知道被HOOK,其实很简单,比较原始表和内存中的表就可以了。所以写了个根据服务号得到函数地址。
这个是驱动部分
GetSSDTByIndex proc index:dword
mov eax,KeServiceDescriptorTable
mov eax,[eax]
push eax
mov eax,4
mul index
pop ecx
add eax,ecx
mov eax,[eax]
ret
GetSSDTByIndex endp
可以发送IOCTL_GETSSDT控制号就可以得到实际函数地址,然后和得到原始地址比较就可以了
在发现被HOOK的情况下,怎么样得到被谁HOOK呢?这要借助ZwQuerySystemInforamtion这个函数的SystemModuleInformation来枚举系统加载的模块,然后根据基地址和大小来判断
CheckByAddress proc uses ebx esi edi Address:dword,lpszBuffer:dword
LOCAL @cb,@p,@dwNumOfModule
invoke NtQuerySystemInformation,SystemModuleInformation,addr @p,0,addr @cb
.if !@cb
invoke MessageBox,0,$CTA0("无法枚举"),0,MB_ICONERROR
mov eax,FALSE
ret
.endif
invoke GlobalAlloc,GPTR,@cb
.if !eax
invoke MessageBox,NULL,$CTA0("分配内存出错"),0,MB_ICONERROR
mov eax,FALSE
ret
.endif
mov @p,eax
invoke NtQuerySystemInformation,SystemModuleInformation,@p,@cb,addr @cb
.if eax!=STATUS_SUCCESS
invoke MessageBox,0,$CTA0("无法枚举"),0,MB_ICONERROR
invoke GlobalFree,@p
mov eax,FALSE
ret
.endif
mov esi,@p
mov ecx,[esi]
add esi,4
assume esi:ptr SYSTEM_MODULE_INFORMATION
mov eax,Address
.repeat
push ecx
mov ebx,[esi].Base
add ebx,[esi]._Size
.if eax>=[esi].Base && eax<ebx
lea edi,[esi].ImageName
invoke lstrlen,edi
invoke RtlMoveMemory,lpszBuffer,edi,eax
mov eax,TRUE
pop ecx
ret
.endif
pop ecx
add esi,sizeof SYSTEM_MODULE_INFORMATION
.untilcxz
invoke GlobalFree,@p
mov eax,FALSE
ret
CheckByAddress endp
就可以检测是谁HOOK的了。
下面将将第三个功能:
我用查看ntdll.dll这个DLL的导出表来找ZW开头的函数,在反汇编就可以得到函数名于服务号对应了。
直接贴出代码,PE导出表方面的内容就不说了
LookByIndex proc uses esi edi index:dword,_lpsz
LOCAL hModule,dwNum,lpsz
invoke LoadLibraryEx,$CTA0("ntdll.dll"),0,DONT_RESOLVE_DLL_REFERENCES
mov hModule,eax
mov esi,eax
assume esi:ptr IMAGE_DOS_HEADER
add esi,[esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
MOV edi,[esi].OptionalHeader.DataDirectory.VirtualAddress
add edi,hModule
assume edi:ptr IMAGE_EXPORT_DIRECTORY
mov ecx,[edi].NumberOfNames
mov dwNum,0
mov esi,[edi].AddressOfNames
add esi,hModule
.repeat
push ecx
mov eax,4
mul dwNum
add eax,esi
mov eax,[eax]
add eax,hModule
push eax
pop lpsz
mov ax,[eax]
.if ax=='wZ'
mov eax,[edi].AddressOfFunctions
add eax,hModule
push eax
mov eax,4
mul dwNum
pop ecx
add eax,ecx
mov eax,[eax]
add eax,hModule
mov eax,[eax+1]
.if eax==index
POP ecx
invoke lstrlen,lpsz
invoke RtlMoveMemory,_lpsz,lpsz,eax
mov eax,TRUE
ret
.endif
.endif
pop ecx
add dwNum,1
.untilcxz
mov eax,FALSE
ret
LookByIndex endp
代码写的都不怎么简洁,也没注释,寄存器都乱用了。高手就别笑了。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)