【收藏】非API函数检测操作系统类型

简介: 【收藏】非API函数检测操作系统类型

Abstract

概要

Today nearly all programmers use the Advanced Programming Interface (API) to receive information's about given system values. By using this API's, we don't have to take care which operating system is currently available.

现在几乎所有的程序员都采用扩展程序接口(API)来获取操作系统信息。采用AIP函数,我们不需要关心当前所用的操作系统具体状况。

But sometimes it might be needful to avoid the usage of such API's. This situation is given during development of software protections in order to avoid importing functions which - eventually - will point a reverse engineer to a solution.

但是有时候不能采用API函数。比如开发保护软件时候,防止给逆向者透漏引用的函数信息信息。

This essay show up a way to detect the today given operating systems from Microsoft: Windows 95, 98, ME - the non NT-based operating systems - and Windows NT4, 2000, XP, 2003 - the NT-based operating systems.

这篇文章介绍了如何检测当前用到的操作系统,微软: Windows 95, 98, ME - 非NT内核,以及 Windows NT4,2000,XP -NT内核系统。

The shown source code is in Microsoft Assembler style (MASM [3]).

这里给出的代码是微软汇编体系(MASM[3])。

Keywords: Microsoft Operating Systems, Software Protection, Assembly Programming, System Internals

关键词: 微软操作系统,软件保护,汇编程序,系统内核

The author Thomas Kruse has his main research focus on operating-system independent code optimising and software-protection development. He is Associate Editor of Assembly-Journal and CodeBreakers-Journal.

本文作者作者 Thomas Kruse 致力于独立于操作系统的代码和软件保护系统的研究,也是Assembly-Journal 和 CodeBreakers-Journal的编辑。

 

I. Introduction 介绍

When analysing the structure of the Thread Environment Block (TEB - also known as Thread Information Block TIB) on different operating systems, we find additional data followed by this structure. This additional data seems to have - on non NT-based operating systems - no logical structure or length definition, where NT-based operating systems store the information inside the Process Environment Block (PEB). The only way to figure out the meaning of this data for non NT-based operating systems is to debug the same application on different operation systems[2].

分析不同操作系统的线程环境块(TEB --- 也叫做线程信息块 TIB),我们可以看到这个结构的附加数据。对于非NT内核的系统,这些附加数据没有逻辑结构或者长度定义,而对于NT内核的系统他们保存了进程环境块(PEB)的信息。确定非NT内核系统中这些数据意义的唯一方法,就是在不同的操作系统中调试同一个程序。

 

II. Application start 程序开始

There are many ways in detecting an operating system. It could be done by using the Windows API function GetVersionEx[1] and checking the version values returned in structure OSVERSIONINFO(EX)[1], or by accessing Register CS. Another way is analysing the registers during start up of an application. There are several rules for them on how operating systems prepare several registers before executing the first instruction:

有很多方法可以检测操作系统。可以采用Windows API函数 GetVersionEx[1],然后检查返回值或者检查CS寄存器。另外一个方法就是分析程序开始运行时候寄存器的值。在操作系统执行程序第一条指令以前,有很多处理寄存器的规则可以被利用。

Startup values for Windows 95/98/ME

Windows 95/98/ME启动值(译注:程序临执行以前)

EAX == Application Entry Point EAX == 程序入口

EBX == 00530000h, a fixed value 确定值

Startup values for Windows NT/2000/XP/2003    Windows NT/2000/XP/2003启动值

EAX == NULL

EBX == 7FFDF000h, pointer to (PEB)       EBX == 7FFDF000h, PEB指针

By knowing this rules we where able to check the operating system base during start up. But then we need to store the register values of EAX and EBX for further usage - or resolve them in a different way.

利用上面的特点,我们可以在启动时候确定操作系统类型。但是为了以后使用我们需要存储EAX,EBX或者也可以采用其他方法处理。

A. Thread Environment Block  A.线程环境块

The TEB is prepared during application start up and contain pointers to thread related additional data. The TEB structure is available on all operating systems. It's size is defined to 34h Bytes. The TEB address could be resolved by accessing the segment register FS in the following way:

程序启动前TEB便被初始化并且含有线程重定位数据指针。TEB结构在所有的操作系统中都是有效的。它的大小是34字节。TEB地址可以利用FS寄存器配合下面的方法来获取:

assume fs:nothing

mov eax,fs:[18h]

The register EAX will contain the base address of this block. The TEB contains - at address 18h inside the structure - a pointer to itself:

EAX寄存器含有TEB地址。TEB结构中第18h位为指向该TEB的指针。

pSelf DWORD ? ; 18h pointer to TEB/TIB

The last entry of TEB is the pointer to process database. On NT-based operating systems this value will point to the address of Process Environment Block (see Section II-C)

TEB最后的内容为指向进程数据的指针。在NT内核系统中,这个值指向进程环境块(参考 II-C 部分)

B. Additional data following TEB           B. TEB附加数据

Told in Section I, this additional data has no logical structure and differs on each non NT-based operating system. On Windows NT, 2000, XP and 2003 this additional Data is defined as follows:

第I部分说过,在每个非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 didn't have such a structure; the additional data is scrambled!

Windows 95, 98, ME 没有这些数据结构。附加数据完全很混乱!

C. Process Environment Block                 C. 进程环境块

Windows NT-based operating systems store process related data inside the Process Environment Block. The address of this structure is avaliable by accessing the segment register FS:

NT内核的系统把进程相关数据存储在进程环境块中。这个结构的地址可以通过操作FS寄存器来获取:

assume fs:nothing

mov eax,fs:[30h]

The register EAX will contain the base address of PEB.      EAX寄存器中便是PEB基地址。

pProcess DWORD ? ; 30h pointer to process database

The version information is stored inside the PEB structure:操作系统信息被存储在PEB结构中:

OSMajorVersion DWORD ? ; A4h <=4->NT / 5->2K/XP/2K3

OSMinorVersion DWORD ? ; A8h 0->2K / 1->XP / 2->2K3

D. NT-based definitions                         D. NT内核中的定义

Windows NT, 2000, XP and 2003 use fixed addresses to store PEB and TEB. The PEB is always stored at address 7FFDF000h and TEB is starting at 7FFDE000h. By knowing these two fixed values, it is possible to detect the operating system base.

Windows NT, 2000, XP and 2003采用固定数据存储PEB和TEB。PEB总是被存放在7FFDF000h,TEB总是从7FFDE000h开始。知道了这2个固定数据,就可以检测出来操作系统类型。

 

III. The Trick           III. 一些技巧

Section II-B has shown an add-on structure for NT-based operating systems. The data exists on non NT-based operating systems, too. But it is stored in a different way. To resolve correct memory positions - related to detect the operating system

第II-B 部分介绍了附加数据在NT内核系统中的存储。在非NT内核系统中,也存在这些数据。但是存储方式不一样。通过获取这些数据的位置,可以检测出来操作系统类型。

- we use a trick the analyse the additional data.

- 我们采用一些技巧来分析这些附加数据

If we take a closer look to the NT TEB ADDON structure shown in Section II-B, we see the entry LastErrorValue. Nearly all Windows API's will return an error value which is accessible via GetLastError[1]. In addition to this, it is possible to manipulate the LastErrorValue via SetLastError[1] API. By using this API and monitoring the memory area behind the TEB, the locations for the LastErrorValue are:

如果仔细看一下II-B部分说的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

Now we are able to detect Windows ME or Windows 95/98. First step to our solution, but not the final one. It is possible to detect a difference between Windows 95 and Windows 98.

现在就可以检测出来Windows ME 或者 Windows 95/98。这是解决问题的第一步,并没有到最后。有可能检测出来Windows 95 和 Windows 98之间的不同。

Section II showed the start up values and their rules. The start up value of EBX on non NT-based OS is 00530000h. Exactly this value will be found inside the additional data part - close to the now resolved LastErrorValue. By analysing it's location,

the result will be:

第II 部分说明了初始化值和他们的规律。对于非NT内核的系统,EBX初始为00530000h。并且这个值可以从附加数据中查出来 - 与LastErrorValue非常近。为了分析这个数据,下面列出来具体位置:

Windows 95 - TEB-base + 58h

Windows 98 - TEB-base + 54h

Windows ME - TEB-base + 7Ch

Now we are able to differ between each non NT-based operating system.

现在我们就可以区分没一个非NT内核的系统。

 

IV. Code creation            IV. 创建代码

Right now, we where able the detect the version information for each operating system. We want an operating system independent code, we need to structure the given information's. Also it should be possible to resolve the version information workflow independent. Section VI will show the complete solution in Assembler.

现在,我们可以检测每个操作系统的版本信息。为了让代码不依赖于操作系统,我们需要把需要的信息组织成一个结构。并且有必要让类型信息独立起来。第VI 部分将给出完全的汇编解决方案。

First of all, we get the base addresses of PEB and TEB and resolve the operating system base by analysing them:

首先,获取PEB和TEB的基地址,通过分析他们获取不同的操作系统信息。

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

.else

   ; Win9X based

.endif ; of base check NT/9X

The version information for NT-based operation systems is stored inside PEB. We only have to analyse the values of

NT内核的版本信息存储在PEB中。我们仅仅需要分析这些数据:

OSMajorVersion and OSMinorVersion:

mov ebx,[eax+0A8h] ; get OSMinorVersion

mov eax,[eax+0A4h] ; get OSMajorVersion

.if eax==5 && ebx==0 ; is it Windows 2000?

.elseif eax==5 && ebx==1 ; is it Windows XP?

.elseif eax==5 && ebx==2 ; is it Windows 2003?

.elseif eax<=4 ; is it Windows NT?

.endif

Non NT-based operating systems could be detected by analysing the additional data area behind TEB, searching the value 00530000h:

非NT内核的操作系统可以通过分析TEB附加数据,搜索00530000h:

mov edx,00530000h ; the 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?

.elseif eax==edx ; is it Windows 98?

.elseif ecx==edx ; is it Windows ME?

.endif

 

V. Conclusions             V. 结论

Resolving the operating system by using this technique is only one possibility to avoid the usage of Advanced Programming

Interface functions. Other functions, for example GetCommandLine[1], IsDebuggerPresent[1] or named functions in this essay could be "rewritten" in the same way. In other words: the reverse engineer isn't able to set breakpoints on API function calls, because they didn't exist. And mixing different operating system solutions together makes life even harder for him.

采用这个技术,不过是避免使用API函数一种方法。其他很多函数,例如GetCommandLine[1], IsDebuggerPresent[1] 或者这篇文章中的一些函数都可以采用同样的方法被重写。换句话说:逆向人员不会拦截到相关API函数,因为根本就没有使用他们。并且,如果把对不同操作系统的处理都混杂在一起,对他们分析来说,会更加困难。

 

VI. Appendix           VI. 附录
.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


相关文章
|
8月前
|
JSON API 数据库
手机空号检测API:接口技术详解
介绍号码有效性检测技术,涵盖空号识别原理、高并发架构设计及Python集成示例,助力企业提升电销、风控等场景的运营效率,降低无效号码带来的资源浪费。
1252 0
|
9月前
|
JSON 监控 API
在线网络PING接口检测服务器连通状态免费API教程
接口盒子提供免费PING检测API,可测试域名或IP的连通性与响应速度,支持指定地域节点,适用于服务器运维和网络监控。
1327 0
|
JSON 测试技术 API
API调用类型全面指南:理解基础知识
在数字化时代,API(应用程序编程接口)是连接不同软件应用的核心技术。掌握API调用类型对于开发高效、可扩展的系统至关重要。本文详细解析了GET、POST、PUT、DELETE等常见API请求方法,以及GraphQL、WebSocket等高级技术的应用场景。同时,介绍了APIPost这一强大工具如何优化API开发与测试流程。通过理解HTTP状态码、数据格式及请求头部信息,开发者能更好地设计和管理API,实现无缝跨平台通信。无论是数据获取、更新还是实时交互,合理选择API调用类型均可提升开发效率与用户体验。
|
人工智能 缓存 自然语言处理
构建智能天气助手:基于大模型API与工具函数的调用实践
在人工智能快速发展的今天,大语言模型(LLM)已经成为构建智能应用的重要基础设施。本文将介绍如何利用大模型API和工具函数集成,构建一个能够理解自然语言并提供精准天气信息的智能助手。
4748 11
|
XML 网络协议 API
从cURL到GraphQL:不同API类型概述
本文概述了不同API类型及其应用,帮助开发人员选择合适的工具。cURL是强大的命令行工具,适用于调试和自动化;RESTful API基于HTTP方法,适合Web服务和微服务架构;SOAP用于企业级应用,提供高安全性;GraphQL通过精确查询减少数据传输;WebSocket支持实时通信,适用于低延迟场景。了解这些API的特点和优势,有助于构建高效、可扩展的应用程序。
|
人工智能 监控 安全
自学记录鸿蒙 API 13:骨骼点检测应用Core Vision Skeleton Detection
骨骼点检测技术能够从图片中识别出人体的关键骨骼点位置,如头部、肩部、手肘等,广泛应用于运动健身指导、游戏交互、医疗辅助、安全监控等领域。我决定深入学习HarmonyOS Next API 13中的Skeleton Detection API,并开发一个简单的骨骼点检测应用。通过理解API核心功能、项目初始化与配置、实现检测功能、构建用户界面,以及性能优化和功能扩展,逐步实现这一技术的应用。未来计划将其应用于健身指导和智能监控领域,探索与其他AI能力的结合,开发更智能的解决方案。如果你也对骨骼点检测感兴趣,不妨一起进步!
511 9
|
网络协议 API
检测指定TCP端口开放状态免费API接口教程
此API用于检测指定TCP端口是否开放,支持POST/GET请求。需提供用户ID、KEY、目标主机,可选指定端口(默认80)和地区(默认国内)。返回状态码、信息提示、检测主机、端口及状态(开放或关闭)。示例中ID和KEY为公共测试用,建议使用个人ID和KEY以享受更高调用频率。
381 14
|
安全 Linux 网络安全
nmap 是一款强大的开源网络扫描工具,能检测目标的开放端口、服务类型和操作系统等信息
nmap 是一款强大的开源网络扫描工具,能检测目标的开放端口、服务类型和操作系统等信息。本文分三部分介绍 nmap:基本原理、使用方法及技巧、实际应用及案例分析。通过学习 nmap,您可以更好地了解网络拓扑和安全状况,提升网络安全管理和渗透测试能力。
953 5
|
网络协议 API
检测指定TCP端口开放状态免费API接口教程
该API用于检测目标主机指定TCP端口是否开放,适用于检测连通状态等场景。支持指定大陆、美国、香港等检测节点。请求地址为 `https://cn.apihz.cn/api/wangzhan/port.php`,支持POST和GET请求方式。请求参数包括 `id`、`key`、`type`、`host` 和 `port`。返回参数包含检测结果和状态码。示例请求:`https://cn.apihz.cn/api/wangzhan/port.php?id=88888888&key=88888888&type=1&host=49.234.56.78&port=80`。
440 3

热门文章

最新文章

推荐镜像

更多