分析不同操作系统的线程环境块(TEB --- 也叫做线程信息块 TIB),我们可以看到这个结构的附加数据。对于非NT内核的系统,这些附加数据没有逻辑结构或者长度定义,而对于NT内核的系统他们保存了进程环境块(PEB)的信息。确定非NT内核系统中这些数据意义的唯一方法,就是在不同的操作系统中调试同一个程序。
程序启动前TEB便被初始化并且含有线程重定位数据指针。TEB结构在所有的操作系统中都是有效的。它的大小是34字节。TEB地址可以利用 FS寄存器配合下面的方法来获取:
assume fs:nothing
mov eax, fs:[18h]
TEB最后的内容为指向进程数据的指针。在NT内核系统中,这个值指向进程环境块
在每个非NT内核系统中附加数据块没有逻辑结构和具体定义(译注:这里好像应该是NT内核结构)。在Windows NT,2000,XP和2003,这些数据如下:
NT_TEB_ADDON struct
LastErrorValue DWORD ? ; 00h (34h TEB)
LastStatusValue DWORD ? ; 04h (38h TEB)
CountOwnedLocks DWORD ? ; 08h (3Ch TEB)
HardErrorsMode DWORD ? ; 0Ch (40h TEB)
NT_TEB_ADDON ends
Windows 95, 98, ME 没有这些数据结构。附加数据完全很混乱!
NT内核的系统把进程相关数据存储在进程环境块中。这个结构的地址可以通过操作 FS寄存器来获取:
assume fs:nothing
mov eax, fs:[30h]
EAX寄存器中便是PEB基地址。
操作系统信息被存储在PEB结构中:
OSMajorVersion DWORD ? ; A4h <=4->NT / 5->2K/XP/2K3
OSMinorVersion DWORD ? ; A8h 0->2K / 1->XP / 2->2K3
Windows NT, 2000, XP and 2003采用固定数据存储PEB和TEB。PEB总是被存放在7FFDF000h,TEB总是从7FFDE000h开始。知道了这2个固定数据,就可以检测出来操作系统类型。
如果仔细看一下NT TEB附加数据,可以发现入口处的LastErrorValue。几乎所有跟GetLastError[1]有关系的API都要返回一个错误值。可以采用一些技巧来利用SetLastError[1] 返回的这个Error值,为了使用这个API并且检测TEB后面的内存,下面列出来LastErrorValue 的位置:
Windows 95 - TEB-base + 60h
Windows 98 - TEB-base + 60h
Windows ME - TEB-base + 74h
对于非NT内核的系统, EBX初始为00530000h。并且这个值可以从附加数据中查出来 - 与LastErrorValue非常近。为了分析这个数据,下面列出来具体位置:
Windows 95 - TEB-base + 58h
Windows 98 - TEB-base + 54h
Windows ME - TEB-base + 7Ch
.const
;-- return values from OS_GetOS
OS_UNKNOWN equ -1
OS_WIN95 equ 1
OS_WIN98 equ 2
OS_WINME equ 3
OS_WINNT equ 4
OS_WIN2K equ 5
OS_WINXP equ 6
OS_WIN2K3 equ 7
.code
OS_GetOS proc
local _theReturnValue: DWORD
pushad ; store all registers
mov _theReturnValue,OS_UNKNOWN
assume fs:nothing
mov ebx, fs:[18h] ; get self pointer from TEB
mov eax, fs:[30h] ; get pointer to PEB / database
.if eax==7FFDF000h && ebx==7FFDE000h ; WinNT based
mov ebx,[ eax+0A8h] ; get OSMinorVersion
mov eax,[ eax+0A4h] ; get OSMajorVersion
.if eax==5 && ebx==0 ; is it Windows 2000?
mov _theReturnValue,OS_WIN2K
.elseif eax==5 && ebx==1 ; is it Windows XP?
mov _theReturnValue,OS_WINXP
.elseif eax==5 && ebx==2 ; is it Windows 2003?
mov _theReturnValue,OS_WIN2K3
.elseif eax<=4 ; is it Windows NT?
mov _theReturnValue,OS_WINNT
.endif
.else ; Win9X based
mov edx,00530000h ; the magic value to search
mov eax, fs:[18h] ; get the TEB base address
mov ebx,[ eax+58h] ; TEB-base + 58h (W95)
mov ecx,[ eax+7Ch] ; TEB-base + 7Ch (WME)
mov eax,[ eax+54h] ; TEB-base + 54h (W98)
.if ebx== edx ; is it Windows 95?
mov _theReturnValue,OS_WIN95
.elseif eax== edx ; is it Windows 98?
mov _theReturnValue,OS_WIN98
.elseif ecx== edx ; is it Windows ME?
mov _theReturnValue,OS_WINME
.endif
.endif ; of base check NT/9X
popad ; restore all registers
mov eax,_theReturnValue
ret ; return to caller
OS_GetOS endp
程序启动前TEB便被初始化并且含有线程重定位数据指针。TEB结构在所有的操作系统中都是有效的。它的大小是34字节。TEB地址可以利用 FS寄存器配合下面的方法来获取:
assume fs:nothing
mov eax, fs:[18h]
TEB最后的内容为指向进程数据的指针。在NT内核系统中,这个值指向进程环境块
在每个非NT内核系统中附加数据块没有逻辑结构和具体定义(译注:这里好像应该是NT内核结构)。在Windows NT,2000,XP和2003,这些数据如下:
NT_TEB_ADDON struct
LastErrorValue DWORD ? ; 00h (34h TEB)
LastStatusValue DWORD ? ; 04h (38h TEB)
CountOwnedLocks DWORD ? ; 08h (3Ch TEB)
HardErrorsMode DWORD ? ; 0Ch (40h TEB)
NT_TEB_ADDON ends
Windows 95, 98, ME 没有这些数据结构。附加数据完全很混乱!
NT内核的系统把进程相关数据存储在进程环境块中。这个结构的地址可以通过操作 FS寄存器来获取:
assume fs:nothing
mov eax, fs:[30h]
EAX寄存器中便是PEB基地址。
操作系统信息被存储在PEB结构中:
OSMajorVersion DWORD ? ; A4h <=4->NT / 5->2K/XP/2K3
OSMinorVersion DWORD ? ; A8h 0->2K / 1->XP / 2->2K3
Windows NT, 2000, XP and 2003采用固定数据存储PEB和TEB。PEB总是被存放在7FFDF000h,TEB总是从7FFDE000h开始。知道了这2个固定数据,就可以检测出来操作系统类型。
如果仔细看一下NT TEB附加数据,可以发现入口处的LastErrorValue。几乎所有跟GetLastError[1]有关系的API都要返回一个错误值。可以采用一些技巧来利用SetLastError[1] 返回的这个Error值,为了使用这个API并且检测TEB后面的内存,下面列出来LastErrorValue 的位置:
Windows 95 - TEB-base + 60h
Windows 98 - TEB-base + 60h
Windows ME - TEB-base + 74h
对于非NT内核的系统, EBX初始为00530000h。并且这个值可以从附加数据中查出来 - 与LastErrorValue非常近。为了分析这个数据,下面列出来具体位置:
Windows 95 - TEB-base + 58h
Windows 98 - TEB-base + 54h
Windows ME - TEB-base + 7Ch
.const
;-- return values from OS_GetOS
OS_UNKNOWN equ -1
OS_WIN95 equ 1
OS_WIN98 equ 2
OS_WINME equ 3
OS_WINNT equ 4
OS_WIN2K equ 5
OS_WINXP equ 6
OS_WIN2K3 equ 7
.code
OS_GetOS proc
local _theReturnValue: DWORD
pushad ; store all registers
mov _theReturnValue,OS_UNKNOWN
assume fs:nothing
mov ebx, fs:[18h] ; get self pointer from TEB
mov eax, fs:[30h] ; get pointer to PEB / database
.if eax==7FFDF000h && ebx==7FFDE000h ; WinNT based
mov ebx,[ eax+0A8h] ; get OSMinorVersion
mov eax,[ eax+0A4h] ; get OSMajorVersion
.if eax==5 && ebx==0 ; is it Windows 2000?
mov _theReturnValue,OS_WIN2K
.elseif eax==5 && ebx==1 ; is it Windows XP?
mov _theReturnValue,OS_WINXP
.elseif eax==5 && ebx==2 ; is it Windows 2003?
mov _theReturnValue,OS_WIN2K3
.elseif eax<=4 ; is it Windows NT?
mov _theReturnValue,OS_WINNT
.endif
.else ; Win9X based
mov edx,00530000h ; the magic value to search
mov eax, fs:[18h] ; get the TEB base address
mov ebx,[ eax+58h] ; TEB-base + 58h (W95)
mov ecx,[ eax+7Ch] ; TEB-base + 7Ch (WME)
mov eax,[ eax+54h] ; TEB-base + 54h (W98)
.if ebx== edx ; is it Windows 95?
mov _theReturnValue,OS_WIN95
.elseif eax== edx ; is it Windows 98?
mov _theReturnValue,OS_WIN98
.elseif ecx== edx ; is it Windows ME?
mov _theReturnValue,OS_WINME
.endif
.endif ; of base check NT/9X
popad ; restore all registers
mov eax,_theReturnValue
ret ; return to caller
OS_GetOS endp