Windows x64内核(3)——分页机制
Windows x64内核9-9-9-9-12分页机制介绍之前我们学过的x86用的是2-9-9-12和10-10-12的分页机制
x64下,分页大小有4K,2M,1G的大小
如果PDE的PS位为0,则为4K,为1则为2M
如果PDPTE 的PS=1的话,指向 1GB 页
x64下,4k分页变成了9-9-9-9-12的分页机制
虽然64位下的地址有64位,但是实际用到的只有48位,这主要因为以下原因:
当前需求有限:
管理复杂度:
使用完整的 64 位地址空间将引入极大的管理和硬件复杂性。
页表大小和效率:
使用四级页表(9-9-9-9-12 分级结构)能够有效管理 48 位的虚拟地址空间。使用更多位数意味着增加页表层级,可能需要五级或更多级页表,这会带来额外的内存和性能开销。当前四级页表架构已经能够高效地处理 48 位地址,而无需增加复杂性。
我们来依次解析下每一个数字的含义:
PML4(Page Map Level 4):页目录指针表
在windows叫PXE
最高的页表层级,用 9 位来索引 PML4 表项。PML4 表最多可以有 512 个条 ...
Windows x64内核(2)——天堂之门
Windows x64内核天堂之门简介在x86-64 架构中,有一个特殊的机制可以让 CPU 在 64 位模式和 32 位模式之间进行切换。Heaven's Gate 就是利用这个机制,在 32 位环境下进入 64 位模式,从而执行 64 位代码并调用 64 位 API。
在长模式下(即 64 位处理器启用 64 位功能时),段选择子可以用来确定 CPU 运行在 64 位模式还是兼容模式。 (具体是CS段寄存器的L位,设置为1就是64位模式)
通过以下代码,32位程序可以转而执行64位汇编代码
123push 0x33 ; 将 64 位代码段选择子压入堆栈push 64bit_address ; 压入 64 位模式下要执行的代码地址retf ; 远返回,切换到 64 位模式
实战一波具体我们实验一下
1234567891011121314151617181920212223242526272829#include <windows.h>#include <iostream>using ...
win x64内核(1)——x64内核与x86的一些区别
Windows x64内核x64下的分段机制
前情回顾:
1. GDT(全局描述符表)
分段机制: GDT是分段机制的核心部分。它定义了系统中所有的段描述符,供处理器在保护模式下使用。GDT中的描述符用于定义代码段、数据段以及系统段的基地址、段限长、访问权限等。
功能:
代码段和数据段: GDT包含代码段(代码段描述符)和数据段(数据段描述符)的定义,描述段的起始地址、段限长、段的特权级(DPL,Descriptor Privilege Level)、段类型等。
系统段: 包括TSS(任务状态段)、LDT(局部描述符表)等的描述符,用于任务切换和其他系统级功能。
2. LDT(局部描述符表)
分段机制: LDT也是分段机制的一部分,但它是GDT的一个补充。LDT允许每个进程或任务有自己独立的段描述符表,从而支持每个进程或任务使用不同的段设置。
功能:
局部描述符: LDT提供了局部段描述符,用于定义特定于某个任务或进程的代码段和数据段。每个LDT包含的描述符范围仅限于该LDT,而不是整个系统。
任务隔离: 通过使用LDT,操作系统可以实现任务间的段隔离,允许不同任务使用不同的段配 ...
MFC逆向分析(找消息处理函数)
MFC事件逆向分析选用测试软件:家庭账本3.5.9
相较于Win32窗口编程,拿到消息后可以在消息处理回调函数里面寻找对应的消息处理函数不同
MFC程序的运行常常令我摸不着头脑,有时候根本就不知道如何去找到对应的处理函数,例如按钮事件的事件处理函数。
最近遇到一些MFC的ctf题目和一些MFC写的软件想要尝试破解,但是无奈按钮事件非常难找,一旦字符串加密或者没有弹窗,很难去找到对应函数体
所以特地花了很多事件去整理了下MFC程序应该如何去逆向
这篇文章前面会讲理论,后边会结合实际逆向分析例子。
MFC消息映射机制在 Windows 编程中,窗口与系统、用户交互主要是通过消息传递的。每个窗口都有一个消息队列,系统通过向消息队列发送消息来通知窗口事件(如鼠标点击、键盘输入、窗口重绘等)。MFC 消息映射机制使得处理这些消息变得更加结构化和便捷。
MFC 中,每个支持消息映射的类都必须使用 DECLARE_MESSAGE_MAP 宏(在类声明中)和 BEGIN_MESSAGE_MAP、END_MESSAGE_MAP 宏(在类实现中)来定义消息映射。
DECLARE_MESSAGE_MAP ...
Windows内核(16)——探究SSDT
Windows内核探究SSDTSSDT简介在Windows x86系统中,系统服务描述表(System Service Descriptor Table,简称SSDT)是一个核心数据结构,主要用于管理和调度系统调用(syscall)。SSDT在操作系统的内核模式下提供了一种机制,使得用户模式的应用程序能够请求内核模式服务,比如文件操作、进程管理、内存管理等。以下是SSDT的主要作用:
系统调用接口SSDT充当了用户模式应用程序与操作系统内核之间的桥梁。应用程序通过调用标准的Windows API(如ReadFile、WriteFile等),这些API最终会通过系统调用的方式进入内核模式。SSDT中包含了一组函数指针,这些指针指向具体的内核服务例程。每个系统调用在SSDT中都有对应的入口,通过这些入口可以找到实现该调用的内核函数。
系统调用号到函数指针的映射每个系统调用在SSDT中都有一个唯一的索引号(系统调用号)。当应用程序发出系统调用时,会使用该调用的系统调用号在SSDT中查找对应的内核服务例程的地址。然后,系统将控制权转移给这个地址处的服务例程来执行实际的操作。例如,通过sysc ...
Windows内核(15)——键盘Hook,调用门
Windwos内核通过IDT Hook键盘IRETD(Interrupt Return Double-word)是 x86 架构中的一条汇编指令,用于从中断或异常处理程序中返回到调用程序。
当一个中断或异常发生时,CPU 会将当前的 EFLAGS 寄存器、CS(代码段)寄存器和 EIP(指令指针)压入堆栈,并跳转到中断处理程序的入口地址。
当中断处理程序完成时,IRETD 指令会从堆栈中弹出这些值并恢复它们,返回到中断发生前的状态。
当你 Hook 一个中断函数时,通常会使用“裸函数”(Naked Function),这是因为中断处理程序具有特殊的要求,不允许编译器在函数的入口和退出时自动插入额外的代码。这些额外的代码可能包括保存和恢复寄存器、设置堆栈帧等常规操作。为了确保中断处理程序的行为符合预期,裸函数就显得非常重要。
12345678910111213141516__declspec(naked) void KeyboardProc(){ __asm{ pushad pushf } //写入代码 ...
Windows内核(14)——补笔记
Windows内核(补笔记)在高两G空间里面,FS段选择子经过变换后指向的是 _KPCR(系统内核数据结构)
在低两G空间里面,FS段选择子经过变换后指向的是_TEB
MmGetPhysicalAddress的作用: 用于将虚拟地址转换为物理地址。在Windows操作系统中,内核代码可以通过这个函数来获取对应于某个虚拟地址的物理地址。MmMapIoSpace的作用:于将物理地址范围映射到内核虚拟地址空间,从而使内核模式代码可以访问该物理地址范围。
完善交换内存的代码以及优化完成下面的代码:
以下代码存在问题,就是如果被交换到磁盘,就有可能会映射失败
下面是改进的代码
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495NTSTATUS DriverEntry(IN PDRIVER ...
FPS矩阵原理
FPS矩阵原理参考文章: FPS通用的方框透视公式的原理_fps透视原理-CSDN博客
FPS游戏方框透视基本原理_fps 透视矩阵算法-CSDN博客
之前我们做的非矩阵画线,位置不准确,还很难进行缩放
但是下图是矩阵的效果,看上去就非常的好
游戏坐标转换原理:游戏中通过建模完成的3D物体要想在2D屏幕上显示出来需要进行坐标的转换。
具体过程看 FPS游戏方框透视基本原理_fps 透视矩阵算法-CSDN博客 吧(看得我十分头大,不过我们只需要大概了解即可)
按照上面的原理,我们只要找到人物在世界坐标系中的坐标 (x1,y1,z1) ,就可以在屏幕上画出人物边框
第一步:世界坐标 -> 裁剪坐标
z1后面的那个1是w,为了兼容4*4矩阵
12345678910X = a11*x1 + a12*y1 + a13*z1 + a14 Y = a21*x1 + a22*y1 + a23*z1 + a24 Z = a31*x1 + a32*y1 + a33*z1 + a34 W = a41*x1 + a42*y1 + a43*z1 + a44 //(x, y, z) ...
非矩阵方法画线
非矩阵画线先说好,因为是是通过数学大致推出坐标,大致画线,所以实际上并不准确,但是作为新手学习下原理也是不错的
代码已经能跑了,当然不是很完美,但是简单定位是没问题了,但是因为精度实在太差……..我去学矩阵了😂
Dll入口函数首先在Dll入口函数创建线程,Sleep看自己电脑是否受得了
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "pch.h"#include "周围对象.h"#include "绘制.h"DWORD WINAPI ThreadFunc(LPVOID lpParam){ HWND hwnd = FindWindowA(NULL, "Counter-Strike"); 绘制 FPS绘制(hwnd); while (TRUE) { ...
CE指针扫描操作
昨天朋友发来一个三国小游戏,让我找金币的基地址
本以为会一帆风顺,结果还是花了好长时间,才找到一个地址,改动会使得金币变化
费劲千辛万苦,终于找到了这个地址,但是很遗憾,这玩意是黑色的,也就是说明这个地址是会变动的,属于堆栈地址。很明显,这个就要去找指针。
凭借我三脚猫的功夫,之前在CE教程学的,我觉得徒手找
首先我去查找是啥玩意改变了这个地址
成功找到这三个值,点进去发现,它们改的地址都是
于是我非常自信的去搜索是哪一块内存存了这个0x351F15C
扫出来有俩,然后再分别去找究竟是什么地址访问了这个地址
果然出了意外,击杀完怪物,迟迟等不到有地址访问
后来我仔细琢磨了一下,很有可能是因为(举个例子)
1234mov [edi+0x55],ecxadd edi,0x55mov [edi],ecx
这玩意,导致我搜索访问不到
所以这回我们就要启用CE的一个强大功能,就是
点开后,点击显示高级选项,我觉得为了防止有些游戏偏移不对齐,所以我选择把 地址必须是32位(4字节)对齐取消掉,以免有些地址找不到,然后最大级别改为8(也是为了防止极端情况吧),小游戏应该够了
然后 ...