[原创]ring0下挂钩SSDT防文件删除
文章作者:asm信息来源:邪恶八进制信息安全团队
好久没写东西了,手痒。见zhouzhen同志写了一篇ring3下抗文件删除的([url]https://forum.eviloctal.com/read-htm-tid-28707-keyword-.html[/url]),所以,偶也献个丑。
贴个图图:
[attach]6507[/attach]
关于文件的操作,一般都通过ZwSetInformationFile完成,只要挂钩ZwSetInformationFile,就可以了。(但愿不要产生流氓程序)
反汇编一下ntdll,找到ZwSetInformationFile:
.text:7C92E5D9 NtSetInformationFile proc near
.text:7C92E5D9 mov eax, 0E0h
.text:7C92E5DE mov edx, 7FFE0300h
.text:7C92E5E3 call dword ptr [edx]
.text:7C92E5E5 retn 14h
.text:7C92E5E5
.text:7C92E5E5 NtSetInformationFile endp
实际上就是把ZwSetInformationFil的服务ID号0E0H传到ring0,系统就会根据0E0H找到ZwSetInformationFile的真正地址。并把结果传回给ntdll.dll的NtSetInformationFile。在此过程中,如果我们把返回的地址给改了,那么,系统就会返回到我们自己定义的函数,这样,真正的NtSetInformationFil就失效了,而要执行的,就是我们的函数。此过程称为"挂勾SSDT"。
代码中,mov eax,KeServiceDescriptorTabled 导出符号获得数组的基地址,这个数组中包含有NT开头的函数,然后调用MmGetSystemRoutineAddress来获取ZwSetInformationFile的地址,并得到其服务ID,即反汇编代码中的"0E0h",得到地址之后,修改到新的函数,这样一来,系统就执行我们的函数了。
;******************************************************
;程序编写by Asm
;日期:2007-9-5日
;出处:[url]http://www.asm32.cn/[/url]
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自 ([url]http://www.asm32.cn/[/url])
;******************************************************
.386
.model flat, stdcall
option casemap:none
;**************************************************************************************************
include w2k\ntstatus.inc
include w2k\ntddk.inc
include w2k\ntoskrnl.inc
includelib ntoskrnl.lib
include Strings.mac
;**************************************************************************************************
.data?
dwOldSetInformationFile dd ?
dwAddr dd ?
psi FILE_NAME_INFORMATION<?>
iosb IO_STATUS_BLOCK<?>
hFile HANDLE ?
.const
CCOUNTED_UNICODE_STRING "\\Device\\Asm", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING "\\??\\AsmFile", g_usSymbolicLinkName, 4
CCOUNTED_UNICODE_STRING "ZwSetInformationFile", g_ApiAddr, 4 ;wSetInformationFile
CCOUNTED_UNICODE_STRING "\\??\\C:\\1.txt", g_usDirName, 4
;**************************************************************************************************
.code
NewSetInformationFile proc
pushad
invoke ZwQueryInformationFile, hFile, addr iosb, addr psi, sizeof psi,FileNameInformation
.if eax == STATUS_SUCCESS
invoke wcsstr,addr psi.FileName,addr g_usDirName
invoke DbgPrint, $CTA0("%s...\n"),addr psi.FileName
.if eax==NULL
jmp _Goto
.elseif
mov esi,dwAddr
mov eax,dwOldSetInformationFile ;正常的ZwSetInformationFile函数地址保存到eax。
cli
mov dword ptr[esi],eax ;恢复SSDT
sti
;恢复了SSDT,就可以正常调用ZwSetInformationFile
invoke ZwSetInformationFile, hFile, addr iosb, addr psi, sizeof psi,FileNameInformation
.if eax == STATUS_SUCCESS
invoke DbgPrint, $CTA0("SetInformationFile ok...\n")
.endif
.endif
.endif
_Goto:
popad
ret
NewSetInformationFile endp
;**************************************************************************************************
_SetSSDT proc
pushad
mov eax, KeServiceDescriptorTable ;导出符号获得数组的基地址
mov esi, [eax]
mov esi, [esi]
invoke MmGetSystemRoutineAddress,addr g_ApiAddr ;取ZwSetInformationFile地址
inc eax
movzx ecx,byte ptr[eax]
sal ecx,2 ;取ZwSetInformationFile服务ID号
add esi,ecx
mov dwAddr,esi
mov edi,dword ptr[esi]
mov dwOldSetInformationFile,edi
mov edi,offset NewSetInformationFile ;获得新函数地址
cli
mov dword ptr[esi],edi ;修改,让系统执行我们的新函数
sti
popad
mov eax, STATUS_SUCCESS
ret
_SetSSDT endp
;**************************************************************************************************
DispatchCreateClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
mov eax, pIrp
assume eax:ptr _IRP
mov [eax].IoStatus.Status, STATUS_SUCCESS
and [eax].IoStatus.Information, 0
assume eax:nothing
invoke IoCompleteRequest, pIrp, IO_NO_INCREMENT
mov eax, STATUS_SUCCESS
ret
DispatchCreateClose endp
;**************************************************************************************************
;此分派过程在ControlService调用时调用
;**************************************************************************************************
DriverUnload proc pDriverObject:PDRIVER_OBJECT
pushad
mov esi,dwAddr
mov eax,dwOldSetInformationFile ;正常的ZwSetInformationFile函数地址保存到eax。
cli
mov dword ptr[esi],eax ;恢复SSDT
sti
invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName
mov eax,pDriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject
popad
ret
DriverUnload endp
;**************************************************************************************************
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT
mov status, STATUS_DEVICE_CONFIGURATION_ERROR
invoke IoCreateDevice, pDriverObject, 0, addr g_usDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, addr pDeviceObject
.if eax == STATUS_SUCCESS
invoke IoCreateSymbolicLink, addr g_usSymbolicLinkName, addr g_usDeviceName
.if eax == STATUS_SUCCESS
mov eax, pDriverObject
assume eax:ptr DRIVER_OBJECT
mov [eax].DriverUnload,offset DriverUnload ;分派过程,ring3下调用ControlService时此过程被调用,恢复SSDT
mov [eax].MajorFunction[IRP_MJ_CREATE*(sizeof PVOID)],offset DispatchCreateClose
mov [eax].MajorFunction[IRP_MJ_CLOSE*(sizeof PVOID)],offset DispatchCreateClose
assume eax:nothing
invoke _SetSSDT
mov status, STATUS_SUCCESS
.else
invoke IoDeleteDevice, pDeviceObject
.endif
.endif
mov eax, status
ret
DriverEntry endp
end DriverEntry
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
驱动加载代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap:none
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; I N C L U D E F I L E S
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
include windows.inc
include kernel32.inc
include user32.inc
include advapi32.inc
includelib kernel32.lib
includelib user32.lib
includelib advapi32.lib
include Strings.mac
.code
start proc
local hSCManager:HANDLE
local hService:HANDLE
local acDriverPath[MAX_PATH]:CHAR
invoke RtlZeroMemory,addr acDriverPath,sizeof acDriverPath
invoke OpenSCManager, NULL, NULL, SC_MANAGER_CREATE_SERVICE
.if eax != NULL
mov hSCManager, eax
push eax
invoke GetFullPathName, $CTA0("ZwSetInformationFile.sys"), sizeof acDriverPath, addr acDriverPath, esp
pop eax
invoke CreateService, hSCManager, $CTA0("testasm"), $CTA0("testasm"), \
SERVICE_START + DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, \
SERVICE_ERROR_IGNORE, addr acDriverPath, NULL, NULL, NULL, NULL, NULL
.if eax != NULL
mov hService, eax
invoke StartService, hService, 0, NULL
invoke CloseServiceHandle, hService
.else
invoke MessageBox, NULL, $CTA0("Can't register driver."), NULL, MB_ICONSTOP
.endif
invoke CloseServiceHandle, hSCManager
.else
invoke MessageBox, NULL, $CTA0("Can't connect to Service Control Manager."), \
NULL, MB_ICONSTOP
.endif
invoke ExitProcess, 0
start endp
end start
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;驱动卸载代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
include windows.inc
include kernel32.inc
include advapi32.inc
includelib kernel32.lib
includelib advapi32.lib
.data
szCapapi db "testasm",0
.data?
hSCManager dd ?
hService dd ?
ServiceStatus SERVICE_STATUS<>
.code
start:
invoke OpenSCManager,NULL,NULL, SC_MANAGER_CREATE_SERVICE ;连接服务管理器
.if eax!=0
mov hSCManager, eax ;连接成功,返回一个句柄
.endif
invoke OpenService, hSCManager,addr szCapapi,0F01FFh ;打开服务
.if eax!=0
mov hService,eax
.endif
invoke ControlService,hService,SERVICE_CONTROL_STOP,addr ServiceStatus
invoke DeleteService,hService
invoke CloseServiceHandle,hService
invoke CloseServiceHandle,hSCManager
invoke ExitProcess,NULL
end start [s:270] 调式这个驱动,偶系统挂了N次。。。
代码还有些bug,但不会让系统挂掉....... 铞..ring0确实强。刚点系统直接蓝屏. 哦,我是xp sp2的..我系统测试确实成功了的说,下面是冰刃查看的图:
[attach]947[/attach] 测试环境XP XP2 nt本机api,大多数win32的api函数都是包装了这些zwxxx api和ntxxx api实现的。
在用户模式下,这两种形式的本机api是相同的,只是ntdll.dll中相同入口点的两个不同符号。
在内核模式下,代码依靠ntoskrnl.exe来连接,不再是ntdll.dll?????????????。这是,zwxxx的函数入口点含有来自于ntdll.dll的一份拷贝。ntxxx的函数入口点则含有系统服务的实际实现。
加了问号的地方还没搞清楚 才发现驱动代码犯了一个常识错误,我已经和谐掉了ZwSetInformationFile,但是在新函数里,我又使用ZwSetInformationFile,这个等于是访问了一个不存在的地址,可能是我运气好,系统不挂掉。。修改一下:
NewSetInformationFile proc
pushad
invoke ZwQueryInformationFile, hFile, addr iosb, addr psi, sizeof psi,FileNameInformation
.if eax == STATUS_SUCCESS
invoke wcsstr,addr psi.FileName,addr g_usDirName
invoke DbgPrint, $CTA0("%s...\n"),addr psi.FileName
.if eax==NULL
jmp _Goto
.elseif
mov esi,dwAddr
mov eax,dwOldSetInformationFile ;正常的ZwSetInformationFile函数地址保存到eax。
cli
mov dword ptr[esi],eax ;恢复SSDT
sti
;恢复了SSDT,就可以正常调用ZwSetInformationFile
invoke ZwSetInformationFile, hFile, addr iosb, addr psi, sizeof psi,FileNameInformation
.if eax == STATUS_SUCCESS
invoke DbgPrint, $CTA0("SetInformationFile ok...\n")
.endif
.endif
.endif
_Goto:
popad
ret
NewSetInformationFile endp
另外,我hFile这个句柄从哪里来,汗,怪不得提示句柄无效。。。
NewSetInformationFile proc
ret
NewSetInformationFile endp
其实这样最好,直接当掉ZwSetInformationFile,那么关于文件的操作,比如删除,重命名等等都失效。
本人才刚接触驱动,希望各大大提些意见吧 [s:266] [quote]引用第5楼ntandtv于2007-09-05 22:44发表的 :
nt本机api,大多数win32的api函数都是包装了这些zwxxx api和ntxxx api实现的。
在用户模式下,这两种形式的本机api是相同的,只是ntdll.dll中相同入口点的两个不同符号。
在内核模式下,代码依靠ntoskrnl.exe来连接,不再是ntdll.dll?????????????。这是,zwxxx的函数入口点含有来自于ntdll.dll的一份拷贝。ntxxx的函数入口点则含有系统服务的实际实现。
.......[/quote]
理论性的问题这个,看下面两贴:
[url]http://bbs.pediy.com/showthread.php?t=51105[/url]
[url]http://bbs.pediy.com/showthread.php?t=40832&highlight=ssdt[/url] 问题的关键是对当前选择的文件进行处理,在FILE_NAME_INFORMATION这个结构的FileName里保存的正是当前要操作的文件,如果符合,就摸掉ZwSetInformationFile,如果不符合就恢复SSDT继续用户的操作..偶正在调式当中... [s:267] asm 进步挺大的。
看看我写的那个函数,其实就是几个数据结构转来转去的。 楼主 出现这个问题啊
测试环境:番茄花园xp sp2 全部补丁齐全! 麦咖啡杀软~~
多次测试都是这个问题
[img]http://www.sdlfit.com/yiyi/02.jpg[/img]
汗~~~图片不能上传 只能自己找个地方传了 那是你电脑里已经有了相同的服务名 呵呵,ASM和我一样,学写DriverEntry也是从李马的《城里城外看SSDT》,跟着牛人的脚步走,学起来真的很舒服,我调试DriverEntry程序都是在VM里,虽然卡点,但是起码不会那么总死机,哈哈 [s:267] 搞定,留给我自己用,代码就不公布了..[s:264][s:264]
[attach]1200[/attach] [quote]引用第15楼caiker于2007-09-11 15:16发表的 :
呵呵,ASM和我一样,学写DriverEntry也是从李马的《城里城外看SSDT》,跟着牛人的脚步走,学起来真的很舒服,我调试DriverEntry程序都是在VM里,虽然卡点,但是起码不会那么总死机,哈哈[/quote]
哈哈,要不是有我,你们还看不到李马的《城里城外看SSDT》呢,没想到当初无意的留言竟然引出这样一篇好文章。
说起来也意外,那次在学校的论坛上瞎转,无意中找到了李马(我跟他一个学校的)的个人网站,又无意中看见有人对他写的那篇远程注入的文章拍马屁,于是忍不住留了言,结果这篇文章就出来了,呵呵。 [s:267] 我是一只挣扎在ring3和ring0缝隙之间的小鱼...游啊游...... 防止删除文件的方法有很多,比如用CreateFile函数以只读,独享的形式打开,不关闭句柄一样可以实现防删除... [s:270] [quote]引用第5楼ntandtv于2007-09-05 22:44发表的 :
nt本机api,大多数win32的api函数都是包装了这些zwxxx api和ntxxx api实现的。
在用户模式下,这两种形式的本机api是相同的,只是ntdll.dll中相同入口点的两个不同符号。
在内核模式下,代码依靠ntoskrnl.exe来连接,不再是ntdll.dll?????????????。这是,zwxxx的函数入口点含有来自于ntdll.dll的一份拷贝。ntxxx的函数入口点则含有系统服务的实际实现。
.......[/quote]
也可以看看这个
[url]https://forum.eviloctal.com/read-htm-tid-7070.html[/url]
[url]https://forum.eviloctal.com/read-htm-tid-14187.html[/url] 来个FSD钩子的吧~搞定IS,HOHO
那个玩意防删除对付常规玩意可以,呵呵~ [quote]引用第16楼7个b于2007-10-08 00:19发表的 :
防止删除文件的方法有很多,比如用CreateFile函数以只读,独享的形式打开,不关闭句柄一样可以实现防删除... [s:270][/quote]
这种方法一个chkdsk卸载掉所有打开的句柄,然后就......[s:264] to sunwear :lol:
下面的失效了,能补一下吗 thank you
[url]https://forum.eviloctal.com/read-htm-tid-7070.html[/url]
[url]https://forum.eviloctal.com/read-htm-tid-14187.html[/url] 内挖大牛,少打一次洞了, 技术要紧麻烦把上面两个失效连接修正一下.谢了 LZ好厉害呀。。:sweat:
页:
[1]