《灰帽黑客:攻守道》
文章平均质量分 82
黑客与安全专家的编程之道
微软技术分享
王瑞、LyShark 品牌创始人、微软C++领域最有价值专家、《灰帽黑客:攻守道》作者,CSDN博客专家、领军人物、2022年度博客新星Top5、2023年度博客之星Top24、北京赛道Top11、研究生赛道Top5,致力于研究Microsoft技术在信息安全领域的最佳实践,并在业内拥有超过10余年的行业研究经验。
展开
-
Win32汇编:算术与伪指令
每种汇编语言都有进行操作数移位的指令,移位和循环移位指令在控制硬件设备,加密数据,以及实现高速图形运算时特别有用,移位指令也是汇编语言中最具特征的指令集,移位(Shifting)的含义是在操作数内向左或向右移动数据位,Intel处理器提供了多种移位指令,具体如下表所示。原创 2019-07-05 09:16:00 · 10697 阅读 · 2 评论 -
Win32汇编:实现PE结构解析器
PE格式是Windows系统下最常用的可执行文件格式,有些应用必须建立在了解PE文件格式的基础之上,如可执行文件的加密与解密,文件型病毒的查杀等,熟练掌握PE文件结构,有助于软件的分析.原创 2021-06-16 16:46:00 · 7241 阅读 · 0 评论 -
Win32汇编:字符串浮点数运算过程
该笔记重点复习字符串操作指令的一些使用技巧,以及浮点数运算相关内容,浮点数运算也是非常重要的知识点,在分析大型游戏时经常会碰到针对浮点数的运算指令,例如枪械换弹动作,人物跳跃时的状态,都属于浮点数运算范围,也就一定会用到浮点数寄存器栈,浮点指令集主要可分为,传送指令,算数指令,比较指令,超越指令,常量加载指令等。原创 2020-09-04 09:38:00 · 8602 阅读 · 0 评论 -
Win32汇编:过程与宏调用
在计算机领域,堆栈是一个不容忽视的概念,堆栈是一种后进先出(LIFO,Last-In,First-Out)的数据结构,这是因为最后压入堆栈的值总是最先被取出,而新数值在执行PUSH压栈时总是被加到堆栈的最顶端,数据也总是从堆栈的最顶端被取出,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场.原创 2019-07-05 09:17:00 · 5178 阅读 · 0 评论 -
Win32汇编:各种语句的构造方式
这次复习的重点就是高级语言,各种语句的底层实现逻辑,我们手工的来实现一些常用的表达式,逐级递增难度,本文中所仿写的汇编流程,风格,参考自VS2013编译器的Debug实现,由于不是研究编译特性的文章,故此处不考虑编译器对代码实施的各种优化措施,只注重C语言代码的汇编化。原创 2020-08-30 12:45:00 · 7314 阅读 · 0 评论 -
Win32汇编:仿写多态与虚函数
多态性是面向对象的重要组成部分,利用多态可以设计和实现易于扩展的程序,所谓多态就是一个类函数有多重形态,具有不同功能的函数可以用同一个函数名,实现使用一个函数名调用不同内容的函数,从而返回不同的结果,这就是多态性,多态离不开虚函数的支撑,以下案例本人将深度分析虚函数实现机制,并通过汇编实现虚函数机制。原创 2022-02-20 16:02:00 · 7021 阅读 · 0 评论 -
Win32汇编:基础知识入门
汇编语言是所有程序设计语言中最古老的,它与计算机机器语言最为接近,通过汇编语言可以直接访问计算机的硬件,能够直接与CPU对话,可以说汇编语言是所有编程语言中语法格式最自由的,但自由的代价就是需要了解计算机体系结构和操作系统的大量细节,每编写一段程序都需要考虑各种硬件的状态,从而导致使用汇编写程序效率非常低.原创 2019-07-05 09:15:00 · 5992 阅读 · 0 评论 -
Win32汇编:实现远程DLL注入器
注入器的主要功能是将一个动态链接库(DLL)加载到目标进程的地址空间中,使其在目标进程中运行。汇编语言编写的Windows平台下的DLL注入器的原理是通过调用Windows API来将指定的DLL加载到目标进程的地址空间中,并执行DLL中的代码。原创 2020-06-04 11:46:00 · 7333 阅读 · 0 评论 -
Win32汇编:数组与标志位测试总结
本次复习重点在于理解数组中常用的寻址方式以及标志位的测试命令,数组寻址包括了,直接寻址,间接寻址,立即数寻址,基址变址寻址,比例因子寻址,通过ESI内存寻址,通过ESP堆栈寻址,指针寻址。原创 2020-08-29 12:12:00 · 8160 阅读 · 0 评论 -
Win32汇编:算数运算指令总结
在汇编语言中,运算符涵盖了多种操作,包括基本的运算符,加减乘除等,另外包括了移位运算等,移位又分为,算数移位,逻辑移位,循环移位,双精度移位等。汇编语言中的运算符和移位运算提供了灵活的操作,但在使用时需要谨慎考虑符号位、标志寄存器和溢出等问题。不同的指令集和架构可能提供略有不同的指令和功能。原创 2020-08-27 19:09:00 · 7931 阅读 · 0 评论 -
Win32汇编:常用系统API函数
熟练掌握Win32 API函数的参数传递,是软件逆向的基础,本章节内容将使用MASM汇编器,逐个编译这些源程序,你可以通过使用一些调试工具,这里推荐OllyDBG来附加编译后的可执行文件,进行逐个分析,观察二进制程序逆向后的一些变化,总结吸收经验,为以后的二进制逆向,漏洞挖掘打基础.原创 2019-07-05 09:18:00 · 11203 阅读 · 0 评论 -
Win32汇编:实现PE结构解析器
PE格式是Windows系统下最常用的可执行文件格式,有些应用必须建立在了解PE文件格式的基础之上,如可执行文件的加密与解密,文件型病毒的查杀等,熟练掌握PE文件结构,有助于软件的分析.在操作系统中,可执行的代码在被最终装载进内存执行之前是以文件的方式存放在磁盘中的,早期DOS操作系统中,是以.com文件的格式存储的,com文件限制了只能使用代码段,堆栈寻址也被限制在了64KB的段中,这样极大的限制了软件的发展.原创 2019-07-05 09:20:00 · 10678 阅读 · 0 评论 -
Win32汇编:字符串操作指令
在汇编语言中,字符串操作是常见的任务之一,针对不同数据大小单位(Byte、Word、DWord),汇编提供了一系列移动、比较、扫描、储存和载入字符串的指令。这些指令的操作目标通常是由寄存器或者内存中的地址指定的一段连续的数据。这些字符串操作指令提供了汇编语言中处理字符串的基本工具,通过合理的组合和使用,可以实现字符串的拷贝、比较、扫描、储存和载入等常见操作。在具体应用中,程序员需要注意数据大小单位以及源、目标地址的设置。原创 2019-07-05 09:18:00 · 5589 阅读 · 0 评论 -
5.10 Windows驱动开发:摘除InlineHook内核钩子
在笔者上一篇文章`《内核层InlineHook挂钩函数》`中介绍了通过替换`函数`头部代码的方式实现`Hook`挂钩,对于ARK工具来说实现扫描与摘除`InlineHook`钩子也是最基本的功能,此类功能的实现一般可在应用层进行,而驱动层只需要保留一个`读写字节`的函数即可,将复杂的流程放在应用层实现是一个非常明智的选择,与`《内核实现进程反汇编》`中所使用的读写驱动基本一致,本篇文章中的驱动只保留两个功能,控制信号`IOCTL_GET_CUR_CODE`用于读取函数的前16个字节的内存,信号`IOCTL_原创 2023-12-08 21:50:16 · 6959 阅读 · 6 评论 -
5.9 Windows驱动开发:内核InlineHook挂钩技术
内核挂钩的原理是一种劫持系统函数调用的技术,用于在运行时对系统函数进行修改或者监控。其基本思想是先获取要被劫持的函数的地址,然后将该函数的前15个字节的指令保存下来,接着将自己的代理函数地址写入到原始函数上,这样当API被调用时,就会默认转向到自己的代理函数上执行,从而实现函数的劫持。原创 2023-12-07 21:39:03 · 7018 阅读 · 8 评论 -
8.4 Windows驱动开发:文件微过滤驱动入门
MiniFilter 微过滤驱动是相对于`SFilter`传统过滤驱动而言的,传统文件过滤驱动相对来说较为复杂,且接口不清晰并不符合快速开发的需求,为了解决复杂的开发问题,微过滤驱动就此诞生,微过滤驱动在编写时更简单,多数`IRP`操作都由过滤管理器`(FilterManager或Fltmgr)`所接管,因为有了兼容层,所以在开发中不需要考虑底层`IRP`如何派发,更无需要考虑兼容性问题,用户只需要编写对应的回调函数处理请求即可,这极大的提高了文件过滤驱动的开发效率。原创 2023-12-01 16:43:10 · 10388 阅读 · 24 评论 -
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动
要想实现`驱动屏蔽`其原理很简单,通过`ImageInfo->ImageBase`得到镜像基地址,然后调用`GetDriverEntryByImageBase`函数来得到程序的入口地址,找NT头的`OptionalHeader`节点,该节点里面就是被加载驱动入口,通过汇编在驱动头部写入`ret`返回指令,即可实现屏蔽加载特定驱动文件。原创 2023-12-01 16:32:45 · 4340 阅读 · 10 评论 -
7.3 Windows驱动开发:内核监视LoadImage映像回调
PsSetLoadImageNotifyRoutine和PsRemoveLoadImageNotifyRoutine是Windows操作系统提供的两个内核API函数,用于注册和取消注册LoadImage映像的回调函数。LoadImage映像回调函数是一种内核回调函数,它可以用于监视和拦截系统中的模块加载事件,例如进程启动时加载的DLL、驱动程序等。当有新的模块被加载时,操作系统会调用注册的LoadImage映像回调函数,并将加载模块的相关信息传递给回调函数。原创 2023-12-01 16:30:18 · 9909 阅读 · 3 评论 -
7.2 Windows驱动开发:内核注册并监控对象回调
ObRegisterCallbacks是Windows操作系统提供的一个内核API函数,它允许开发者注册一个回调函数,用于监控对象的创建、打开、关闭和删除等事件。对象可以是文件、目录、进程、线程、注册表键等等。当操作系统创建、打开、关闭或删除一个对象时,它会触发注册的回调函数,然后在回调函数中调用开发者定义的代码。开发者可以在回调函数中执行自定义的逻辑,例如记录日志、过滤敏感数据、或者阻止某些操作。原创 2023-12-01 16:28:16 · 4140 阅读 · 0 评论 -
7.6 Windows驱动开发:内核监控FileObject文件回调
ObRegisterCallbacks是Windows操作系统提供的一个内核API函数,用于注册对象回调函数。对象回调函数是一种内核回调函数,可以用于监视和拦截系统中的对象操作,例如文件、进程、线程等。在文件系统中,FileObject是内核中表示文件对象的结构体,包含了文件的相关信息,例如文件名、文件句柄、访问权限等。当操作系统执行文件操作时,会使用FileObject结构体来表示文件对象。原创 2023-12-01 15:48:05 · 10041 阅读 · 0 评论 -
6.9 Windows驱动开发:内核枚举进线程ObCall回调
进程与线程ObCall回调是Windows操作系统提供的一种机制,它允许开发者在进程或线程发生创建、销毁、访问、修改等事件时拦截并处理这些事件。进程与线程ObCall回调是通过操作系统提供的回调机制来实现的。原创 2023-12-01 15:43:25 · 4252 阅读 · 1 评论 -
6.8 Windows驱动开发:内核枚举Registry注册表回调
Registry注册表回调是Windows操作系统提供的一种机制,它允许开发者在注册表发生变化时拦截并修改注册表的操作。Registry注册表回调是通过操作系统提供的注册表回调机制来实现的。原创 2023-12-01 15:39:19 · 10081 阅读 · 1 评论 -
6.7 Windows驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章`《内核特征码搜索函数封装》`中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核`LoadImage`映像回调,在Win64环境下我们可以设置一个`LoadImage`映像加载通告回调,当有新驱动或者DLL被加载时,回调函数就会被调用从而执行我们自己的回调例程,映像回调也存储在数组里,枚举时从数组中读取值之后,需要进行位运算解密得到地址。原创 2023-12-01 15:30:16 · 4201 阅读 · 0 评论 -
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动
Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的`sfilter`文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使用过滤管理器`FilterManager`提供接口,由于提供了管理结构以及一系列管理API函数,所以枚举过滤驱动将变得十分容易。原创 2023-12-01 15:27:56 · 10437 阅读 · 0 评论 -
6.5 Windows驱动开发:内核枚举PspCidTable句柄表
在 Windows 操作系统内核中,PspCidTable 通常是与进程(Process)管理相关的数据结构之一。它与进程的标识和管理有关,每个进程都有一个唯一的标识符,称为进程 ID(PID)。与之相关的是客户端 ID,它是一个结构,其中包含唯一标识进程的信息。这样的标识符在进程管理、线程管理和内核对象的创建等方面都起到关键作用。原创 2023-12-01 15:24:44 · 4235 阅读 · 0 评论 -
6.4 Windows驱动开发:内核枚举DpcTimer定时器
DPC(Deferred Procedure Call)是一种异步执行的机制。它允许内核代码在不中断当前进程的情况下,延迟执行一些工作。DPC的执行是由内核定时器触发的。内核定时器是一种特殊的内核对象,用于定时执行某个特定的操作。在DPC的上下文中,内核可以安全地访问任何内核数据结构,而不会引起死锁或其他问题。原创 2023-11-26 20:03:22 · 10333 阅读 · 1 评论 -
6.3 Windows驱动开发:内核枚举IoTimer定时器
内核I/O定时器(Kernel I/O Timer)是Windows内核中的一个对象,它允许内核或驱动程序设置一个定时器,以便在指定的时间间隔内调用一个回调函数。通常,内核I/O定时器用于周期性地执行某个任务,例如检查驱动程序的状态、收集性能数据等。今天继续分享内核枚举系列知识,这次我们来学习如何通过代码的方式枚举内核`IoTimer`定时器,内核定时器其实就是在内核中实现的时钟,该定时器的枚举非常简单,因为在`IoInitializeTimer`初始化部分就可以找到`IopTimerQueueHead原创 2023-11-26 19:56:26 · 4396 阅读 · 0 评论 -
6.2 Windows驱动开发:内核枚举SSSDT表基址
在Windows内核中,SSSDT(System Service Shadow Descriptor Table)是SSDT(System Service Descriptor Table)的一种变种,其主要用途是提供Windows系统对系统服务调用的阴影拷贝。SSSDT表存储了系统调用的函数地址,类似于SSDT表,但在某些情况下,Windows系统会使用SSSDT表来对系统服务进行引导和调用。SSSDT表的存在是为了加强系统的安全性和稳定性。通过使用SSSDT表,操作系统可以在运行时检查系统服务的合法原创 2023-11-26 19:53:26 · 10243 阅读 · 0 评论 -
6.1 Windows驱动开发:内核枚举SSDT表基址
SSDT表(System Service Descriptor Table)是Windows操作系统内核中的关键组成部分,负责存储系统服务调用的相关信息。具体而言,SSDT表包含了系统调用的函数地址以及其他与系统服务相关的信息。每个系统调用对应SSDT表中的一个表项,其中存储了相应系统服务的函数地址。SSDT表在64位和32位系统上可能有不同的结构,但通常以数组形式存在。对于系统调用的监控、分析或修改等高级操作,常需要内核枚举SSDT表基址。这一操作通常通过内核模块实现,涉及技术手段如逆向工程和Hook原创 2023-11-26 19:47:11 · 4219 阅读 · 1 评论 -
5.7 Windows驱动开发:取进程模块函数地址
在笔者上一篇文章`《内核取应用层模块基地址》`中简单为大家介绍了如何通过遍历`PLIST_ENTRY32`链表的方式获取到`32位`应用程序中特定模块的基地址,由于是入门系列所以并没有封装实现太过于通用的获取函数,本章将继续延申这个话题,并依次实现通用版`GetUserModuleBaseAddress()`取远程进程中指定模块的基址和`GetModuleExportAddress()`取远程进程中特定模块中的函数地址,此类功能也是各类安全工具中常用的代码片段。原创 2023-11-25 21:26:27 · 10110 阅读 · 2 评论 -
7.5 Windows驱动开发:监控Register注册表回调
在笔者前一篇文章`《内核枚举Registry注册表回调》`中实现了对注册表的枚举,本章将实现对注册表的监控,不同于32位系统在64位系统中,微软为我们提供了两个针对注册表的专用内核监控函数,通过这两个函数可以在不劫持内核API的前提下实现对注册表增加,删除,创建等事件的有效监控,注册表监视通常会通过`CmRegisterCallback`创建监控事件并传入自己的回调函数,与该创建对应的是`CmUnRegisterCallback`当注册表监控结束后可用于注销回调。原创 2023-11-24 18:43:26 · 10138 阅读 · 1 评论 -
5.1 Windows驱动开发:判断驱动加载状态
在驱动开发中我们有时需要得到驱动自身是否被加载成功的状态,这个功能看似没啥用实际上在某些特殊场景中还是需要的,如下代码实现了判断当前驱动是否加载成功,如果加载成功, 则输出该驱动的详细路径信息。该功能实现的核心函数是`NtQuerySystemInformation`这是一个微软未公开的函数,也没有文档化,不过我们仍然可以通过动态指针的方式调用到它,该函数可以查询到很多系统信息状态,首先需要定义一个指针。原创 2023-11-24 18:39:38 · 4628 阅读 · 0 评论 -
3.2 Windows驱动开发:内核CR3切换读写内存
CR3是一种控制寄存器,它是CPU中的一个专用寄存器,用于存储当前进程的页目录表的物理地址。在x86体系结构中,虚拟地址的翻译过程需要借助页表来完成。页表是由页目录表和页表组成的,页目录表存储了页表的物理地址,而页表存储了实际的物理页框地址。因此,页目录表的物理地址是虚拟地址翻译的关键之一。在操作系统中,每个进程都有自己的地址空间,地址空间中包含了进程的代码、数据和堆栈等信息。为了实现进程间的隔离和保护,操作系统会为每个进程分配独立的地址空间。在这个过程中,操作系统会将每个进程的页目录表的物理地址存储在原创 2023-11-24 18:32:11 · 10532 阅读 · 0 评论 -
9.9 Windows驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章`《内核RIP劫持实现DLL注入》`介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过`NtCreateThreadEx`这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,`NtCreateThreadEx`函数最终会调用`ZwCreateThread`,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。原创 2023-11-23 10:23:57 · 10328 阅读 · 2 评论 -
9.4 Windows驱动开发:内核PE结构VA与FOA转换
本章将继续探索内核中解析PE文件的相关内容,PE文件中FOA与VA,RVA之间的转换也是很重要的,所谓的FOA是文件中的地址,VA则是内存装入后的虚拟地址,RVA是内存基址与当前地址的相对偏移,本章还是需要用到中所封装的映射函数,在映射后对其PE格式进行相应的解析,并实现转换函数。首先先来演示一下内存VA地址与FOA地址互相转换的方式,通过使用WinHEX打开一个二进制文件,打开后我们只需要关注如下蓝色注释为映像建议装入基址,黄色注释为映像装入后的RVA偏移。通过上方的截图结合PE文件结构图我们可得知。原创 2023-11-22 14:34:51 · 10229 阅读 · 0 评论 -
9.3 Windows驱动开发:内核解析PE结构节表
在笔者上一篇文章`《内核解析PE结构导出表》`介绍了如何解析内存导出表结构,本章将继续延申实现解析PE结构的PE头,PE节表等数据,总体而言内核中解析PE结构与应用层没什么不同,在上一篇文章中`LyShark`封装实现了`KernelMapFile()`内存映射函数,在之后的章节中这个函数会被多次用到,为了减少代码冗余,后期文章只列出重要部分,读者可以自行去前面的文章中寻找特定的片段。PE结构(Portable Executable Structure)是Windows操作系统用于执行可执行文件和动态链原创 2023-11-22 14:30:06 · 4411 阅读 · 1 评论 -
9.2 Windows驱动开发:内核解析PE结构导出表
在笔者的上一篇文章`《内核特征码扫描PE代码段》`中`LyShark`带大家通过封装好的`LySharkToolsUtilKernelBase`函数实现了动态获取内核模块基址,并通过`ntimage.h`头文件中提供的系列函数解析了指定内核模块的`PE节表`参数,本章将继续延申这个话题,实现对PE文件导出表的解析任务,导出表无法动态获取,解析导出表则必须读入内核模块到内存才可继续解析,所以我们需要分两步走,首先读入内核磁盘文件到内存,然后再通过`ntimage.h`中的系列函数解析即可。原创 2023-11-22 14:27:15 · 10126 阅读 · 0 评论 -
5.4 Windows驱动开发:内核通过PEB取进程参数
PEB结构`(Process Envirorment Block Structure)`其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一个特有的PEB结构,通过附加进程并遍历这段结构即可得到非常多的有用信息。在应用层下,如果想要得到PEB的基地址只需要取`fs:[0x30]`即可,TEB线程环境块则是`fs:[0x18]`,如果在内核层想要得到应用层进程的PEB信息我们需要调用特定的内核函数来获取。原创 2023-11-21 20:00:42 · 6784 阅读 · 0 评论 -
5.3 Windows驱动开发:内核取应用层模块基址
的基址,当在某些场景中,我们不仅需要得到内核的基地址,也需要得到特定进程内某个模块的基地址,显然上篇文章中的方法是做不到的,本篇文章将实现内核层读取32位应用层中特定进程模块基址功能。等结构体定义依然需要保留,此处只保留核心代码,定义部分请看前一篇文章,自定义读取模块基址核心代码如下,调用。如上就是如何得到特定模块基址的方法,如下是入口函数的调用方法,首先通过传入。中我们通过调用内核API函数获取到了内核进程。结构该结构可通过内核函数。这个PID号,得到进程。原创 2023-11-21 19:58:31 · 4292 阅读 · 0 评论 -
5.2 Windows驱动开发:内核取KERNEL模块基址
模块是程序加载时被动态装载的,模块在装载后其存在于内存中同样存在一个内存基址,当我们需要操作这个模块时,通常第一步就是要得到该模块的内存基址,模块分为用户模块和内核模块,这里的用户模块指的是应用层进程运行后加载的模块,内核模块指的是内核中特定模块地址,本篇文章将实现一个获取驱动。操作系统的一个重要内核程序,里面存储了大量的二进制内核代码,用于调度系统时使用,也是操作系统启动后第一个被加载的程序,通常该进程在任务管理器中显示为。的基地址以及长度,此功能是驱动开发中尤其是安全软件开发中必不可少的一个功能。原创 2023-11-21 19:56:21 · 6708 阅读 · 0 评论