![](https://img-blog.csdnimg.cn/20201014180756757.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
windows核心编程
文章平均质量分 85
寻梦&之璐
这个作者很懒,什么都没留下…
展开
-
HANDLE HMODULE HINSTANCE HWND
Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。HMODULE 是代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址。HINSTANCE 在win32下与HMODULE是相同的东西,在Win32下还存在主要是因为win16程序使用HINSTANCE来区别task。HWND 是窗口句柄。HWND、HANDLE、HMODULE、HINSTANCE之间的差别不是在变量类型上,而是在语义上。HWND是线程相关的,你可以通过HWND找到该窗口所属进程和线程Handle原创 2022-05-11 21:37:46 · 618 阅读 · 0 评论 -
SetDlgItemText GetDlgItemText SetDlgItemInt 和GetDlgItemInt GetDlgItem
SetDlgItemText函数功能在对话框中设置控件的标题或文本。函数声明WINUSERAPIBOOLWINAPISetDlgItemTextA( _In_ HWND hDlg, _In_ int nIDDlgItem, _In_ LPCSTR lpString);第一个参数输入参数,包含控件的对话框的句柄。第二个参数输入参数,要设置标题或文本的控件。第三个参数输入参数,要复制到控件的文本返回值类型:布尔如果函数成功,则返回值为非零。如果函数失败原创 2022-05-11 21:37:10 · 1121 阅读 · 0 评论 -
线程锁&&互斥体&&事件(处理临界区)
线程锁临界区实现之线程锁:创建全局变量:CRITICAL_SECTION cs;初始化全局变量:InitializeCriticalSection(&cs);实现临界区:EnterCriticalSection(&cs);//使用临界资源LeaveCriticalSection(&cs);实例#include <iostream>#include<Windows.h>//创建全局变量CRITICAL_SECTION cs;原创 2021-02-21 00:35:17 · 3902 阅读 · 0 评论 -
编译器扩展SEH(2)
问题我们在制作SEH链的时候,每增加一个,就得进行一次如下代码__asm{mov eax,FS:[0]mov temp,eaxlea ecx,myExceptionmov FS:[0],ecx -------------->修改FS:[0]挂入链表}那么当编译进行自行生成时,会不会也是每增加一个try,except,然后就压入一个_EXCEPTION_REGISTRATION_RECORD结构体呢?接下来我们来看看如下代码会压入多少_EX原创 2021-02-18 18:55:34 · 4654 阅读 · 0 评论 -
编译器扩展SEH(1)
编译器支持的SEH __try{ --------------------------------------->1.挂入链表 }__except(过滤表达式)--------------------------------->2.异常过滤 {异常处理程序 ------------------------------------>异常处理程序 }过滤表达式规则:EXCEPTION_EXECUTE_HANDLER(1)执行except代码EXCEPTI原创 2021-02-18 13:21:39 · 3830 阅读 · 0 评论 -
VEH(向量化异常处理)
内容回顾:当用户异常产生后,内核函数KiDispatchException并不是像处理内核异常那样在0环直接进行处理,而是修正3环EIP为KiUserExceptionDispatcher函数后就结束了这样,当线程再次回到3环时,将会从KiUserExceptionDispatcher函数开始执行KiUserExceptionDispatcher调用RtDispatchException查找并执行异常处理函数如果RtDispatchException返回真,调用ZwContinue再次进入0环,原创 2021-02-18 00:07:34 · 5347 阅读 · 0 评论 -
SEH(结构化异常处理)
内容回顾:当用户异常产生后,内核函数KiDispatchException并不是像处理内核异常那样在0环直接处理,而是修正3环EIP为KiUSerExceptionDispatcher函数后就结束了。这样,当线程再次回到3环时,将会从KiUserExceptionDispatcher函数开始执行。KiUserExceptionDispatcher会调用RtlDispatchException函数来查找并调用异常处理函数,查找的顺序:先查全局链表:VEH再查句柄链表:SEH它是与线程有关的,原创 2021-02-18 00:01:06 · 5422 阅读 · 0 评论 -
异常分发(用户异常)
内容回顾:异常如果发送在内核层,处理起来比较简单,因为异常处理函数也在0环,不用切换堆栈,但是如果异常发生在3环,就意味着必须要切换堆栈,回到3环执行处理函数切换堆栈的处理方式与用户APC的执行过程几乎是一样的,惟一的区别就是执行用户APC时返回3环后执行的函数是KiUserApcDispatcher,而异常处理时返回3环后执行的函数是KiUserExceprionDispatcher所以,理解用户APC的执行过程是理解3环异常处理的关键用户异常的处理流程:VOID KiDispatchEx原创 2021-02-17 20:31:07 · 697 阅读 · 0 评论 -
异常分发(内核异常)
用户层异常与内核层异常异常,可以发生在用户空间,也可以发生在内核空间无论是CPU异常还是模拟异常,是用户层异常还是内核异常,都要通过KiDispatchException函数进行分发。理解这个函数是学好异常的关键,这个函数比较复杂KiDispatchException首先第一步,不管用户异常还是内核异常,先把Trap_frame(当前线程3环进入0环时,那些寄存区环境,也就是eip运行地方那些值)备份到context里(为返回3环做准备)这个函数两种异常(用户异常和内核异常)的分发都归它管,所以原创 2021-02-17 18:10:48 · 8024 阅读 · 0 评论 -
异常记录(CPU产生的异常和软件模拟产生的异常)
前奏当API函数3环进0环时,第一件事就是保存现场,保存到_Trap_Frame异常的分类CPU产生的异常错误首先肯定被CPU先发现,然后CPU就会执行相应的错误处理程序软件模拟产生的异常throw 1异常产生CPU异常的产生CPU指令检测到异常(例:除0)------>查IDT表,执行中断处理函数--------->CommonDispatchException------>KiDispatchException在跳转CommonDispatchExcepti原创 2021-02-17 17:52:38 · 900 阅读 · 0 评论 -
My First Window构造过程,SendMessage同步,PostMessage异步
第一步:定义你的窗口是什么样的?(创建,初始化,注册窗口类)窗口的类名:PSTR classname = (PSTR)"My First Window";创建窗口类的对象:WNDCLASS wndclass = { 0 }; //一定要将所有值赋值wndclass.hbrBackground = (HBRUSH)COLOR_MENU;//窗口背景色wndclass.lpfnWndProc = WindowProc;//窗口过程函数(注册回调函数)wndclass.lpszClass原创 2021-02-17 13:31:20 · 4963 阅读 · 0 评论 -
从内核层说清GetMessage , DispatchMessage
要点回顾:一个GUI线程有一个消息队列:普通线程–>GUI线程–>THREAD.W32THREAD -->THREADINFO–>消息队列一个线程可以有多个窗口,所有窗口共享一个消息队列:_WINDOW_OBJECT ---->PTHREADINFO pti //所属线程---->WNDPROC IpfnWndProc //窗口过程(窗口回调函数)为什么拿到句柄非得要回零环?GetMessage(&msg, NULL, 0, 0)Translate原创 2021-02-17 11:28:40 · 6120 阅读 · 2 评论 -
窗口与线程的关系
能产生消息的四种情况鼠标键盘其它的应用程序(其它进程送过SendMessage发送消息)操作系统的内核程序消息到哪里去当鼠标点击按钮时,那么这个消息就会去这个窗口所对应线程的消息队列,w32k.sys中开启了两个线程监听鼠标和键盘:这就是为什么程序卡死之后,鼠标还能动的原因。因为鼠标的监控是在0环的一个线程,和程序无关。如何通过窗口找到消息队列呢?首先我们得了解窗口实际是在哪?所以需要近一步往下了解窗口在哪?用IDA看user32.dll中的CreateWindow,跟踪到3原创 2021-02-16 16:41:31 · 3039 阅读 · 0 评论 -
消息机制(GUI线程讲解)
你能回答这些问题吗?什么是窗口句柄?在哪里?有什么用?什么是消息?什么是消息队列?消息队列在哪 ?什么是窗口过程?窗口过程是由谁调用的?没有消息循环窗口过程会执行吗?为什么要有w32k.sys这个模块?为什么只有使用图形界面的程序才可以访问KeServiceDescriptorTableShadow?界面“卡死”的时候为什么鼠标还可以动?消息队列:消息队列在何处呢?首先我们假设把消息队列放在用户空间(3环),那么谁又来往用户空间的消息队列存储这些东西呢?最好的解决方案就是找一个专原创 2021-02-16 14:46:37 · 1583 阅读 · 0 评论 -
物理内存的管理
简介物理内存:1.最大物理内存10-10-12分页,最多识别物理内存为4GB2-9-9-12分页,最多识别物理内存为GB2.操作系统限制为什么在xp中,明明是2-9-9-12分页,仍然无法超越4GB呢?因为操作系统(操作系统内核文件里面的几个函数)的限制,和32位无关。3.实际物理内存:MmNumberOfPhysicalPages * 4=物理内存查询到数据为0x7ff7c,这个数据是以物理页(4KB)为单位,转为KB为单位的话需要乘以4即可Windows采用什么方式管理原创 2021-02-16 00:50:45 · 439 阅读 · 0 评论 -
线性地址的管理
EPROCESS中+0x11c VadRoot : Void这就是个入口点,从这个入口点开始是一个搜索二叉树,这个二叉树里面每个结点都记录了一块被占用的线性地址空间,结点类型是_MMVD类型是 _MMVD,如下:接下来探索一下:因为它是根节点,所以呢?父节点也就为null左右子树都是_MMVD,往下继续找即可。左右子树的父节点一定是上一个点。为什么采用二叉树的方式管理线性地址空间呢?最主要的原因是使用二叉树查询的性能会更好(涉及数据结构)这个StartingVpn和这个Endi原创 2021-02-15 22:56:06 · 297 阅读 · 0 评论 -
私有句柄表(内核对象,并非用户对象),全局句柄表
私有句柄表1.什么是句柄(内核对象)当一个进程创建或者打开一个内核对象时,将获得一个句柄,通过这个句柄可以访问内核对象(注意:这里所说的句柄往往对应一个内核对象,调用窗口相关的函数时,也会得到所谓的句柄,但是那种句柄和这里所说的句柄是两回事,这里所说的句柄一定对应一个内核对象,而且这个内核对象其实也就是一个结构体,在0环才能够进行读写的。并非普通窗口,笔刷,字体等对象的句柄,这种对象我们通常称为用户对象,并非内核对象)如:HANDLE g_hMutex=::CreateMutex(NULL,FAL原创 2021-02-15 20:33:29 · 5298 阅读 · 0 评论 -
进程挂靠 详解
1.进程与线程的关系:一个进程可以包含多个线程一个进程至少要有一个线程进程为线程提供资源,也就是提供Cr3的值,Cr3中存储的是页目录表基址,Cr3确定了,线程能访问的内存也就确定了线程代码:mov eax,dword ptr ds:[0x12345678]CPU会如何解析这个0x12345678这个地址呢?1.CPU解析线性地址时通过页目录表来找对应的物理页,页目录表基址存在Cr3寄存器中2.当前的Cr3的值来源于当前的进程(_KPROCESS.Directory TableBase(+0原创 2021-02-15 16:54:32 · 3802 阅读 · 4 评论 -
等待链表_调度(准备运行)链表
对于进程断链,程序可以正常运行,原因是CPU执行与调度是基于线程的,进程断链只是影响一些遍历系统进程的API,并不会影响程序执行对于线程断链也是一样的,断链后在Windbg或者OD中无法看到被断的掉的线程,但不影响其执行(仍然再跑)(1.平时使用API查询当前进程有几个线程时,都从上图中的这个链表中查出,把链断掉后,影响了API查询结果)(2.CPU在调度线程时,切换线程时,并没有使用这个链表)线程三种状态:就绪,等待,运行1.等待链表在windbg中输入:(找等待链表指令:)dd KiW原创 2021-02-15 14:22:34 · 2432 阅读 · 0 评论 -
KPCR:CPU控制区(Processor Control Region)
KPCR介绍:1 .当线程进入0环时,FS:[0]指向KPCR(3环FS:[0]–>TEB)2 .每个CPU都有一个KPCR结构体(一个核一个)3 .KPCR 存储了CPU本身要用的一些重要数据:GDT,IDT以及线程相关的一些信息 (IDT和GDT并非通用,而是一个CPU有一组)KPCR成员_NT_TIB介绍1.+0x000 ExceptionList :Ptr32_EXCEPTION_REGISTRATION_RECORD当前线程内核异常链表2.+0x004 StackBas原创 2021-02-15 12:49:06 · 2578 阅读 · 0 评论 -
EPROCESS ETHREAD简介
EPROCESS(0环)中的KPROCESS主要成员介绍:1 .+0x000 Header:_DISPATCHER_HEADER“可等待对象”,比兔Mutex互斥体,Event事件等(WaitForSingleObject)2.+0x018 DirectoryTableBase:[2]Unit4B页目录表的基址(这个值最终会填在Cr3寄存器中)(所谓进程切换就是切换Cr3的值)3.+0x038 KernelTime : Unit4B+0x03c UserTime:Unit4B统计信息原创 2021-02-15 00:46:47 · 1106 阅读 · 0 评论 -
控制寄存器,CPU缓存,PWT,PCD
控制寄存器控制寄存器用于控制和确定CPU的操作模式Cr0 Cr1 Cr2 Cr3 Cr4 Cr1 保留Cr3 页目录表基址(在10-10-12分页和2-9-9-12分页结构是不一样的)Cr0寄存器说明:1.PE位:CR0的位0是启用保护标志PE=1保护模式PE=0实地址模式这个标志开启段级保护,而并没有启用分页机制。若要启用分页机制,那么PE和PG标志都要置位2.PG位:当设置该位时即开启了分页机制。在开启这个标志之前必须已经或者同时开启PE标志PG=0且PE=0 处理器工作是原创 2021-02-14 23:35:38 · 834 阅读 · 0 评论 -
中断与异常
1.什么是中断?1.中断通常是由CPU外部的输入输出设备(硬件)所触发的,供外部设备通知CPU“有事情需要处理”,因此又叫中断请求2.中断请求的目的是希望CPU暂时停止执行当前正在执行的程序,转区执行中断请求所对应的中断处理例程(中断处理程序在哪由IDT表决定)3.80X86有两条中断请求线:非可屏蔽中断线,称为NMI(NonMaskable Interrupt)可屏蔽中断线,称为INTR(Interrupt Require)详细解释:2.非可屏蔽中断如何处理(IDT表)中断号NM原创 2021-02-14 22:43:18 · 464 阅读 · 0 评论 -
DLL注入简单测试
什么是注入?所谓注入就是在第三方进程不知道或者不允许的情况下将 模板 或者 代码 写 入对方进程空间,并设法执行的技术在安全领域,“注入”是一种非常重要的技术手段,注入与反注入也一直处于不断变化的,而且越来越激烈的对抗当中已知的注入方式:远程线程注入,APC注入,消息钩子注入,注册表注入,导入表注入,输入法注入等等线程函数并非固定的,只需满足条件:四个字节的参数,四个字节的返回值,那么其它都无所谓了其实DLL注入就是利用CreateRemoteTheread来开启一个远程线程,但是这个线程函数原创 2021-02-11 14:16:41 · 7274 阅读 · 3 评论 -
两个小程序利用注入如何进行简单交互
找call这里涉及到找call,DLL代码cpp#include "pch.h"#define _MAP_ "共享内存"#include<Windows.h>#include <cstdio>#define __ATTACK__ 0x00411880#define __DEFEND__ 0x004118E0#define __SITDOWN__ 0x00411A90HMODULE g_hModule;void thread() { in原创 2021-02-11 13:13:16 · 334 阅读 · 0 评论 -
CreateThread和CreateRemoteThread
CreateThread函数功能创建一个线程以在调用进程的虚拟地址空间内执行。函数原型HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, __drv_aliasesMem LPVOID lpParameter, DWORD原创 2021-02-10 22:37:02 · 3077 阅读 · 0 评论 -
段描述符属性
整个GDT表中的段描述符分为两大类,一类是数据段或者代码段的描述符;一类是系统段描述符。当我们需要拆分段描述符来判断时,顺序如下:1.首先看P位,决定是否有效,无效则没必要继续2.然后看S位,通过S位把它分为两大类,当S位为1时,它就是数据段或者代码段的描述符;当S位为0时,它就是系统段描述符。3.根据S位s=1代码段或者数据段描述符s=0系统段描述符...原创 2021-02-10 19:23:56 · 1206 阅读 · 1 评论 -
段寄存器,段描述符和段选择子
X86 CPU的3个模式:实模式,保护模式和虚拟8086模式段寄存器:ES CS SS DS FS GS LDTR TR共8个读一个段寄存器只读16位,写一个段寄存器写96位Struct SegMent{WORD Selector;//16位selectorWORD Attribute;//16位的AttributeWORD Base;//32位的BaseDWORD Limit //32位的Limit};可以通过MOV指令对寄存器进行读写(LDTR和TR除外)可执行:当前修饰这个段的原创 2021-02-10 18:12:26 · 1637 阅读 · 5 评论 -
一次讲清UNICODE
UNICODE什么是UNICODE?这是一个编码方案,说白了就是一张包含全世界所有文字的一个编码表,只要这个世界上存在的文字符号,统统给你一个唯一的编码:Unicode编码范围:0~0x10FFFF,可以容纳100多万个符号UNICODE的问题:UNICODE只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储UTF-16UTF-16编码以16位无符号整数为单位,注意是16位为一个单位,不表示一个字符只有16位。这个要看字符的UNICODE编码处于什么范围而定,有原创 2021-02-05 22:54:23 · 8740 阅读 · 1 评论 -
HOOK虚函数
声明首先呢,这里会牵扯到虚函数,建议先看看以下博客(前三章就行),c++类成员函数指针详解虚函数的实现过程之初探虚表(1)详解虚函数的实现过程之单继承(2)详解虚函数的实现过程之多重继承(3)详解虚函数的实现过程之虚基类(4)详解虚函数的实现过程之菱形继承(5)看了之后大家会了解到:虚函数的地址存放在虚表里面,虚表地址放在对象里面,虚表地址都是放在对象的前四个字节。所以我们可以进行把存放在 虚表里面这个函数地址值给替换(这也就是Hook手法之一)了,当进行调用虚函数时,是不是就可以改变程原创 2021-02-05 15:38:48 · 4800 阅读 · 0 评论 -
内核和用户模式下进程与线程创建
内核模式下进程与线程的创建进程创建在内核模式中,一个进程的创建是从函数NtCreateProcess开始的。该函数位于文件ntosrnl.exe中,该文件位于%windir%\system32.它对用户传进的部分参数进行简单处理,然后交给函数NtCreateProcessExNTSTATUS NtCreateProcessEx( __out PHANDLE ProcessHandle, //返回进程句柄 __in ACCESS_MASK DesiredAccess,原创 2021-02-04 19:25:21 · 2542 阅读 · 1 评论 -
c++类成员函数指针
提出疑问首先问大家一句,什么是函数指针?肯定有的人会这样回答,函数指针?不就是指向函数地址的一个指针吗?或者就是一个存放着一个函数首地址的变量?当然,那些有点底层基础的肯定会这样说,函数就是一堆连续的机器码,而函数指针,就是存放了这堆连续机器码首地址的变量。那么大家是不是回答的时候,考虑的地方是不是仅仅局限于 一般的函数????那么成员函数呢???为什么得强调成员函数呢?因为成员函数包括了虚函数和非虚函数(这里涉及虚表问题,可以先简单看看列出的虚函数系列,否则接下来问题会有点难以接受。)虚函数原创 2021-01-19 18:04:56 · 7628 阅读 · 2 评论 -
PROCESSENTRY32结构体 CreateToolhelp32Snapshot Process32First 和Process32Next
PROCESSENTRY32结构体typedef struct tagPROCESSENTRY32{ DWORD dwSize; DWORD cntUsage; DWORD th32ProcessID; // this process ULONG_PTR th32DefaultHeapID; DWORD th32ModuleID; // associated exe DWORD cntThreads原创 2021-01-14 23:15:51 · 1697 阅读 · 0 评论 -
InternetOpen InternetOpenUrl InternetReadFile 和 InternetCloseHandle
InternetOpen函数功能初始化应用程序对WinINet函数的使用函数声明INTERNETAPI_(HINTERNET) InternetOpenA( _In_opt_ LPCSTR lpszAgent, _In_ DWORD dwAccessType, _In_opt_ LPCSTR lpszProxy, _In_opt_ LPCSTR lpszProxyBypass, _In_ DWORD dwFlags );第一个参数指向以null终原创 2021-01-13 12:03:11 · 3550 阅读 · 1 评论 -
OpenProcessToken LookupPrivilegeValue 和AdjustTokenPrivilege
OpenProcessToken函数功能用来打开与进程相关联的访问令牌函数申明WINADVAPIBOOLWINAPIOpenProcessToken( _In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Outptr_ PHANDLE TokenHandle );第一个参数ProcessHandle [in],输入参数,要打开的访问令牌所属的进程句柄,查询进程必须拥有PROCESS_QUERY_INF原创 2021-01-13 00:58:04 · 783 阅读 · 0 评论 -
FindWindow ,GetWindowThreadProcessId , OpenProcess 和ReadProcessMemory
FindWindow函数功能:函数检索处理顶级窗口的类名和窗口名称匹配指定的字符串,这个函数不搜索子窗口。第一个是要找的窗口的类,第二个是要找的窗口的标题函数声明:WINUSERAPIHWNDWINAPIFindWindowW( _In_opt_ LPCWSTR lpClassName, _In_opt_ LPCWSTR lpWindowName);在搜索的时候不一定两者都知道,但至少要知道其中的一个。第一个参数lpClassName,输入参数,指向一个以null结尾原创 2021-01-13 00:01:28 · 1553 阅读 · 0 评论 -
dll注入之SetWindowsHookEx(1)
第一步学会写dll(格式这些东西自行查询 以及学习),然后生成(解决方案)即可新建项目动态链接库2.写完之后,在生成----> 生成解决方案 即可在debug下面找到Dll2.dll文件3.生成之后,直接把dll文件拷贝到注入代码Main.cpp相同目录下,然后导入进行注入即可实现代码举例:Dll2.dll实现代码// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "pch.h"#include<iostream>#incl原创 2021-01-12 20:14:39 · 5276 阅读 · 2 评论 -
GetMessage TranslateMessage DispatchMessage 和PeekMessage
GetMessage函数功能GetMessage是计算机编程中的一个函数,从调用线程的消息队列里取得一个消息并把其放于指定的结构。GetMessage函数可取得与指定窗口联系的消息和由PostThreadMesssge寄送的线程消息,接收一定范围的消息值,不接收属于其他线程或应用程序的消息。GetMessage获取消息成功后,线程把从消息队列中删除该消息,函数会一直等待直到有消息到来才有返回值。函数声明WINUSERAPIBOOLWINAPIGetMessage( _Out_ LPMS原创 2021-01-12 15:02:49 · 790 阅读 · 0 评论 -
(Hook)SetWindowsHookEx和UnhookWindowsHookEx
函数功能钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传原创 2021-01-12 13:16:05 · 789 阅读 · 1 评论 -
c/c++ typedef定义函数指针(Hook前奏2)
简介关于函数指针的介绍,点击超链接即可查看,这里就不做过多说明了,或者可以点击这里:https://blog.csdn.net/CSNN2019/article/details/112492092关于typedef作用的介绍,点击超链接即可查看,这里就不做过多说明了,或者可以点击这里:https://blog.csdn.net/CSNN2019/article/details/112495262接下来呢,我们一起来通过例子来讲解一下typedef 定义函数指针:#include<iostr原创 2021-01-11 23:03:31 · 5052 阅读 · 1 评论