Windows Pwn 基本知识
函数调用约定
由于函数调用约定大多只和架构相关,因此和Linux相比没有太大的变化。
Windows程序保护
Windows下有部分程序保护更换了名字或者有一些细节发生了改变,我们来详细列举。
ASLR:与Linux相同,ASLR保护指的是地址随机化技术(Address Space Layout Randomization),这项技术将在程序启动时将DLL随机的加载到内存中的位置,这将缓解恶意程序的加载。ASLR技术自Windows 10开始已经在系统中被配置为默认启用。

- High Entropy VA:这个保护被称为高熵64位地址空间布局随机化,一旦开启,表示此程序的地址随机化的取值空间为64 bit,这会导致攻击者更难去推测随机化后的地址。
- Force Integrity:这个保护被称为强制签名保护,一旦开启,表示此程序加载时需要验证其中的签名,如果签名不正确,程序将会被阻止运行。
- Isolation:这个保护被称为隔离保护,一旦开启,表示此程序加载时将会在一个相对独立的隔离环境中被加载,从而阻止攻击者过度提升权限。
- NX/DEP/PAE:与Linux相同,NX保护指的是内存页不可运行(No-eXecute),这项技术是一项系统级的内存保护功能,使操作系统能够将一页或多页内存标记为不可执行,从而防止从该内存区域运行代码,以帮助防止利用缓冲区溢出。它帮助防止代码在数据页面(例如堆,栈和内存池)中运行,在Windows中常称为DEP(数据执行保护,即Data Execution Prevention),同时引入了一个新的机制被称为PAE(物理地址扩展,即Physical Address Extension),PAE是一项处理器功能,使x86处理器可以在部分Windows版本上访问4 GB以上的物理内存。在基于x86的系统上运行的某些32位版本的Windows Server可以使用PAE访问最多64 GB或128 GB的物理内存,具体取决于处理器的物理地址大小。使用PAE,操作系统将从两级线性地址转换转换为三级地址转换。两级线性地址转换将线性地址拆分为三个独立的字段索引到内存表中,三级地址转换将其拆分为四个独立的字段:一个2位的字段,两个9位的字段和一个12位的字段。PAE模式下的页表条目(PTE)和页目录条目(PDE)的大小从32位增加到64位。附加位允许操作系统PTE或PDE引用4 GB以上的物理内存。同时,PAE将允许在基于x64的系统上运行的32位Windows中启用DEP等功能。
- SEHOP:即结构化异常处理保护(Structured Exception Handling Overwrite Protection),这个保护能够防止攻击者利用结构化异常处理来进行进一步的利用。
- CFG:即控制流防护(Control Flow Guard),这项技术通过在间接跳转前插入校验代码,检查目标地址的有效性,进而可以阻止执行流跳转到预期之外的地点, 最终及时并有效的进行异常处理,避免引发相关的安全问题。
简单的说,就是在程序间接跳转之前,会判断这个将要跳转的地址是否是合法的。 - RFG:即返回地址防护(Return Flow Guard),这项技术会在每个函数头部将返回地址保存到fs:rsp,并在函数返回前将其与栈上返回地址进行比较,从而有效阻止了这些攻击方式。
- SafeSEH:即安全结构化异常处理(Safe Structured Exception Handlers),这项技术可以理解为一个白名单版的安全沙箱,它会事先为你定义一些异常处理程序,并基于此构造安全结构化异常处理表,程序正式运行后,安全结构化异常处理表之外的异常处理程序将会被阻止运行。
- GS:这个保护类似于Linux中的Canary保护,一旦开启,会在返回地址和BP之前压入一个额外的Security Cookie。系统会比较栈中的这个值和原先存放在.data中的值做一个比较。如果两者不吻合,说法栈中发生了溢出。
- Authenticode:签名保护。
- .NET:DLL混淆级保护。
新机制——结构化异常处理(SEH机制)
结构化异常处理是Windows操作系统上Microsoft对C/C++程序语言做的语法扩展,用于处理异常事件的程序控制结构。异常事件是指打断程序正常执行流程的不在期望之中的硬件、软件事件。硬件异常是CPU抛出的如“除0”、数值溢出等;软件异常是操作系统与程序通过RaiseException语句抛出的异常。Microsoft扩展了C语言的语法,用try-except与try-finally语句来处理异常。异常处理程序可以释放已经获取的资源、显示出错信息与程序内部状态供调试、从错误中恢复、尝试重新执行出错的代码或者关闭程序等等。一个try语句不能既有except,又有__finally。但try-except与try-finally语句可以嵌套使用。SEH相关的重要结构体
TIB结构体
TIB(Thread Information Block,线程信息块)是保存线程基本信息的数据结构,它存在于x86的机器上,它也被称为是Win32的TEB(Thread Environment Block,线程环境块)。TIB/TEB是操作系统为了保存每个线程的私有数据创建的,每个线程都有自己的TIB/TEB。
TEB结构位于Windows.h,内容如下:
TIB没有在Windows文档中说明,这里从Wine中可以看到结构如下: ```c // Code in https://source.winehq.org/source/include/winnt.h#2635typedef struct _TEB {PVOID Reserved1[12];PPEB ProcessEnvironmentBlock;PVOID Reserved2[399];BYTE Reserved3[1952];PVOID TlsSlots[64];BYTE Reserved4[8];PVOID Reserved5[26];PVOID ReservedForOle;PVOID Reserved6[4];PVOID TlsExpansionSlots;} TEB, *PTEB;
typedef struct _NT_TIB{ struct _EXCEPTION_REGISTRATION_RECORD Exceptionlist; // 指向当前线程的 SEH PVOID StackBase; // 当前线程所使用的栈的栈底 PVOID StackLimit; // 当前线程所使用的栈的栈顶 PVOID SubSystemTib; // 子系统 union { PVOID FiberData; ULONG Version; }; PVOID ArbitraryUserPointer; struct _NT_TIB Self; //指向TIB结构自身 } NT_TIB;
在这个结构中与异常处理有关的成员是指向_EXCEPTION_REGISTRATION_RECORD结构的Exceptionlist指针<a name="EzgPK"></a>#### _EXCEPTION_REGISTRATION_RECORD结构体该结构体主要用于描述线程异常处理句柄的地址,多个该结构的链表描述了多个线程异常处理过程的嵌套层次关系。<br />结构内容为:```c// Code in https://source.winehq.org/source/include/winnt.h#2623typedef struct _EXCEPTION_REGISTRATION_RECORD{struct _EXCEPTION_REGISTRATION_RECORD *Next; // 指向下一个结构的指针PEXCEPTION_ROUTINE Handler; // 当前异常处理回调函数的地址}EXCEPTION_REGISTRATION_RECORD;
新机制——导入表和导出表
Windows程序没有延迟绑定机制自然也就没有PLT/GOT表,但是Windows程序显然也是要调用所谓的库函数的,Windows下的函数库是DLL文件,类似于Unix下的libc文件,程序调用库函数需要借助的就是导入表和导出表了。
导入表是PE数据组织中的一个很重要的组成部分,它是为实现代码重用而设置的。通过分析导入表数据,可以获得诸如PE文件的指令中调用了多少外来函数,以及这些外来函数都存在于哪些动态链接库里等信息。Windows加载器在运行PE时会将导入表中声明的动态链接库一并加载到进程的地址空间,并修正指令代码中调用的函数地址。在数据目录中一共有四种类型的数据与导入表数据有关: 导入表、导入函数地址表、绑定导入表、延迟加载导入表。
程序中,导入表的地址通常位于.idata段

