Windows版本和检测
前天在研究PEB位置时发现自XPSP2之后就开始随机变动位置了,而不是想以前那样固定在0X7FFDF000上了.我突然想起以前转发的一篇文章<非API函数检测操作系统类型>,此文中就是将PEB位置是否为OX7FFDF000作为区分WINNT和WIN9X的标志的.现在PEB的位置也不固定了,看来判断条件得修正一下了.
Windows版本号分为操作系统版本号和服务包(Service Packet)版本号.其中操作系统版本号分为:主版本号(MajorVersion)、次版本号(MinorVersion)和内部版本号(BuildNumber);服务包号分为主服务包号和内部服务包号.
Windows内部有一组变量专门用来保存版本号的信息,在调用MmCreatePeb创建每个进程的PEB时会将这些信息的大部分拷贝至PEB中.而我们使用GetVersionEx这样的API函数就是从PEB中读取数据的.由于在WinNt下这些版本信息在PEB中的位置没有改变,于是在用户态下,我们可以直接读取PEB中的版本信息,而绕过API了.
下表是XPSP3下版本信息分别在系统中存放的位置:
|
内核变量 |
PEB成员 |
OS主版本号 |
NtMajorVersion |
+0x 0a 4 OSMajorVersion : Uint4B |
OS次版本号 |
NtMinorVersion |
+0x 0a 8 OSMinorVersion : Uint4B |
OS内部版本号 |
NtBuildNumber |
+0x 0ac OSBuildNumber : Uint2B |
主服务包号 |
CmNtCSDVersion |
+0x0ae OSCSDVersion : Uint2B |
内部服务包号 |
CmNtSpBuildNumber |
无 |
其他 |
NtBuildLab[] |
无 |
根据上面的叙述,下面就是我对<非API函数检测操作系统类型>一文的代码修正,用c内嵌汇编完成:
_asm { MOV EAX, FS:[18H] ;TEB MOV EBX, FS:[30H] ;PEB MOV ECX, EBX AND EAX, 7FF00000H CMP EAX, 7FF00000H JNZ Win9x AND EBX, 7FF00000H CMP EBX, 7FF00000H JNZ WIN9x
//WIN2K,WINXP,WIN2K3 MOV EAX, [ECX + 0A 4H] ;MajorVersion MOV EBX, [ECX + 0A 8H] ;MinorVersion CMP EAX, 5 JB OVER CMP EBX, 0 JNZ VER1 //5.0 = WIN2K JMP OVER VER1: CMP EBX, 1 JNZ VER2 //5.1 = WINXP JMP OVER VER2: CMP EBX, 2 JNZ OVER //5.2= WIN2K3
WIN9x: MOV EDX, 00530000H MOV EAX, FS:[18H] MOV EBX, [EAX + 58H] MOV ECX, [EAX + 7CH] MOV EAX, [EAX + 54H] CMP EBX, EDX JNZ VER3 //WIN95 JMP OVER VER3: CMP EAX, EDX JNZ VER4 //WIN98 JMP OVER VER4: CMP ECX, EDX JNZ OVER //WINME OVER: } |
上面是根据主次版本号来区别操作系统版本的,由于在内核中仅有NtBuildNumber从ntoskrnl.exe中导出,而且内部本版号和操作系统版本也有严格的对照关系,如下图:
于是我们在内核中可以使用内部版本号来分辨操作系统版本了.
参考文献:
1. http://en.wikipedia.org/wiki/Windows_NT