怎样判定应用程序自身运行在“兼容模式”下?

      P.S.话说有很多天很多天没有写东东了啊,因为实在太忙了,还是恢复至少一个月两篇的状态吧。

 

      我们的程序有时候需要精确的判定当前运行在哪个系统下面,也就是说程序的某个功能可能需要知道当前运行在哪个真正的操作系统下,而操作系统提供了一个兼容模式功能,就是用户可以设置某个程序运行在某个模拟的更低的版本的操作系统下面,这是有好处的,因为某些程序在某些更高版本的操作系统下面可能发生兼容性问题而无法运行。在设置兼容模式运行后,程序里面调用ring3层的GetVersionEx得到的将是模拟的的操作系统版本,而不是真正的操作系统版本。

      由此而引发两个问题:

      1、怎么判定当前程序(自己)运行在兼容模式下了呢?

      2、如果有一个需求,在安装时,怎么设置一个程序运行在某个低版本的操作系统兼容模式下呢?

     

      先看下第2个问题,首先看一下在设置了兼容模式运行后,系统做了些什么事情?很容易做到,使用注册表工具对explorer.exe进行监控,在设置兼容模式应用或者确定后,发现系统在注册表 [HKCU/Software/Microsoft/Windows NT/CurrentVersion/AppCompatFlags/Layers] 写下了如下一些东东:

      系统把需要进行兼容模式运行的程序路径记录在这个下面,具体兼容哪个环境则由属性的值来确定,譬如WIN2000, NT4SP5, WIN95, WIN98, WINXPSP2, WINXPSP3, WINSRV03SP1, WINSRV08SP1, VISTARTM, VISTASP1, VISTASP2等等(不要在低版本的操作系统下兼容更高版本的操作系统,不会出问题,而是毫无意义,系统直接忽略)。有了这个就可以做到把某个程序写入兼容模式运行中。也可以保护这个注册表位置防止别人来使用兼容模式运行你的程序。

 

      再看看第一个问题,研究下了微软实现兼容模式的原理,网上的资料很少,但是大概就是使用HOOK的原理,windows发现该程序需要进行兼容模式运行(通过查注册表啦,还有一些系统默认以兼容模式运行的程序,应该是记录在其他地方,没有深究),就会加载一些不同的系统DLL(在win32下一个应用程序想跑起来,是需要很多系统的DLL的)来进行程序的运行,大概情况如下,左边是非兼容模式运行时加载的一些DLL,右边是运行在兼容模式环境下后加载的一些DLL:

 

      这是否就给了我们一些思路?可以检测当前程序加载的模块,如果有这些AcGenral.dll之类的模块存在,就认为是运行在兼容模式下呢?这个我没有去试过,但是我觉得可行。o(∩_∩)o

      另外一种方法是从原理是来绕过,GetVersionEx这个API来之kernel32.dll,而kernel32.dll又调用了ntdll.dll里面的RtlGetVersion这个函数,如果我们直接调用呢?试了下也是有一定可行性的。不过悲剧的是,这个方法在vista及以上系统就无效了,可能是因为微软在实现兼容模式时,hook得更加深了。

 

      360也有个兼容模式检测功能,去看了下他的实现,还不错。

      然后去研究了下,发现很有道理,360的方式是先调用 GetVersionEx 得到一个版本号,譬如是5.0(2000系统),然后算出一个值50(5*10 + 0);然后调用文件版本API,取出文件ntoskrnl.exe的版本号,譬如是5.1.2600.5938,然后算出一个值52(5*10 + 1),对比前后两个值,如果不相等则认为自身运行在兼容模式下。具体分析可以见调试结果(call 0042980是去取ntoskrnl.exe是版本)。

     

      下面是IDA反编译的结果:

 

      还不错哦。

      [END]

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值