几个常用内核函数(《Windows内核情景分析》)
参考:《Windows内核情景分析》
0x01 ObReferenceObjectByHandle
这个函数从句柄得到对应的内核对象,并递增其引用计数。
NTSTATUS
ObReferenceObjectByHandle(
IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType,IN
KPROCESSOR_MODE AccessMode,
OUT PVOID* Object,
OUT POBJECT_HANDLE_INFORMATION
HandleInformation)
{
*Object = NULL;
//若句柄是一个内核句柄或当前进程、线程的句柄
if (HandleToLong(Handle) < 0)
{
if (Handle == NtCurrentProcess())//若句柄值是当前进程的句柄(-1),特殊处理
{
if ((ObjectType == PsProcessType) || !(ObjectType))
{
CurrentProcess = PsGetCurrentProcess();
GrantedAccess = CurrentProcess->GrantedAccess;
//if内核模式/要求的权限<=进程对象支持的权限(权限检查)
if ((AccessMode == KernelMode) ||!(~GrantedAccess & DesiredAccess))
{
if (HandleInformation)
{
HandleInformation->HandleAttributes = 0;
HandleInformation->GrantedAccess = GrantedAccess;
} ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentProcess);
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);//递增引用计数
*Object = CurrentProcess;//返回得到的对象指针
Status = STATUS_SUCCESS;
}
Else //权限检查不通过
Status = STATUS_ACCESS_DENIED;
}
else
Status = STATUS_OBJECT_TYPE_MISMATCH;
return Status;
}
else if (Handle == NtCurrentThread())//若句柄值是当前线程的句柄(-2),特殊处理
{
if ((ObjectType == PsThreadType) || !(ObjectType))
{
CurrentThread = PsGetCurrentThread();
GrantedAccess = CurrentThread->GrantedAccess;
if ((AccessMode == KernelMode) ||!(~GrantedAccess & DesiredAccess))
{
if (HandleInformation)
{
HandleInformation->HandleAttributes = 0;
HandleInformation->GrantedAccess = GrantedAccess;
}
ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentThread);
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
*Object = CurrentThread;
Status = STATUS_SUCCESS;
}
else
Status = STATUS_ACCESS_DENIED;
}
else
Status = STATUS_OBJECT_TYPE_MISMATCH;
return Status;
}
else if (AccessMode == KernelMode)//若句柄是一个内核句柄
{
Handle = ObKernelHandleToHandle(Handle);//去掉最高位的1,转为普通句柄
HandleTable = ObpKernelHandleTable;//采用内核句柄表
}
}
Else //最典型的情况,普通句柄,就使用当前进程的句柄表
HandleTable = PsGetCurrentProcess()->ObjectTable;
//以该句柄的值为“索引”,找到句柄表中对应的句柄表项
HandleEntry = ExMapHandleToPointer(HandleTable, Handle)
if (HandleEntry)//如果找到了,这就是一个有效句柄
{
ObjectHeader = ObpGetHandleObject(HandleEntry);//关键。获得该句柄指向的对应对象
if (!(ObjectType) || (ObjectType == ObjectHeader->Type))
{
GrantedAccess = HandleEntry->GrantedAccess;
if ((AccessMode == KernelMode) ||!(~GrantedAccess & DesiredAccess))//通过权限检查
{
InterlockedIncrement(&ObjectHeader->PointerCount);
Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
if (HandleInformation)
{
HandleInformation->HandleAttributes = Attributes;
HandleInformation->GrantedAccess = GrantedAccess;
}
*Object = &ObjectHeader->Body;//返回的是对象体的地址
return STATUS_SUCCESS;
}
Else //权限检查没通过
Status = STATUS_ACCESS_DENIED;
}
else
Status = STATUS_OBJECT_TYPE_MISMATCH;
}
Else //有可能用户给定的句柄值是一个无效句柄,在句柄表中找不到
Status = STATUS_INVALID_HANDLE;
*Object = NULL;
return Status;
}
两个特殊情况:
#define NtCurrentProcess() (HANDLE)-1
#define NtCurrentThread() (HANDLE)-2
这是两个伪句柄值,永远获得的是当前进程、线程的内核对象。
另外:若句柄值的最高位是1,则是一个内核句柄,各进程通用。内核型句柄是“System”进程的句柄表中的句柄。因此,要获得内核句柄对应的对象,系统会挂靠到“System”进程的地址空间中,去查询句柄表。
根据句柄值在句柄表中找到对应的表项是靠ExMamHandleToPointer这个函数实现的,这个函数又在内部调用ExpLookupHandleTableEntry来真正查找。句柄表组织为一个稀疏数组(目的用来节省内存),但可以
简单的看做一个一维数组,不影响理解,句柄值本身也可简单理解为一个索引。
调用方传递给驱动程序的句柄不会经过 I/O 管理器,因此 I/O 管理器不对这类句柄执行任何验证检查。决不要假设一个句柄有效;始终确保句柄拥有正确的对象类型、对于所需任务的合适的访问权、正确的访问模式,并且访问模式与请求的访问兼容。
驱动程序应该谨慎使用句柄,特别是那些从用户模式应用程序接收到的句柄。
第一,这种句柄特定于进程上下文,因此它们仅在打开句柄的进程中有效。当从不同的进程上下文或工作线程使用时,句柄可以引用不同的对象或者只是变得无效。
第二,在驱动程序使用句柄期间,攻击者可以关闭和重新打开句柄来改变其引用的内容。
第三,攻击者可以传入这样一个句柄来引诱驱动程序执行对于应用程序非法的操作,例如调用 ZwXxx 函数。对于这些函数的内核模式调用方,访问检查被跳过,因此攻击者可以使用这种机制绕过验证。
驱动程序还应该确保用户模式应用程序不能误用驱动程序创建的句柄。为一个句柄设置 OBJ_KERNEL_HANDLE 属性使其成为内核句柄,内核句柄可以在任何进程上下文中使用,但是只能从内核模式进行访问(对于传递给ZwXxx 例程的句柄,这特别重要)。用户模式的进程不能访问、关闭或替换内核句柄。
几个常用内核函数(《Windows内核情景分析》)的更多相关文章
- Linux 内核和 Windows 内核有什么区别?
Windows 和 Linux 可以说是我们比较常见的两款操作系统的. Windows 基本占领了电脑时代的市场,商业上取得了很大成就,但是它并不开源,所以要想接触源码得加入 Windows 的开发团 ...
- Windows内核原理系列01 - 基本概念
1.Windows API Windows 应用编程接口(API)是针对WIndwos操作系统用户模式的系统编程接口,包含在WindwosSDK中. 2.关于.NET .NET由一个被称为FCL的类库 ...
- windows内核基础与异常处理
前两日碰到了用异常处理来做加密的re题目 所以系统学习一下windows内核相关 windows内核基础 权限级别 内核层:R0 零环 核心态工作区域 大多数驱动程序 应用层:R3 用户态工作区域 只 ...
- windows内核情景分析之—— KeRaiseIrql函数与KeLowerIrql()函数
windows内核情景分析之—— KeRaiseIrql函数与KeLowerIrql()函数 1.KeRaiseIrql函数 这个 KeRaiseIrql() 只是简单地调用 hal 模块的 KfRa ...
- windows内核编程之常用数据结构
1.返回状态 绝大部分的内核api返回值都是一个返回状态,也就是一个错误代码.这个类型为NTSTATUS.我们自己写的函数也大部分这样做. NTSTATUS MyFunction() { NTSTAT ...
- [4]Windows内核情景分析---内核对象
写过Windows应用程序的朋友都常常听说"内核对象"."句柄"等术语却无从得知他们的内核实现到底是怎样的, 本篇文章就揭开这些技术的神秘面纱. 常见的内核对象 ...
- [1]windows 内核情景分析---说明
本文说明:这一系列文章(笔记)是在看雪里面下载word文档,现转帖出来,希望更多的人能看到并分享,感谢原作者的分享精神. 说明 本文结合<Windows内核情景分析>(毛德操著).< ...
- Windows内核-7-IRP和派遣函数
Windows内核-7-IRP和派遣函数 IRP以及派遣函数是Windows中非常重要的概念.IRP 是I/O Request Pocket的简称,意思是I/O操作的请求包,Windows中所有Use ...
- Windows 驱动发展基金会(九)内核函数
Windows 驱动发展基金会系列,转载请注明出处:http://blog.csdn.net/ikerpeng/article/details/38849861 这里主要介绍3类Windows的内核函 ...
随机推荐
- 什么时候使用“RCC_APBXPeriph_AFIO”
什么时候需要开启复用时钟: (1)使用EXTI (2)重映射(用到外设的重映射功能时才需要使能AFIO的时钟) 举例:重映射USART2 USART2的TX/RX在PA.2/3.但是,PA.2已经被T ...
- linux中查找(find、locate、which、whereis、grep)命令汇总、帮助命令(man、whatis、apropos、info、help)汇总
(一)find命令详解 find:功能:文件搜索: 语法:find[搜索范围][匹配条件]: 只要匹配条件完全符合才可以被显示,使用通配符*匹配条件*则可以显示匹配条件的所有目录,问号?匹配单个字符 ...
- js随机数的取整
- Python3学习笔记--迭代器
迭代 使用一个循环来遍历某个东西时这个过程本身叫做迭代. 可迭代对象 python中只要定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法,那么它就 ...
- ios开启双重认证之填坑式教学
2019.03.01.阳光明媚(不,,,有些雾霾..) 本来打算发布一个新版本app,修复一些小小bug, 然而,打包出错了,,错误是显示账号无连接.. 顿时慌出了天际,,以为是账号的证书问题,,最烦 ...
- Economics degrees
Economics degrees Name game"> 经济学学位"> 名称痕戏 Luring students with a new label 新瓶旧酒吸引学生 ...
- Ant Design of React 框架使用总结1
一. 为什么要用UI 框架 统一了样式交互动画 . Ui框架会对样式,交互动画进行统一,保证了系统风格完整统一,不像拼凑起来的. 兼容性 ,不是去兼容IE 6 7 8那些低版本浏览器,而是对主流的标 ...
- LayaAir引擎开发HTML5最简单教程(面向JS开发者)
LayaAir引擎开发HTML5最简单教程(面向JS开发者) 一.总结 一句话总结:开发游戏还是得用游戏引擎来开发,其实很简单啦 切记:开发游戏还是得用游戏引擎来开发,其实很简单,引擎很多东西都帮你做 ...
- UML作业第三次
一.学习小结 类之间的关系通过符号定义 : 使用.. 来代替 -- 可以得到点 线. 例如: @startuml Class01 <|-- Class02 Class03 *-- Class04 ...
- jQueryEasyUI应用 – datagrid之CRUD应用
本文 jQueryEasyUI + SpringBoot + Mybatis整合Datagrid的CRUD应用 一.前言准备 1.我们将使用下面的插件: datagrid:向用户展示列表数据. dia ...