12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 228|回复: 0

【习题】Tencent2016C (虚拟机检测技术)

[复制链接]

315

主题

315

帖子

640

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
640
发表于 2020-7-16 07:32:10 | 显示全部楼层 |阅读模式
题目来自:
2016腾讯游戏安全技术竞赛第二轮第2题——PC方向
题目概要

要求说明:
编写一个【Tencent2016C.dll】,并导出多个接口函数:CheckVMWareX,CheckVirtualPCX,CheckVirtualBoxX,X为1-100之间的数字,比如CheckVMWare1,CheckVirtualPC8,...,CheckVirtualBox98。
CheckVMWareX系列函数功能:检测自己是否运行于VMWare中,是返回TRUE,否则返回FALSE。
自己一直用VMware,积累一下反虚拟机手段,希望调试病毒能少踩坑,适合新手看,VirtualPC和VirtualBox也都是差不多,以后有时间补上吧~
编译环境:
VS2015创建win32 dll ,静态编译->属性->C/C++->代码生成->运行库(MT)
VMware12 + win7 32位测试

代码原理

执行特权指令检测

原理:在x86体系中,一些指令在获取硬件相关信息时不产生异常,如sidt、sgdt、sldt、cpuid等,而VMware因为性能原因并没有虚拟这些指令,所以意味着这些指令在vm虚拟机中和物理机中运行时会返回不同的结果。
然而在测试一些常用检测技术时发现部分已失效,应该是VMware更新导致的,先来看两个之前很常用的技术:
Redpill

  简单说,就是通过运行sidt指令获取IDT寄存器的值(IDT: 中断描述符表,可以简单理解为查找处理中断时所用的函数,共256项,如第3项就是我们常用的int3断点)。Redpill的作者测试说明虚拟机中的IDT地址通常位于0xFFXXXXXX,而在真实主机上位于0x80xxxxxx。所以可通过判断执行SIDT指令后返回的第一字节是否大于0xD0,判断是否在虚拟机中。同时这项技术必须满足运行在单核处理器上,因为每个核心只有一个IDT表~如果是多核切换就很难确定具体值了~
No Pill

  sgdt与sldt指令探测技术,依赖于LDT(局部描述符表)由处理器分配而非操作系统分配的事实。因为Windows正常情况下不使用LDT,但VM提供了LDT的虚拟化支持,结果就是:真机中LDT位置为0,而在虚拟机,不为0。同时对于GTR,虚拟机中应为0xFFXXXXXX , 否则为真机。
简单看一下idt:
打开双机调试(建议Virtual KD,配置较简单)

当前我们已经在调试虚拟机的操作系统了,所以直接看这三个表的地址~

好吧,这哪里是虚拟机,不就是真机啊!看来VM这么多年没少打补丁~
代码也不用测试了,肯定不能成功啊,有兴趣的可以测试下低版本VM~
好在我们还有第三种特权指令可用~
查询I/O通信端口

原理:使用IN指令来读取特定端口的数据进行两机通讯,但由于IN指令属于特权指令,在处于保护模式下的真机上执行此指令时,除非权限允许,否则将会触发类型为"EXCEPTION_PRIV_INSTRUCTION"的异常,而在虚拟机中并不会发生异常,在指定功能号为0xA/10(获取VMware版本)时,会在EBX中返回其版本号“VMXH”;而当功能号为0x14时,可用于获取VMware内存大小,当大于0时则说明处于虚拟机中。代码分析如下:
//查询I/O通信端口BOOL CheckVMWare1(){        BOOL bResult = TRUE;        __try        {                __asm                {                        push   edx                        push   ecx                        push   ebx                //保存环境                        mov    eax, 'VMXh'                        mov    ebx, 0             //将ebx清零                        mov    ecx, 10            //指定功能号,用于获取VMWare版本,为0x14时获取VM内存大小                        mov    edx, 'VX'          //端口号                        in     eax, dx            //从端口edx 读取VMware到eax                        cmp    ebx, 'VMXh'        //判断ebx中是否包含VMware版本’VMXh’,若是则在虚拟机中                        setz[bResult]             //为零 (ZF=1) 时设置字节                        pop    ebx                //恢复环境                        pop    ecx                        pop    edx                }        }        __except (EXCEPTION_EXECUTE_HANDLER)       //如果未处于VMware中,则触发此异常        {                bResult = FALSE;        }        return bResult;}利用虚拟硬件检测

网卡MAC地址检测

原理:网卡设备的MAC地址是唯一不变的(虽然也能物理修改)。
MAC地址的前三个字节标识一个提供商,所以一般情况下只需要找到VM固定的前三个字节就可以了~
ipconfig /all

查询到虚拟机的MAC地址00-0C-29-38-8B-E1
//通过MAC地址检测BOOL CheckVMWare2(){        string mac;        getMacAddr(mac);            //API见附件,以下是3种常见标识         if (mac == "00-05-69" || mac == "00-0c-29" || mac == "00-50-56")        {                return TRUE;        }        else        {                return FALSE;        }}CPUID检测

原理:CPUID指用户计算机当前的信息处理器的信息。CPUID 指令是从 Intel 486 处理器以后开始加入支持的(只要不是古董应该都OK )。当eax=1时,运行CPUID指令之后,ecx的高31位可以判断出是否在虚拟机中,如果ecx的高31位为0表示在虚拟机下,否则在宿主机中。
//3.CPUID检测BOOL CheckVMWare3(){        DWORD dwECX = 0;        bool b_IsVM = true;        _asm        {                pushad;                pushfd;                mov eax, 1;                cpuid;                mov dwECX, ecx;                and ecx, 0x80000000;        //取最高位                test ecx, ecx;              //检测ecx是否为0                setz[b_IsVM];               //为零 (ZF=1) 时设置字节                popfd;                popad;        }        if (b_IsVM)                          //宿主机        {                return FALSE;        }        else                                 //虚拟机        {                return TRUE;        }}mov eax, 0cpuid上面代码中,eax为0获取,那么它将返回值是:

  • eax:最大的基本功能号
  • ebx:"Genu"
  • edx: "ineI"
  • ecx:"ntel"
这几个字符串组合起来就是 "GenuineIntel" 对于 AMD 的处理器来说,它返回的字符串是:"AuthenticAMD",可对应判断处理器。
类似的,对于虚拟机CPUID还有另一种方式检测
eax为0x40000000时,运行CPUID后,ebx+ecx+edx=”VMWareVMWare”;

BOOL CPUID2(){                DWORD dwECX = 0;                bool isVM = true;                DWORD dwReg[3] = { 0 };                _asm {                        pushad;                        pushfd;                        mov eax, 0x40000000;                        cpuid;                        mov dword ptr[dwReg], ebx;     //运行CPUID之后,ebx+ecx+edx=”VMWareVMWare”;                        mov dword ptr[dwReg + 4], ecx;                        mov dword ptr[dwReg + 8], edx;                        popfd;                        popad;                }}通过主板序列号、型号、系统盘所在磁盘名称等其他硬件信息

原理:这里使用WMI的方式,连接COM接口,循环枚举所有的结果对象找到带有VMware的相关信息(类似的信息有很多,只列举一个)。
BOOL CheckVMWare4(){        string table = "Win32_DiskDrive";        wstring wcol = L"Caption";        string ret;        ManageWMIInfo(ret, table, wcol);            //API见附件        if (ret.find("VMware") != string::npos)        {                return TRUE;        }        else        {                return FALSE;        }}通过能够获取的其它特征信息检测

本质和找MAC地址类似,就是要观察虚拟机,观察它的各种系统信息,设备信息,再找相关的信息。
搜索特定进程

原理:会有一些虚拟机特有的进程,可以通过检测这些进程是否存在来判断~

显然我们可以从vmtoolsd.exe和vmacthlp.exe突破
//遍历进程BOOL CheckVMWare3(){        DWORD ret = 0;        PROCESSENTRY32 pe32;        pe32.dwSize = sizeof(pe32);        HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//拍摄快照        if (hProcessSnap == INVALID_HANDLE_VALUE)        {                return FALSE;        }        BOOL bMore = Process32First(hProcessSnap, &pe32);            //获取第一个进程        while (bMore)        {                if (wcscmp(pe32.szExeFile, L"vmtoolsd.exe") == 0)       //注意此处用了wcscmp(pe32.szExeFile是 WCHAR*)                {                        return TRUE;                }                bMore = Process32Next(hProcessSnap, &pe32);           //遍历下一个进程        }        CloseHandle(hProcessSnap);        return FALSE;}通过注册表检测

虚拟机中有非常多的虚拟硬件(不只是网卡,还有打印机、鼠标等等,都可以判断)

以VMwareHostOpen.exe为例~
//通过注册表检测BOOL CheckVMWare5(){        HKEY hkey;        if (RegOpenKey(HKEY_CLASSES_ROOT, L"\\Applications\\VMwareHostOpen.exe", &hkey) == ERROR_SUCCESS)         {                return TRUE;        //RegOpenKey函数打开给定键,如果存在该键返回ERROR_SUCCESS        }        else        {                return FALSE;        }}通过特定服务检测


//通过特定服务检测BOOL CheckVMWare7(){        int menu = 0;        SC_HANDLE SCMan = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);        //打开服务控制管理器        if (SCMan == NULL)        {                cout  输入regedit->注册表</strong>
定位到网卡处:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E972-E325-11CE-BFC1-08002bE10318}</p>
新建一个字符串值,命名为NetworkAddress,内容是新的MAC地址
&quot;网络连接&quot;中重启本地连接即可

调整VM设置

VMware Tools中有一些未文档化的功能可以减轻反虚拟机技术探测,下面的代码放到VMware的.vmx文件的最后面:
isolation.tools.getPtrLocation.disable = "TRUE" isolation.tools.setPtrLocation.disable = "TRUE" isolation.tools.setVersion.disable = "TRUE" isolation.tools.getVersion.disable = "TRUE" monitor_control.disable_directexec = "TRUE" monitor_control.disable_chksimd = "TRUE" monitor_control.disable_ntreloc = "TRUE" monitor_control.disable_selfmod = "TRUE" monitor_control.disable_reloc = "TRUE" monitor_control.disable_btinout = "TRUE" monitor_control.disable_btmemspace = "TRUE" monitor_control.disable_btpriv = "TRUE" monitor_control.disable_btseg = "TRUE"  其中directexec可以使用户模式下的代码被模拟执行而非直接在硬件上运行,因此可以ANTI一些反虚拟机技术。前四条设置被VMware后门命令使用,它们的作用是使得运行在Guest系统中的VMware Tools不能获取宿主系统的信息。这些设置会禁用VMware Tools的一些有用功能,并可能对虚拟机性能有严重负面影响(测试发现速度会明显降低,建议其它技术无效时再使用)
另:
1.monitor_control.restrict_backdoor = &quot;true&quot;
2.开启vmware workstation,虚拟机 -> 设置 -> 处理器 -> 禁用二进制翻译加速 可能在某些时候会有帮助
       总体而言感觉IDA插件的方式比较实用,比如有病毒在申请的空间中放入反虚拟机代码,我们可以在空间申请后DUMP下来,在IDA中搜索,再在OD中定位,这样能节省不少时间~
  而许多对硬件和信息的探测想anti就比较难了,没什么思路,总不能把虚拟机CPU、文件路径、服务名等等都改了吧,最好的方式,应该还是逆向分析破解吧 ~比如,一段代码在一个条件跳转处过早终止,可能就会用到反虚拟机技术~我们已经清楚正向怎么检测了,逆起来当然有思路喽~ 路漫漫其修远兮啊~ 大部分技术很多年没变化了,有新加入的,也有的随着VMware 更新已无法使用,和网上的一些资料多少会有冲突,查漏补缺,方便需要的朋友参照,文中测试如有不准确处,请各位指出~谢谢
参考资料

《恶意代码分析实战》    诸葛建伟 姜辉 张光凯 译
《虚拟机检测技术剖析》 林桠泉
Tencent2016_PC.rar
287.73 KB, 下载次数: 453, 下载积分: 吾爱币 -1 CB

题目、代码、IDA插件

来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-26 05:51 , Processed in 0.078125 second(s), 32 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表