句柄表跟内核对象

一丶什么是句柄表什么是内核对象.

1.句柄表的生成

我们知道.我们使用CreateProcess 的时候会返回一个进程句柄.以及线程句柄. 其实在调用CreateProcess的时候.内核中会新建一个EPROCESS结构来存储我们的进程信息.

例如如下图:

  

但是有一个问题.怎么给三环使用.难道直接返回EPROCESS?

其实不是这样的. 第一EPROCESS在高两G. 三环程序是不可以访问的.所以返回的地址是高两G所以不能使用. 但是为了解决这一问题.

windows创建了一个表格. 返回这个表格的索引. 而我们使用的就是这个索引.

2.什么是内核对象.

内核对象就是我们上面所说的EPROCESS. 有很多内核对象.具体可以看下CloseHandle. 这个API表示他可以关闭什么内核对象.

  • Access token
  • Communications device
  • Console input
  • Console screen buffer
  • Event
  • File
  • File mapping
  • I/O completion port
  • Job
  • Mailslot
  • Memory resource notification
  • Mutex
  • Named pipe
  • Pipe
  • Process
  • Semaphore
  • Thread
  • Transaction
  • Waitable timer

可以操作事件  文件 互斥体 线程. 等等....

二丶多进程共用内核对象

1.第一种方法. 使用OpenProcess

在windows程序中.我们操作的都是内核对象. 我们可以通过OpenProcess API来打开一个已有进程的内核对象.

如下图:

  

每个进程里面的句柄表都是私有的. 例如第一张表. 句柄索引位1. 对应内核对象为A. 那么将索引传给B进程是没用用的.

B进程只有使用API打开之后才能获得 A内核对象.

其中中间的紫色表代表引用计数. 也就是说这个内核对象引用一次 这个值则会+1

而CloseHandle作用就是 使内核对象的引用计数-1 如果都关闭了.那么此时内核对象没有人使用. 也没有执向了.所以就会销毁这个内核对象了.也就是说.当内核对象的引用计数位为0了.那么此时的内核对象

才是真正的销毁.

而线程是特例:  当线程的内核对象引用计数为0的时候也不会关闭.  此时必须先关闭线程.在使用CloseHandle 是引用计数 -1才可以.

2.使用继承句柄技术

在windows程序中. A创建 B .或者带有内核对象的 API在创建的时候. 都有一个SD属性.也就是安全属性.这个属性可以表示你创建的这个句柄是否可以继承.

例如:

  CreateEvent()创建事件. 先不用管API的作用.我们看下API的参数吧.

HANDLE CreateEventA(
LPSECURITY_ATTRIBUTES lpEventAttributes, 安全属性结构体 主要介绍他
BOOL bManualReset,
BOOL bInitialState,
LPCSTR lpName
);

第一个就是安全属性结构体.如果我们不指定.默认就是父进程的.

安全属性结构体.

typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; 当前结构体大小.windows扩展使用的
LPVOID lpSecurityDescriptor; 表明这个句柄给谁用谁可以访问.谁可以关闭.不重要 具体可以看下API中的结构体的定义.不重要不列出来了.
BOOL bInheritHandle; 重要.表明句柄是否可以被继承.
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

如下图所示:

如果我们的句柄可以被继承. 那么句柄表的第一项就填1.表示这个句柄可以被继承.如果不能继承.则为0

此时我们的子进程就可以继承父进程的 所有可继承的句柄表了.  注意.是所有可继承.  可以是共享的了. 如下图所示.

A进程创建的 B D是可以继承的. 所以 子进程可以完全复制A进程 可继承句柄表. 不允许继承的为0 都赋值为0

二丶进程PID解析

在windows任务管理器中.有PID选项.我们可以选中查看. 而且在windows中也常常听到进程ID的概念.

那么进程ID到底是个什么东西.

其实进程ID是全局的句柄表的一个索引.  上面所讲的句柄表.都是自己私有的句柄表. PID是全局句柄表里面的.

这个句柄表里面记录了所有的正在运行进程的句柄.而且是唯一的. 如果进程死亡那么这个pid可能会执向别的句柄.  但也是唯一的.如下图所示.

而这个全局句柄表才是真正有意义的.为什么这样说.

我们可以做个测试.

1.使用OpenProcess打开进程句柄.

2.使用TerminlateProcess结束进程.

OpenProcess(访问权限,句柄是否可以继承,进程PID)

TerminlateProcess(进程句柄,自定义的退出码) 结束进程.

使用上面的两个API可以测试一下我们已有的进程是否可以被关闭. 如果测试过后你会发现.

只有PID获得句柄才是有用了.也就是说全局句柄表. 而上面所讲的都是子进程的句柄表.

三丶常用进程操作API

1. GetModuleFileName()  获取当前模块路径 例如:  c:\\1.exe

2.GetCurretDirectory()     获取当前的工作目录 例如:  c:\text\abc

3.OpenProcess()  根据进程PID打开进程.获取进程句柄.

4.FindWindow()    根据类名以及文件名.返回窗口句柄.

5.GetWindowsThreadProcessId()  根据窗口句柄.获取进程PID

6.EnumProcesses 遍历所有进程.返回进程PID    具体参考MSDN 有提供的例子.

7.GetCommandLine() 获取命令行参数

8.CreateToolHelp32Snapshot() 创建进程快照. 如果懂逆向的就知道.FS寄存器中的TEB PEB结构中有存储当前模块的或者进程的链表.这个是保存当前这一时刻的快照.

我们可以进行遍历. 具体参考MSDN或者本博客.

四丶编写windows程序遇到的问题.

我们在编写windows程序的时候.会包含windows.h 但是有的函数可能就没有. 比如上面我们说的第八个函数. 快照函数.

此时我们要查询MSDN. 我们可以搜索一下网页的.

我们可以在下边看到所需要的头文件 是 tlhelp32.h 此时我们包含一下即可.

遇到的问题2.

有的时候我们头文件也包含了也去使用了.但是调用API的时候出错了.为什么?

原因是 有的API在高版本中才有.低版本中使用的时候是没有导出的.此时使用就会出错.提示没有这个API.

解决方法: 如果学过win32的 说的这个方法你们就理解了.如果没学过也没关系.一般这个问题很少遇见. 博主也才预见过一次.

可以使用 loadlibary加载所需要的dll. 然后使用 GetProcAddress获取函数地址. 使用函数指针来使用这个函数.

win32进程概念之句柄表,以及内核对象.的更多相关文章

  1. EPROCESS 进程/线程优先级 句柄表 GDT LDT 页表 《寒江独钓》内核学习笔记(2)

    在学习笔记(1)中,我们学习了IRP的数据结构的相关知识,接下来我们继续来学习内核中很重要的另一批数据结构: EPROCESS/KPROCESS/PEB.把它们放到一起是因为这三个数据结构及其外延和w ...

  2. 零基础逆向工程39_Win32_13_进程创建_句柄表_挂起方式创建进程

    1 进程的创建过程 打开系统 --> 双击要运行的程序 --> EXE开始执行 步骤一: 当系统启动后,创建一个进程:Explorer.exe(也就是桌面进程) 步骤二: 当用户双击某一个 ...

  3. 内核对象&句柄

    目录 1 内核对象的概念 2 内核对象的使用计数 3 句柄 4 句柄表   项目工程代码中设计句柄的使用,一时不知句柄是何物,通过查阅自学之后,对句柄及其使用有一个初步的了解.分享出来,算是抛砖引玉吧 ...

  4. Windows进程的内核对象句柄表

    当一个进程被初始化时,系统要为它分配一个句柄表.该句柄表只用于内核对象 ,不用于用户对象或GDI对象. 创建内核对象 当进程初次被初始化时,它的句柄表是空的.然后,当进程中的线程调用创建内核对象的函数 ...

  5. 【Windows 操作系统】Windows 进程的内核对象句柄表

    总结: 1.句柄就是进程句柄表中的索引.2.句柄是对进程范围内一个内核对象地址的引用,一个进程的句柄传给另一个进程是无效的.一个内核对象可用有多个句柄.Windows之所以要设立句柄,根本上源于内存管 ...

  6. 驱动开发:内核枚举PspCidTable句柄表

    在上一篇文章<驱动开发:内核枚举DpcTimer定时器>中我们通过枚举特征码的方式找到了DPC定时器基址并输出了内核中存在的定时器列表,本章将学习如何通过特征码定位的方式寻找Windows ...

  7. windows核心编程---第三章 内核对象及句柄本质

      本章讨论的是相对抽象的概念,不涉及任何具体的内核对象的细节而是讨论所有内核对象的共有特性. 首先让我们来了解一下什么是内核对象.内核对象通过API来创建,每个内核对象是一个数据结构,它对应一块内存 ...

  8. 计算机操作系统处理机调度读后感—–关于进程概念的剖析。从RING3到RING0(32位操作系统)

    计算机操作系统处理机调度读后感: 笔者在看操作系统西安电子科技大学那本书的时候,初次感觉本科教的不会太难,所以没有认真的看,但是随后这本书讲的刷新了我的世界观.这本书居然是ring0级别的,这时不禁吐 ...

  9. 《windows核心编程系列》三谈谈内核对象及句柄的本质

    内核对象 本章讨论的是相对抽象的概念,不涉及任何具体的内核对象的细节而是讨论所有内核对象的共有特性. 首先让我们来了解一下什么是内核对象.内核对象通过API来创建,每个内核对象是一个数据结构,它对应一 ...

随机推荐

  1. vscode快捷键的中文版

    自己整理了一份vscode快捷键的中文版本

  2. Matching Networks for One Shot Learning

    1. Introduction In this work, inspired by metric learning based on deep neural features and memory a ...

  3. 移动端web兼容各种分辨率写法

    移动端web开发最好用rem单位,再设置以下js,以iphone6 750*1334为基准 <script> var size = document.documentElement.cli ...

  4. ScriptOJ-flatten2#91

    generator的使用 function *flatten2 (arr) { const result = [] function flatten(ar) { ar.map(iter => { ...

  5. oracle数据库创建分区表

    参考资料:http://blog.chinaunix.net/uid-21943216-id-4062400.html 一.建按月自增分区表:1.1建表SQL> create table mon ...

  6. 几种String对象方法的区别

    1.在String对象方法中,发现.slice()方法和.substring()方法的作用几乎相同,都是根据起始索引返回截取得到的字符串.经过查阅资料和实测得到区别: 正常情况下索引都为正值,返回值为 ...

  7. python 引入本地 module

    数据校验时,需要引入本地的一个告警python代码,引入的方式如下: import sys import os # 引入本地文件目录,或和需要引入的python文件放在同一个文件夹下 sys.path ...

  8. centos docker安装和使用

    系统要求:centos7,内核3.10或更高一.配置yum源并安装 vim /etc/yum.repos.d/docker.repos [dockerrepo] name=Docker Resposi ...

  9. PHP合并数组

    1.arrary_merge 示例代码: $arr1 = array(1, 2, 3, 4, 5); $arr2 = array(1, 2, 6, 7, 8, 9, 10); $result1 = a ...

  10. ubuntu 16.04下源码安装opencv3.4

    源码安装opencv,遇到了一些小波折,这里做个备忘吧. 首先要下载源码,路径: https://github.com/opencv/opencv 下载成功后,在opencv的根目录下执行下面操作: ...