Win64 驱动内核编程-29.强制解锁文件

强制解锁文件

    强制解锁因其他进程占用而无法删除的文件。

1.调用 ZwQuerySystemInformation 的 16 功能号来枚举系统里的句柄

2.打开拥有此句柄的进程并把此句柄复制到自己的进程

3.用 ZwQueryObject 查询句柄的类型和名称

4.如果 发现此句柄的类型是文件句柄, 名称和被锁定的文件一致,就关闭此句柄

5.重复 2、3、4 步,直到遍历完系统里所有的句柄

第4步中因为是要解锁其他进程占用的文件所以有如下细节:

1.用 KeStackAttachProcess“依附”到目标进程

2.用 ObSetHandleAttributes 设置句柄为“可以关闭”

3.用 ZwClose 关闭句柄

4.用 KeUnstackDetachProcess 脱离“依附”目标进程

以下代码适用于Win7  X64,如果想支持全系统,请对应调教。

#include <ntddk.h>
 
#define kprintf	DbgPrint
#define kmalloc(_s)	ExAllocatePoolWithTag(NonPagedPool, _s, 'SYSQ')
#define kfree(_p)	ExFreePool(_p)
 
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO{
USHORT	UniqueProcessId;
USHORT	CreatorBackTraceIndex;
UCHAR	ObjectTypeIndex;
UCHAR	HandleAttributes;
USHORT	HandleValue;
PVOID	Object;
ULONG	GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
 
typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG64 NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
 
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryObject
(
HANDLE	Handle,
ULONG	ObjectInformationClass,
PVOID	ObjectInformation,
ULONG	ObjectInformationLength,
PULONG	ReturnLength OPTIONAL
);
 
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation
(   
ULONG	SystemInformationClass,
PVOID	SystemInformation,
ULONG	SystemInformationLength,
PULONG	ReturnLength
);
 
NTSYSAPI
NTSTATUS
NTAPI
ZwDuplicateObject
(
HANDLE	SourceProcessHandle,
HANDLE	SourceHandle,
HANDLE	TargetProcessHandle OPTIONAL,
PHANDLE 	TargetHandle OPTIONAL,
ACCESS_MASK	DesiredAccess,
ULONG	HandleAttributes,
ULONG	Options
);
 
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenProcess
(    
PHANDLE	ProcessHandle,
ACCESS_MASK	AccessMask,
POBJECT_ATTRIBUTES	ObjectAttributes,
PCLIENT_ID	ClientId
);
 
typedef enum _OBJECT_INFORMATION_CLASS {
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectAllInformation,
    ObjectDataInformation
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
 
typedef struct _OBJECT_BASIC_INFORMATION {
  ULONG                   Attributes;
  ACCESS_MASK             DesiredAccess;
  ULONG                   HandleCount;
  ULONG                   ReferenceCount;
  ULONG                   PagedPoolUsage;
  ULONG                   NonPagedPoolUsage;
  ULONG                   Reserved[3];
  ULONG                   NameInformationLength;
  ULONG                   TypeInformationLength;
  ULONG                   SecurityDescriptorLength;
  LARGE_INTEGER           CreationTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
 
/*typedef struct _OBJECT_NAME_INFORMATION {
  UNICODE_STRING          Name;
  WCHAR                   NameBuffer[0];
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;*/
 
typedef struct _OBJECT_TYPE_INFORMATION {
  UNICODE_STRING          TypeName;
  ULONG                   TotalNumberOfHandles;
  ULONG                   TotalNumberOfObjects;
  WCHAR                   Unused1[8];
  ULONG                   HighWaterNumberOfHandles;
  ULONG                   HighWaterNumberOfObjects;
  WCHAR                   Unused2[8];
  ACCESS_MASK             InvalidAttributes;
  GENERIC_MAPPING         GenericMapping;
  ACCESS_MASK             ValidAttributes;
  BOOLEAN                 SecurityRequired;
  BOOLEAN                 MaintainHandleCount;
  USHORT                  MaintainTypeList;
  POOL_TYPE               PoolType;
  ULONG                   DefaultPagedPoolCharge;
  ULONG                   DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
 
typedef struct _KAPC_STATE 
{
LIST_ENTRY ApcListHead[2];
PVOID Process;
BOOLEAN KernelApcInProgress;
BOOLEAN KernelApcPending;
BOOLEAN UserApcPending;
}KAPC_STATE, *PKAPC_STATE;
 
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION{
BOOLEAN Inherit;
BOOLEAN ProtectFromClose;
}OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
 
NTKERNELAPI 
NTSTATUS 
ObSetHandleAttributes (HANDLE Handle, POBJECT_HANDLE_FLAG_INFORMATION HandleFlags, KPROCESSOR_MODE PreviousMode);
 
NTKERNELAPI 
VOID 
KeStackAttachProcess(PEPROCESS PROCESS, PKAPC_STATE ApcState);
 
NTKERNELAPI 
VOID 
KeUnstackDetachProcess(PKAPC_STATE ApcState);
 
NTKERNELAPI 
NTSTATUS 
PsLookupProcessByProcessId (IN HANDLE ProcessId,OUT PEPROCESS *Process);
 
PEPROCESS LookupProcess(HANDLE Pid)
{
PEPROCESS eprocess=NULL;
if( NT_SUCCESS(PsLookupProcessByProcessId(Pid, &eprocess)) )
return eprocess;
else
return NULL;
}
 
VOID UnicodeStringToCharArray(PUNICODE_STRING dst, char *src)
{
ANSI_STRING string;
if( dst->Length>260 ) return;
RtlUnicodeStringToAnsiString(&string,dst, TRUE); 
strcpy(src,string.Buffer);
RtlFreeAnsiString(&string); 
}
 
VOID ForceCloseHandle(PEPROCESS Process, ULONG64 HandleValue)
{
HANDLE h;
KAPC_STATE ks;
OBJECT_HANDLE_FLAG_INFORMATION ohfi;
if( Process==NULL )
return;
if( !MmIsAddressValid(Process) )
return;
KeStackAttachProcess(Process, &ks);
h=(HANDLE)HandleValue;
ohfi.Inherit=0;
ohfi.ProtectFromClose=0;
ObSetHandleAttributes(h, &ohfi, KernelMode);
ZwClose(h);
KeUnstackDetachProcess(&ks);
}
 
VOID CloseFileHandle(char *szFileName)
{
PVOID Buffer;
ULONG BufferSize = 0x20000, rtl=0;
NTSTATUS Status, qost=0;
NTSTATUS ns = STATUS_SUCCESS;
ULONG64 i=0;
ULONG64 qwHandleCount;
SYSTEM_HANDLE_TABLE_ENTRY_INFO *p;
    OBJECT_BASIC_INFORMATION BasicInfo;
    POBJECT_NAME_INFORMATION pNameInfo;
    ULONG ulProcessID;
    HANDLE hProcess;
    HANDLE hHandle;
    HANDLE hDupObj;
CLIENT_ID cid;
OBJECT_ATTRIBUTES oa;
CHAR szFile[260]={0};
Buffer=kmalloc(BufferSize);
memset(Buffer,0,BufferSize);
Status = ZwQuerySystemInformation(16, Buffer, BufferSize, 0);	//SystemHandleInformation
while(Status == 0xC0000004)	//STATUS_INFO_LENGTH_MISMATCH
{
kfree(Buffer);
BufferSize = BufferSize * 2;
Buffer=kmalloc(BufferSize);
memset(Buffer,0,BufferSize);
Status = ZwQuerySystemInformation(16, Buffer, BufferSize, 0);
}
if (!NT_SUCCESS(Status)) return;
qwHandleCount=((SYSTEM_HANDLE_INFORMATION *)Buffer)->NumberOfHandles;
p=(SYSTEM_HANDLE_TABLE_ENTRY_INFO *)((SYSTEM_HANDLE_INFORMATION *)Buffer)->Handles;
 
//ENUM HANDLE PROC
for(i=0;i<qwHandleCount;i++)
{
ulProcessID = (ULONG)p[i].UniqueProcessId;
cid.UniqueProcess = (HANDLE)ulProcessID;
cid.UniqueThread = (HANDLE)0;
hHandle = (HANDLE)p[i].HandleValue;
InitializeObjectAttributes( &oa ,NULL ,0 ,NULL ,NULL );
ns = ZwOpenProcess( &hProcess ,PROCESS_DUP_HANDLE ,&oa ,&cid );
if ( !NT_SUCCESS( ns ) )
{
KdPrint(( "ZwOpenProcess : Fail " ));
continue;
}
ns = ZwDuplicateObject( hProcess ,hHandle ,NtCurrentProcess() ,&hDupObj , PROCESS_ALL_ACCESS ,0 ,DUPLICATE_SAME_ACCESS );
if ( !NT_SUCCESS( ns ) )
{
KdPrint(( "ZwDuplicateObject : Fail " ));
continue;
}
//get basic information
ZwQueryObject( hDupObj ,ObjectBasicInformation ,&BasicInfo , sizeof( OBJECT_BASIC_INFORMATION ) ,NULL );
//get name information
pNameInfo = ExAllocatePoolWithTag( PagedPool ,1024 ,'ONON');
RtlZeroMemory( pNameInfo ,1024 );
qost=ZwQueryObject( hDupObj, ObjectNameInformation, pNameInfo, 1024, &rtl );
//get information and close handle
UnicodeStringToCharArray(&(pNameInfo->Name),szFile);
ExFreePool( pNameInfo );
ZwClose(hDupObj);
ZwClose(hProcess);
//if(!_stricmp(szFile,szFileName))
if(strstr(_strlwr(szFile),szFileName))
{
PEPROCESS ep=LookupProcess((HANDLE)(p[i].UniqueProcessId));
ForceCloseHandle(ep,p[i].HandleValue);
ObDereferenceObject(ep);
}
}
}
 


执行结果:

之前:

启动驱动之后可以成功删除因为其他进程占用而导致的文件无法删除。

宋孖健,13

原文地址:https://www.cnblogs.com/csnd/p/12061986.html