众所周知,系统中无论是EXE、DLL还是驱动SYS,都是PE结构的(废话了)。系统需要执行这些代码,首先要对其映射并加载。
前辈写过……
http://bbs.pediy.com/showthread.php?t=112338 驱动的加载流程
(流程:大概是这样 IoCreateFile(打开驱动文件,将它的第二个参数设置为FILE_EXECUTE | SYNCHRONIZE) - > NtCreateSection(为驱动在内核内存空间创建一个节) ->NtMapViewOfSection(映射驱动到内核内存空间) -> 寻找驱动的DriverEntry,并调用 -> ZwClose(关闭文件句柄) ->然后通知 NtLoadDriver(或者NtSetSystemInformation)驱动加载完成->NtLoadDriver(或者 NtSetSystemInformation)返回用户层,并通知用户驱动加载完成)
(其实偶早就知道咯啦,只是没仔细咯去研究而已,呵呵 因为XueTr也是那么做的)
但是XueTr inline了NtCreateSection中的Mm调用,简单的说就是Hook Nt的函数。我觉的这种做法还不够彻底,因为系统加载器会调用Nt来加载镜像,但是如果是RootKit 理论上没人会用Nt的(想想看啊,Nt那个函数又SSDT、又IAT、还有个inline。就单单第一个SSDT就被咔嚓了)
对于拦截,越底层越好 但是,越底层就会对代码的效率好过滤操作的复杂程度越高
为什么不用SSDT,因为SSDT实在是被用烂了…… 谁都去HOOK SSDT,谁都会恢复SSDT。无论是杀软,还是病毒这个东西都会被轻而易举的被破坏、突破。IAT HOOK我想了想,在NtCreateSection内部调用Mm,这个只是一个内部的call,所以IAT勾不住。再则IAT要对PE结构进行分析,并获取IAT表的地址,所以也注定了一定的代码复杂程度,有违于我的程序最少代码的初衷(其实偶不会IAT HOOK,说错求指正)
本文其实纯属扯淡来的,呵呵 话不在多有代码则灵,接下来就看代码吧
这个代码是我正在开发的一款小HIPS的初期测试代码,设计构想是用最少的代码hook最少的函数,完成最多的功能…… 当然程序也会写的非常的小(偶就喜欢小程序,所以我到现在一直都用VBMini 一个装完只有15M的VB开发环境。。。又要遭BS了 )
.386
.model flat, stdcall
option casemap :none
;/c /coff /nologo inlinehook MmCreateSection -by JuncoJet
;/WDM /SUBSYSTEM:NATIVE /nologo /base:1000 /relese /align:16
include ntddk.inc
include ntoskrnl.inc
include Strings.mac
includelib ntoskrnl.lib
.DATA?
pMmCreateSection dd ?
.CODE
START proc DriverObject,RegistryPath
pushad
mov eax,DriverObject
mov [eax+34h],Unload ;安装卸载例程 逆向得来其实我也不知道啥结构
invoke DbgPrint,$CTA0("EzHiPS LOAD") ;其实是EzH!PS,只是Print不支持才换成了i
mov ebx,DWORD ptr[MmCreateSection+2] ;MASM中的导入的函数 不是直接指向导入表的值,而是jmp
mov edx,[ebx] ;+2字节后 就是一个jmp [addr]的 addr值
mov pMmCreateSection,edx ;把地址装载到pMmCreateSection指针中
call WriteOn ;这个你懂的
mov ecx,6 ;改写MmCreateSection头部的长度 6字节
xor eax,eax
mov edx,pMmCreateSection ;其实这句可以不要的
@@:
mov bl,BYTE ptr[hookcode+eax] ;把hookcode处第eax个字节读出
mov BYTE ptr[edx+eax],bl ;写入到MmCreateSection的地址
inc eax
loop @b ;相当于memcpy,很爽吧
call WriteOff
xor eax,eax
popad
ret
START endp
hookcode: ;6个字节
push Hook
ret
Hook proc
pushad
xor edx,edx
cmp [esp+7*4+20h],edx ;pushad后esp增加了 20h,所以要加上
je @f
invoke DbgPrint,$CTA0("来自文件") ;这个你懂的 不解释
@@:
mov eax,[esp+5*4+20h] ;由于入口没有push ebp所以不需要多加4
and eax,10h or 20h or 40h or 80h ;PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY
test eax,eax ;这个判断算法也是逆向得来 一开始狠茫然的(其实可以用宏命令的,但是我喜欢纯代码)
jnz @1 ;true则调到@1
mov eax,[esp+6*4+20h] ;6当然就代表着第六个参数啦
cmp eax,1000000h ;SEC_IMAGE
jnz @2
@1:
invoke DbgPrint,$CTA0("可执行镜像")
@2:
invoke DbgPrint,$CTA0("SectionPageProtection %x"),DWORD ptr[esp+5*4+20h]
invoke DbgPrint,$CTA0("AllocationAttributes %x"),DWORD ptr[esp+6*4+20h]
popad ;恢复所有的寄存器 否则会蓝屏咯 只要对ntoskrnl.exe进行处理,即使是ARK软件也找不出HOOK的地址
OldCode::
mov edi,edi
push ebp
mov ebp,esp
sub esp,80h
mov ecx,pMmCreateSection
add ecx,11
push ecx ;这个其实和Hook时的代码一样 相当于jmp
ret
Hook endp
Unload proc
pushad
invoke DbgPrint,$CTA0("EzHiPS UNLOAD")
call WriteOn
mov edx,pMmCreateSection
mov ecx,6
xor eax,eax
@@:
mov bl,BYTE ptr[OldCode+eax] ;恢复Hook
mov BYTE ptr[edx+eax],bl
inc eax
loop @b
call WriteOff
popad
ret 4
Unload endp
WriteOn proc
mov eax, cr0 ;你懂的…… 不解释
and eax, not 10000h
mov cr0, eax
ret
WriteOn endp
WriteOff proc
mov eax, cr0
or eax, 10000h
mov cr0, eax
ret
WriteOff endp
end START
原谅我语法没有高亮…… 其实可以处理到有高亮的,可惜百度的空间对文章长度有限制,HTML的表达式太多就发不上去了。其实保存到有语法高亮的编辑器中就行了,没高亮看任何一种语言确实都狠郁闷的。
附件下载地址:
65F2E5F1C456CF5726B4AB4486BB9C33
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!