ring0下挂钩SSDT防文件删除
文章作者:asm
信息来源:邪恶八进制信息安全团队
好久没写东西了,手痒。见zhouzhen同志写了一篇ring3下抗文件删除的(https://forum.eviloctal.com/read-htm-tid-28707-keyword-.html),所以,偶也献个丑。
贴个图图:
关于文件的操作,一般都通过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日
;出处:http://www.asm32.cn/
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自 (http://www.asm32.cn/)
;******************************************************
.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
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
invoke ZwSetInformationFile, hFile, addr iosb, addr psi, sizeof psi,FileNameInformation
.if eax == STATUS_SUCCESS
invoke DbgPrint, $CTA0("SetInformationFile ok…\n")
.endif
.endif
.endif
_Goto:
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