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
Win64 驱动内核编程-29.强制解锁文件的更多相关文章
- Win64 驱动内核编程-3.内核里使用内存
内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...
- Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)
驱动安装,通讯,Hello World 开发驱动的简单流程是这样,开发驱动安装程序,开发驱动程序,然后安装程序(或者其他程序)通过通讯给驱动传命令,驱动接到之后进行解析并且执行,然后把执行结果返回. ...
- Win64 驱动内核编程-8.内核里的其他常用
内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...
- Win64 驱动内核编程-7.内核里操作进程
在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...
- Win64 驱动内核编程-18.SSDT
SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...
- Win64 驱动内核编程-5.内核里操作文件
内核里操作文件 RING0 操作文件和 RING3 操作文件在流程上没什么大的区别,也是"获得文件句柄->读/写/删/改->关闭文件句柄"的模式.当然了,只能用内核 A ...
- Win64 驱动内核编程-14.回调监控文件
回调监控文件 使用 ObRegisterCallbacks 实现保护进程,其实稍微 PATCH 下内核,这个函数还能实现文件操作监视.但可惜只能在 WIN7X64 上用.因为在 WIN7X64 上 P ...
- Win64 驱动内核编程-10.突破WIN7的PatchGuard
突破WIN7的PatchGuard WIN64 有两个内核保护机制,KPP 和 DSE.KPP 阻止我们 PATCH 内核,DSE 拦截我们加载驱动.当然 KPP 和 DSE 并不是不可战胜的,WIN ...
- Win64 驱动内核编程-23.Ring0 InLineHook 和UnHook
Ring0 InLineHook 和UnHook 如果是要在R0里hook,作者的建议是InLine HOOK,毕竟SSDT HOOK 和 SHADOW SSDT HOOK比较麻烦,不好修改.目前R3 ...
随机推荐
- sap2000v21安装教程(附详细安装步骤+中文安装包)
sap2000 v21是sap2000系列软件的全新版本,也是目前行业中的一款用于结构分析和设计的集成软件,该软件保持了原有产品的传统,具有完善.直观和灵活的界面,能够在交通运输.工业.公共事业.体育 ...
- windows 之间内网开启远程桌面连接
win7设置远程桌面1.找到我的电脑\计算机图标,右键"属性"如图2.进入系统和安全设置-选项卡中,找到"远程设置"右上角位置点击打开3.在随后的"系 ...
- 浅谈Dotnet的数据定位和匹配
Dotnet里,数据定位和匹配的相关编程现在变得很舒服. 最近项目紧,还要不停出差. 所以,写个短点的.最近经常用到的内容:数据定位和匹配. 数据定位 假设我们有这样一个数组: var arr ...
- windows程序员开发linux程序的头一个月
开发环境选择 vim,vscode,qt,visual studio都可以做linux c++开发,但是作为windows程序员,最熟悉的还是visual stuio,加上visual studio ...
- github个人主页 阿里云域名的绑定
域名解析 我在阿里云上买了一个新域名:gaolu.name,我已经在GitHub Pages上建立了自己的博客:http://gaolu1215.github.io.现在我希望将gaolu.name映 ...
- Hive数据导出的几种方式
在hive的日常使用中,经常需要将hive表中的数据导出来,虽然hive提供了多种导出方式,但是面对不同的数据量.不同的需求,如果随意就使用某种导出方式,可能会导致导出时间过长,导出的结果不满足需求, ...
- python-实现顺序栈
7 class sqstack(object): 8 def __init__(self,maxsize): 9 self.maxsize = maxsize 10 self.stackElem = ...
- 小白的第一次sql实战
去年发的有一篇sql注入忘记粘贴过来了,今天想起了就fuzz过来一下 有id尝试sql注入 找这种sql注入的站用sql检索就行了,但是最好挂代理用谷歌搜索,百度的话搜sql注入的很多被别人打过了,导 ...
- 回忆那些年我玩过的ide,看看哪些你也玩过,看图回忆
闲来无聊,回忆一下这些年玩过的ide.看看哪些你也玩过. QBasic 第一个ide,兴奋程度也是最大的,从此进入了码农行列 VisualBasic 可以拖界面了,成就感爆棚 Turbo C c语言, ...
- Vue3教程:Vue 3 + Element Plus + Vite 2 的后台管理系统开源啦
之前发布过一篇文章<Vue3教程:开发一个 Vue 3 + element-plus 的后台管理系统>,文中提到会开发并开源一个 Vue 3 + Element Plus 的项目供大家练手 ...