几个常用内核函数(《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的内核函 ...
随机推荐
- KMP总结
首先给一个我能看懂的KMP讲解: http://blog.csdn.net/v_july_v/article/details/7041827 来自大神july 文章很长,但是慢慢看,会发现讲的很好. ...
- python读Excel
import xlrd def open_excel(fileName="TransInfo.xlsx"): try: fileHandler = xlrd.open_workbo ...
- xml转json和实体类的两种方式
本文为博主原创,未经允许不得转载: xml在http通信中具有较高的安全性和传输速度,所以应用比较广泛, 在项目中往往需要对xml,json和实体类进行相互转换,在这里总结一下自己所用到的一些方法: ...
- ZOJ 2477 Magic Cube(魔方)
ZOJ 2477 Magic Cube(魔方) Time Limit: 2 Seconds Memory Limit: 65536 KB This is a very popular gam ...
- vue--vant组件库Dialog弹出框
安装vant UI框架: cnpm install vant –-save-dev 导入组件-在main.js里: import Vant from 'vant'; import'vant/lib/v ...
- python打包分发工具setuptools使用记录
关于python setup.py文件的编写技巧 环境:最新版setuptools,初步认识setuptools可以参考这篇文章 1. 自定义命令 from setuptools import set ...
- .bat批处理启动redis
背景: 最近,公司的项目开发,需要用到Redis,然而每天都需要到d盘下面的去启动redis很烦, 我是我就想写一个.bat启动文件放在桌面上,这样每天只要在桌面上点以下redis的bat文件就可以启 ...
- HBase详解
1. hbase简介 1.1. 什么是hbase HBASE是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBASE技术可在廉价PC Server上搭建起大规模结构化存储集群. H ...
- 在action中进行文件下载,下载时运行不报错,可是也不下载
在写前端下载页面时,使用ajax方式调用action中的方法,然后就将下载内容返回js中了,所以没有下载,之后改为使用Windows.location进行下载,就没有问题了. action中代码: i ...
- cryptoJS
CryptoJS通俗的来讲是为了安全性,将前端传递到后端的参数加密 加密/解密方法(对称加密算法) AES 高级加密标准,是下一代的加密算法标准,速度快,安全级别高 DES 数据加密标准,适用于大量数 ...