首页
论坛
课程
招聘
[分享]基于Qemu/kvm硬件加速的下一代安全对抗平台PPT分享
2021-10-27 18:22 21528

[分享]基于Qemu/kvm硬件加速的下一代安全对抗平台PPT分享

2021-10-27 18:22
21528

安全的本质永远绕不开“对抗”这个主题,基于对日常攻防对抗的思考和作为研究员不断探索的天性。

 

蒋浩天先生为我们带来了《基于Qemu/kvm硬件加速下一代安全对抗平台》,虚拟化等技术带给传统攻防全新的思考维度,让我们看到了站在上帝模式下的降维打击。随着后续行为监控和武器库的完善,相信此工具可以帮广大安全人员解决安全对抗的疑难杂症。

 

下面就让我们来回顾2021看雪第五届安全开发者峰会上《基于Qemu/kvm硬件加速的下一代安全对抗平台》的精彩内容。

演讲嘉宾

图片描述

蒋浩天:字节跳动无恒实验室云安全专家,曾任职于360、腾讯,现就职于字节跳动无恒实验室。
拥有6年一线安全对抗经验。擅长内核安全开发、虚拟化安全、沙箱检测,是某沙箱的核心作者之一。擅长逆向分析、二进制漏洞攻防、游戏安全对抗、嵌入式,bios开发。

演讲内容

以下为速记全文:

 

大家好,接下来由我给大家分享《基于Qemu/kvm硬件加速下一代安全对抗平台》。分享者:蒋浩天,来自字节跳动无恒实验室。我的研究方向为:二进制安全、漏洞攻防、游戏安全、沙箱检测、虚拟化安全,喜欢研究一些底层方向。将安全能力下沉,开启安全对抗的上帝模式。

 

我们的议题分为大概几个部分,分别是:

  1. 安全对抗思考

  2. 虚拟化技术

  3. Ark工具设计思路

  4. 调试器设计思路

  5. 平台介绍(KVM-Based security platform)

  6. 后续展望

01安全对抗思考

 

首先,先来说一下:安全对抗思考。我们在安全对抗中会经常遇到那些棘手的问题呢?

 

由于很多黑产模块商业化。导致对抗异常激烈,商业化模块具备各种对抗功能,当恶意样本,黑产工具集成了商业化模块后,会具备很强的对抗能力,例如说:

 

1、反调试,公开插件已经无法绕过。

 

2、反沙箱,反ark工具,一旦检测到沙箱环境,行为监控工具,ark工具等常用的安全工具,样本停止工作。

 

3、机器封禁,当它检测到你在分析它,将会进行机器封禁,导致此机器无法运行此样本。

 

4、样本很紧急,老板让你今晚出报告。

 

目前来说,业界有哪些优秀的解决方案?

 

第一个解决方案,也是目前比较流行的解决方案,就是模拟执行,例如unicorn。模拟执行具备一定的优势,例如它可以模拟执行一段shellcode且是轻量级的。也有一些劣势,例如需要模拟一个可以执行的环境,这个环境想要模拟非常全面,工程量也是很大的。它的致命缺点是效率比较低,且环境模拟不全。无法模拟D3D,一些依赖于D3D的软件无法正常工作运行。例如说:游戏无法运行,游戏外挂就不能正常工作,你就无法分析它。

 

第二个比较主流的解决方案就是硬件调试器,此方案优点比较多:效率高,支持d3d。劣势是:第一,需要额外购买硬件并且价格比较高;第二,携带不方便,不方便给小伙伴展示高端调试技巧;第三,对于用户态环境识别不是非常好。

 

这两种解决方案为什么比较好用?

 

图片描述

 

当前的这些问题,其实我综合分析一下,站在我的角度来看:windbg依赖于windows的调试子系统,gdb依赖unix的ptrace,所以就会存在很多可检测特征。

 

我理解来说:硬件调试器和模拟执行这两类工具抽象一点来看,更像一个站在CPU内部的工具,可以精准的控制每一行指令的执行,监控或修改指令执行结果。它不依赖于系统的调试机制,所以很多反调试方法对其无效。

 

通俗一点说:站在了一个至高点,实现了降维打击。

 

我们继续思考:模拟执行这项技术最开始用于虚拟机,来虚拟一个操作系统,虚拟机本身具备模拟执行的能力。

 

Unicorn和虚拟机有什么关联?经过查阅资料,unicorn的代码大部分是移植的QEMU中的代码。由于虚拟机模拟执行操作系统时,性能非常低,所以模拟执行逐渐被抛弃。硬件虚拟化成为了主流。启用硬件虚拟化的虚拟机,不再需要模拟执行了,效率得到了非常大的提升。

 

虚拟机一般都具备一个virtualJTAG接口,这个接口在模拟执行和硬件虚拟化两种模式中,实现原理不同。VirtualJTAG接口不能区分进程上下文,不能调试用户态程序,而且不能识别windows内核。

 

这时突发奇想,我们是否可以基于虚拟化来开发一套类似的工具?

 

是否可以对虚拟机进行二次开发,开发一个支持windows系统,支持用户态和内核态的调试器呢?并且将各种安全工具,ark工具,调试,都集成到一起,形成平台化。

 

这样,我们也是站在了一个制高点,形成一个降维打击。以后做安全对抗就非常方便了。我们的目标是:将安全工具运行在物理机,对虚拟机进行控制。在开发之前,就可以想到一些优略势,首先说优势:1、不依赖于操作系统机制。例如调试机制。2、不需要在虚拟机中安装模块,安全工具无法被检测。3、直接在物理机对虚拟机进行环境扫描,权限更高且不会被检测。4、可以监控虚拟机中敏感内存的读写执行。

 

但同时也会存在一些劣势:1、数据解析工作量大,适配繁琐。2、不能调用 api。一些常规操作变得异常复杂,例如锁,同步。

 

02虚拟化技术

 

接下来介绍一下虚拟化技术,先来介绍几个名词:对应的翻译在后面都列出来了,大家可以先看一下,因为后续讲解过程中可能会用到。

 

图片描述

 

由于模拟执行,性能非常低,随着技术的发展,硬件虚拟化成为了主流。所以我们需要看一下硬件虚拟化的原理:

 

图片描述

 

如图我们调用vmxon指令后,cpu进入虚拟化模式。分别为guest模式和host模式。通过VMExit和VMEntry事件来进行驱动。

 

例如说执行VMLAUNCH指令后,此时就会有一个VMEntry事件,虚拟机从host模式,进入到guest模式,此时虚拟机就开始执行了。

 

当虚拟机运行过程中,遇到了一些特殊事件比方说执行了in out 指令,就会产生一个VMExit 事件,此时CPU将会从guest模式切换到host模式。

 

在host模式下,对in out指令进行虚拟化处理。处理完成之后,在返回到guest,让虚拟机继续执行。

 

接下来需要介绍qemu kvm的架构图:

 

图片描述

 

首先最底层,是硬件层,例如说CPU,GPU, 内存,磁盘,网卡等硬件设备。再硬件层之上,是linux内核层,例如说vmlinux,设备驱动,kvm等,其中kvm就处于这一层。再上一层,就是linux用户层,在这一层,运行了很多linux程序,服务,守护进程等相关的东西。Qemu就处于这一层,qemu以一个进程的形式存在。

 

Qemu基于kvm开启硬件虚拟化。所以说图中的两个qemu虚拟机都运行在kvm之上。在qemu虚拟机内部,运行着虚拟机的操作系统,分为虚拟机的内核层,和虚拟机的用户层。

 

根据上面的架构图得知,虚拟机是运行在qemu进程的上下文的。那么qemu进程,是否包含虚拟机的内存数据呢?

 

我们在创建虚拟机时,需要设置虚拟机内存的大小。虚拟机在启动时,首先要为虚拟机申请物理内存,代码如下。

 

图片描述

 

通过此代码反映出一个问题。虚拟机的内存,其实就是对应这个mmap的内存,在qemu进程的上下文中。大家可以从代码中看到,这个mmap函数的调用。

 

如上图可以看到,虚拟机启动后,用户态会存在一个qemu的进程。我们的问题是:如何对这块内存进行识别,解析出虚拟机中操作系统的数据?想要完成这项工作,我们必须要完全了解虚拟机中是如何实现内存的虚拟化的。

 

我们先看一下虚拟化模式和非虚拟化模式的内存地址翻译流程区别:

 

图片描述

 

对比发现,多了一层地址翻译,需要把虚拟机中的物理地址,再次进行翻译,翻译成物理机的物理地址。也就是GPA 翻译成HPA。

 

我们首先需要简单回顾一下X86架构下内存翻译流程:

 

图片描述

 

逻辑地址到线性地址的翻译,我们在保护模式下,地址访问都是段寄存器加逻辑地址来进行访问的。

 

例如说,TI位为0。我们需要在gdt中寻址。根据段寄存器的index字段,来访问gdt表。找到对应的项,例如说,cs段寄存器的index 为2,对应GDT的第3项,获取到对应的段描述符之后,P位为1表示有效。

 

判断段描述符的DPL和段寄存器的RPL是否满足一系列的权限检查。如果检查全部通过。将得到段对应的base。大家可以看到,这些段的base都是0。拿到段的base之后,用base 加上逻辑地址偏移,既可以计算出对应的线性地址。

 

接下来我们说一下从线性地址到物理地址的转换,线性地址到物理地址的转换需要通过页表来完成。由这张图,我们可以找到每一级索引的位置:

 

图片描述

 

先说一下4K页面的转换,CR3寄存器是页表寄存器。存放了页表的首地址,首先需要对线性地址进行拆分,把每一级的索引都划分出来,偏移也要划分出来。最高级索引,索引CR3指向的目录,拿到对应的项之后,这里面存放的也是一个物理地址。然后用第二级索引进行索引,以此类推,直到索引完成,最后拿索引到的物理地址,加上offset,即可完成线性地址到物理地址的转换。

 

图片描述

 

接下来看一下2M页面的转换,他跟4K页面的转换基本原理一致,只是说索引级别少了。Offset变长了。

 

图片描述

 

再看一下从GPA到HPA的翻译过程,先将GPA 进行拆分,划分好每一级的索引,和offset。根据eptp指向的页表,进行一级一级的索引,跟前面的页表翻译原理类似。

 

图片描述

 

接着看一下虚拟机的内存虚拟化实现的整体架构,如图:

 

图片描述

 

1、在虚拟机中,GVA先通过页表,翻译成GPA。
2、通过EPT,将GPA翻译成HPA.

 

Host模式下:1、在宿主机中,HVA通过宿主机的页表翻译成HPA。2、Qemu通过memory slot机制,管理这个GPA 到HPA的映射。

 

如图,黄色的方块,就代表虚拟机的一块内存,这块内存在guest中,访问对应的GVA可以访问到。同时,在host中,访问对应的HVA也可以访问到,因为都是对应的同一块物理内存。

 

前面我们介绍了X86架构下的地址翻译过程,我们还需要了解一下qemu是如何管理内存的。

 

由于qemu在启动时,mmap了一块内存,这块内存用于虚拟机的物理内存。由于内存的惰性分配,和效率优化,虚拟机需要对他进行管理。

 

Qemu有两种内存管理方式,第一种是树形管理,具备一个更好的管理视图。第二种是平坦类型管理,用于和kvm交互。

 

我们先说一下树形管理:Qemu的内存,最顶端是一个address space 结构体,不同类型的内存由不同的address space来表示。所有的address space通过链表,连接在一起。

 

图片描述

 

在address space结构体内部,有一个root字段,指向一个memory region结构体,这个字段是内存树的根节点。

 

Memoryregion下面会有子节点,有一些子节点的ram_block是为空的,他表示一个别名的引用。其中alias offset 就是指向引用的memory region对应的这个虚拟机物理内存的偏移。有一些memory region的ram_block是有值的,如果不为空,里面会有一个host字段,这里指向的是虚拟机物理内存对应的hva。

 

虽然说qemu对虚拟机的内存有自己的管理体系。但是想要实现内存虚拟化,必须按照cpu的规则来进行ept映射。才能够生效。所以qemu还有一套平坦内存管理视图,用于和kvm进行交互。实现基于硬件的内存虚拟化。

 

图片描述

 

如图所示,每一个memory region经过generatememory topology函数调用后,都会生成一个Flatview结构体,这个结构体会插入到一个flat_views的一个hashmap中,方便下次快速查找。

 

这个FlatView内部,存在一个ranges字段,这个字段是一个指针,指向Flat range的数组。每一个flat range 结构体管理着一块虚拟机的物理内存,标志着kvm中EPT如何对虚拟机物理内存进行虚拟化。

 

例如说flat range里有一个addr字段,Addr是一个addrrange 类型,里面包含一个start,和size。这里面的start存放的是一个gpa。Qemu通过调用kvm的接口来完成ept映射。kvm会根据调用参数,和上述的X86架构的规则来完成ept的映射。建立GPA和HPA的映射关系。从而实现了内存的虚拟化。到目前位置,qemukvm的内存虚拟化,我们大概介绍完成。

 

03ark工具设计

 

有了前面的知识体系,我们想实现ark的功能,已经有了一些希望。我们就有了初步的想法。虚拟机中的物理内存是qemu启动中mmap出来的一块内存。所以我们读写这块内存,其实就是在读写虚拟机的物理内存。

 

图片描述

 

所以第一步,我们要先完成HVP ßà GPA转换。我们可以加载一个内核模块,从而获取到EPT的页表。拿到页表后,我们就可以将GPA翻译成HPA。然后再从HPA转换成HVA。

 

但是这样有一个缺点,想要从HPA 翻译成GPA 就比较麻烦了,需要遍历ept的表,效率非常低。

 

KVM为了完成这个GPA到HVA的互相翻译,实现了一个remap机制。我们通过解析kvm的remap 可以完成这个步骤,也可以通过qemu的两种内存管理模型来完成这项工作。

 

我们完成了上述功能后,我们就具备了读取任意GPA的能力了。但是现在的操作系统都是分页的,就跟前面所讲述的一样,通过页表进行了映射。

 

图片描述

 

所以说我们具备了GPA的任意地址读写能力还是不够的。我们还需要能够读取任意地址GVA才行。我们要想具备GVA的读写能力,我们就需要一个页表。有了页表,我们才能够自己翻译内存,找到GVA和GPA的对应关系。

 

现在的操作系统,每一个进程的用户态内存都是隔离的。内核态的内存是相同的。每一个进程都有一个独立的的页表,存放在进程控制块中。所以说我们要想能够读取任意进程的任意GVA,我们就需要先拿到所有进程的页表。但是我们想要拿到所有进程的页表,我们就需要拿到所有进程控制块信息。

 

由于进程控制块是存放在内核地址空间的,进程的内核态地址空间都是相同的,所以说,我们只要拿到任意一个进程的cr3,即可通过解析页表,来实现一个读写内核GVA的能力。有了这个能力,我们才能进行下一步操作。

 

问题来了,我们如何获得虚拟机中任意进程的cr3寄存器?

 

我们如何获取一个cr3寄存器的值呢?我们这里尝试了几种方法:
1、通过vmread指令,读取vmcs中的guest cr3。

 

2、通过对vmexit handler进行hook。

 

3、Kvm运行时,会把cr3 保存在某个位置。

 

图片描述

 

如图,只要设置kvm_valid_regs的值, kvm在运行过程中就会自动把所有寄存器保存下来。经过调试发现,默认情况下,这个字段为0。所以我们需要自己将他置为1,之后我们就可以去读到cr3寄存器了。

 

有了cr3之后,我们自己写一套页表翻译的代码,将GVA转换成GPA。我们就可以具备读写内核地址空间GVA能力了。我们需要适配各个模式,例如32位模式,PAE模式,64位模式,4k页面模式,2M页面,1G页面等多种情况。

 

现在,我们只具备了读写内核地址空间任意GVA,但是我们还不能读写任意进程用户态的任意内存。

 

如前面所述,每一个进程都拥有一个自己的页表。而这个页表存放在进程控制块中。而进程控制块在内核地址空间中。

 

所以接下来我们应该找到所有的进程控制块。进程控制块由操作系统内核进行管理,例如说windows平台下,在ntoskrnl模块中,我们可以通过解析PspCidTable, PsActiveProcessHead等来识别出所有的进程控制块。

 

但是我们目前无法知道这些数据结构所在的地址。所以我们当务之急,我们需要找到ntoskrnl模块的首地址在哪里?

 

如何找到它,其实方法很多,可以通过IDT中的中断向量的handler来进行定位,或者msr寄存器等等诸多方法。

 

例如说:我们首先在物理机读取到虚拟机的IDT表。获取异常向量的handler。我们知道,异常向量的handler,肯定是位于ntoskrnl模块中。

 

图片描述

 

第一种方法采用暴力搜索,向上搜做mz文件头,肯定能搜到。还是不够优雅。

 

第二种方法采用符号解析,我们通过解析内核符号,来获取handler在模块中的位置,Ntoskrnl首地址 =handler 地址 – 偏移;这样我们就能够获取到内核模块首地址了。

 

我们既然要用到符号信息,那么我们就得具备解析符号的能力。我们的代码运行在linux平台,我们如何解决符号解析的问题?

 

对于linux虚拟机,我们解析elf文件的debug info信息,这里面是一个dwarf结构,开源,第三方库比较多。所以很好解决。

 

但是windows pdb符号如何解析呢。我们知道在windows平台下解析pdb,调用com接口即可,非常简单。但是我们运行在linux平台上,是无法调用windows提供的api的。

 

微软最近几年公开了pdb相关的格式和代码。但是非常复杂,如果我们自己去解析,将耗费非常多的时间。于是我们想到了其他方法:

 

1、硬编码?放弃,维护很困难。
2、Llvmpdbutil,解析成功,但是对于win10 的符号信息解析崩溃,不知道现在llvm有没有修复这个问题。
3、Wine?我们最终采用了wine的方式,开发一个windows平台的符号解析程序,然后运行在wine环境下,来完成pdb解析。

 

这样,我们就解决了符号解析的问题。

 

我们现在具备了符号解析的能力,知道内核模块的首地址,并且具备对内核地址空间任意地址读写的能力。我们就可以基于这些能力实现一个ark的工具,例如说:

 

解析PspCidTable,PsActiveProcessHead读取所有的进程信息;解析PsLoadedModuleList读取所有的内核模块信息等等,方法非常多,可以实现的功能也非常多,而且老前辈写过很多文章,这里就不一一讲解了。

 

当我们解析出所有的进程控制块的时候,我们就可以拿到进程对应的页表。通过解析进程对应的页表,我们就具备读写任意进程任意空间GVA的能力了。

 

此时有一个潜在的问题,由于内存分页的机制问题,会把不常用的内存交换到磁盘上。

 

这种情况我们就无法读取这块内存了,这个问题我们后续进行讲解。

 

经过我们不懈努力,我们已经具备一个ark初级的功能,例如:可以读取到虚拟机中的所有进程;每一个进程中,加载的模块信息;可以读取到虚拟机中所有的内核模块等等。这些都是调试器不可缺少的能力。

 

04调试器设计

 

接下来我们介绍一下调试器的设计。

 

传统的虚拟机,在未开启硬件虚拟化加速时,采用的模拟执行。实现一个调试接口比较简单。采用了硬件虚拟化后,虚拟机不再需要模拟执行,具备了更高的性能。

 

虚拟机本身提供了一个virtual JTAG调试接口。只是在模拟执行和硬件虚拟化两种模式下原理不同。并且不支持windows虚拟机,不能区分用户态和内核态。

 

如果我们对virtual JTAG调试接口进行改造,二次开发。我们是否可以能实现windows 内核态,用户态调试呢?

 

图片描述

 

我们首先需要深入分析一下virtual JTAG的实现原理。我们以软件断点为例,会调用kvmarch insert sw breakpoint 函数来插入一个断点,我们看这个代码实现,我们发现,就是保存了原来的位置的字节码,然后替换成了cc。

 

把内存改写成一个0xcc,就能实现断点功能?看似平平无奇,其实在kvm_update_guest_debug中存在着奥秘。

 

我们首先得介绍一下intel硬件虚拟化中的一个特性,exception bitmat特性。

 

图片描述

 

他是一个32位的字段,每一位对应一个异常。当对应的位为1时,虚拟机中,产生对应的异常,就会产生vmexit事件。从而host可以进行捕获,并进行虚拟化。

 

kvm_update_guest_debug 函数,看名字就可以猜到,会和kvm进行交互。我们分析到最后,到最关键的位置,发现:最终通过一个vmcs_write32函数,更新了vmcs的ExceptionBitmap,使得vcpu对guest中int3 异常具备拦截能力。

 

图片描述

 

虚拟机中执行代码,如果遇到int3指令,会产生vmexit,进入host模式,首先由宿主机接管,宿主机将int3指令封装成一个事件,投递给qemu中内置的gdbserver来处理。

 

接着我们整体梳理一下virtualJTAG流程:

 

图片描述

 

1、Vcpu遇到int 3,会产生异常,如果exception bitmap中第四位为1,则产生vmexit事件,并切换到host模式。
2、执行kvm中注册的vmexit handler。
3、Handler将此次的这个vmexit的事件封装成一个结构体,投递给qemu。4、Qemu把此事件交给内置的gdb server。
5、Gdb server 会和gdb client进行交互。
6、Gdb server 收到请求后,返回到vmexit handler中。
7、Vmexit handler中调用vmresume指令,产生vmentry事件,虚拟机恢复执行。
这个virtual jtag方案大概是这个原理。

 

我们通过分析发现,virtualJTAG之所以不能调试用户态内存,不支持windows,根本原因在于这个gdbserver不能识别windows 的结构体,

 

无法解析虚拟机中的所有进程,所有模块等等系统信息。

 

所以我们要做的事情,就是帮它来完成这个功能。于是我们就有了实现一个基于virtualJTAG的调试接口的思路的。

 

我们通过我们自己的ark,来识别所有的进程,进程中所有的模块。我们的ark,具备对虚拟机任意进程,任意内存的读写能力,我们对想调试的位置,把内存改写成int3。通过ExceptionBitmap 的能力,拦截int3异常。后续的处理流程交给qemu内置的gdbserver。

 

我们对内置的gdb server进行了修改,来完成了这个功能。有个问题是:是否可以采用硬件断点?其实采用硬件断点也是可以的,我们需要在kvm中对dr寄存器操作进行拦截,由于精力有限,所以并未实现。

 

其实不止如此,还有非常多的细节问题,例如说:

 

我们采用软件断点的方法,最终还是改写了内存,容易被检测到,怎么办?

 

用户态的内存,可能会被交换到磁盘,如何解决?
对于系统动态库,copy_on_write 如何解决?
Cpu 缓存问题?等等

 

有感兴趣的可以私下交流。我们需要把重点放在第一个问题上。用调试器下断点时还是把内存改写成了int 3,如何才能不被检测到?

 

我们要做的一件事情就是隐藏int3断点。保证不被检测。

 

通过ept特性,对虚拟机的内存进行hook,来欺骗虚拟机,使其无法感知到内存被修改。

 

图片描述

 

如图所示,左边这部分时正常状态下的内存翻译流程,和权限,例如说,GPAàHPA的翻译,此页面具备读写执行三个权限。

 

右边这部分时我们hook之后的状态。我们对原始内存页面进行复制,将权限进行拆分,分为读写权限对应原始内存,和执行权限对应复制的内存,对复制的内存改写int3。

 

当guest 进程读写这块内存的时,读取到的是原始页面。当guest 进程执行这块内存的时候,将翻译成另一个已修改的另一个页面,执行的是修改成int 3的内存页面。

 

通过此方法,我们欺骗进程,让其无法检测到我们修改了内存。

 

我们通过eptMTF 等特性,进行了一些其他功能的扩展,例如说指令trace,内存读写监控。

 

05平台介绍(KVM-Based security platform)

 

通过上述介绍,我们的安全对抗平台,大概原理想必大家都已经理解。

 

图片描述

 

现在我们介绍一下我们安全对抗平台的整体架构:

 

1、首先我们具备一个linux内核模块,用于patchkvm,读写kvm中的关键数据,hookkvm 的关键函数。

 

2、我们需要对qemu进行二次编译,将我们自己实现的调试相关的代码移植到qemu去。使其具备调试能力。

 

3、Manager模块,分为几个子模块。虚拟机管理功能;符号解析功能,支持windows,支持linux;鼠标键盘模拟功能,虚拟机屏幕图片查找功能;Hypervisorsdk,用于和内核模块,qemu调试模块交互。

 

5、Python引擎,用于将目前的大部分功能通过python接口的形式导出,降低开发门槛。方便安全人员参与开发

 

6、还开发了一个简易的ui。

 

Python插件,来实现一些强力的功能,例如antirootkit,武器库,调试器等功能。

 

图片描述

 

这是我们目前导出的部分python接口。例如说,获取所有进程,获取所有内核模块。获取符号信息。读写GPA,读写GVA,EPT hook, 内存读写执行监控等。

 

开发者,知道内核模块地址,进程控制块信息,然后通过解析符号的方法,可以轻松的开发其他的功能。

 

图片描述

 

例如上面代码,大家可以通过非常简单的几行代码,就可以获取到虚拟机中的所有进程,所有内核模块等信息。

 

只需要在python中,importhypervisor_engine,即可。

 

接下来是视频演示:通过视频可以观察,我们的工具在运行过程中,不会出现虚拟机卡顿情况,而且不需要在虚拟机安装任何程序。

 

图片描述

 

图片描述

 

如果采用传统方法,对working set 进行对抗,比较麻烦。通过我们平台提供的能力,几行代码就可以搞定。

 

图片描述

 

如图,非常简单,我们直接定位到内核的PsWatchEnabled,直接进行修改,关闭working set的信息收集。

 

图片描述

 

调试能力展示,大家可以看到,我们在linux宿主机,直接调试虚拟机中的进程。

 

右边是被调试程序的ida截图,大家可以看一下汇编指令,和地址。左边是在物理机通过gdb,调试虚拟机中的这个demo程序。可以观察,汇编指令,和地址都是对应的。

 

调试能力展示,大家可以看到,我们在linux宿主机,直接调试虚拟机中的进程。

 

图片描述

 

06后续展望

 

1、武器库完善,后续希望把 ark 中的常用功能全部移植,实现一个完整的 ark。

 

2、通过 hook 虚拟机内核,完善行为监控工具,将沙箱检测能力放在host中。

 

3、后续尝试支持 arm 架构,通过 arm 服务器,运行安卓系统,完成对安卓系统的支持。

 

4、希望此工具可以帮广大安全人员解决安全对抗的疑难杂症

 

最后是这次议题相关的一些参考文献。那么今天我分享的议题就到这里,谢谢大家!

 

注意:可于下方附件获取本次峰会演讲完整PPT!其它议题演讲PPT经讲师同意后会陆续放出!


[2022冬季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2021-10-27 19:22 被Editor编辑 ,原因:
上传的附件:
收藏
点赞18
打赏
分享
最新回复 (17)
雪    币: 2933
活跃值: 活跃值 (2216)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2021-10-28 09:14
2
0
支持下
雪    币: 4530
活跃值: 活跃值 (2367)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
LeadroyaL 活跃值 1 2021-10-28 09:27
3
0
优秀
雪    币: 4993
活跃值: 活跃值 (817)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
猡蠡 活跃值 2021-10-28 10:05
4
1
感觉牵扯技术挺多,实际应用场景有限,感觉就是大公司有钱任性做的一个事情
雪    币: 58
活跃值: 活跃值 (186)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
hhstudy 活跃值 1 2021-10-28 10:10
5
0
Hey,板凳我来坐
雪    币: 641
活跃值: 活跃值 (287)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
风铃i 活跃值 2021-10-28 11:34
6
0
抛出的几个问题没法解决的话应用场景有限,在系统内COW在内核都很难处理,别说在系统外面了
雪    币: 11198
活跃值: 活跃值 (7406)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
一半人生 活跃值 5 2021-10-28 15:31
7
0
ept hook + 10号vmexit事件(#24),基于kvm做虚拟化沙箱有好有坏。
雪    币: 391
活跃值: 活跃值 (696)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wowocock 活跃值 1 2021-10-29 16:56
8
1
想法挺好,不过问题在于这种东西,随着不断深入,坑越来越多,所以很难实现产品。
雪    币: 103
活跃值: 活跃值 (170)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lcys 活跃值 2021-11-1 10:09
9
0
wowocock 想法挺好,不过问题在于这种东西,随着不断深入,坑越来越多,所以很难实现产品。
产品还是TCG方便些
雪    币: 1012
活跃值: 活跃值 (712)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
jhthaotian 活跃值 1 2021-11-1 15:51
10
0
风铃i 抛出的几个问题没法解决的话应用场景有限,在系统内COW在内核都很难处理,别说在系统外面了
目前抛出的一些问题,已经解决。由于演讲时间超时,所以不能在会议上讲解。
雪    币: 1012
活跃值: 活跃值 (712)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
jhthaotian 活跃值 1 2021-11-1 15:51
11
0
wowocock 想法挺好,不过问题在于这种东西,随着不断深入,坑越来越多,所以很难实现产品。
的确是。如果后期遇到特别大的坑,无法填上的,就只能在虚拟机中放一个agent了。
雪    币: 1012
活跃值: 活跃值 (712)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
jhthaotian 活跃值 1 2021-11-1 15:52
12
0
lcys 产品还是TCG方便些
tcg,不能支持gpu虚拟化,有很多软件无法运行。硬伤
雪    币: 1012
活跃值: 活跃值 (712)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
jhthaotian 活跃值 1 2021-11-1 16:00
13
0
hhstudy Hey,板凳我来坐


最后于 2021-11-1 16:00 被jhthaotian编辑 ,原因:
雪    币: 1012
活跃值: 活跃值 (712)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
jhthaotian 活跃值 1 2021-11-1 16:01
14
0
猡蠡 感觉牵扯技术挺多,实际应用场景有限,感觉就是大公司有钱任性做的一个事情
个人业余时间做的一个东西。非公司产品
雪    币: 103
活跃值: 活跃值 (170)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lcys 活跃值 2021-11-1 18:39
15
0
jhthaotian tcg,不能支持gpu虚拟化,有很多软件无法运行。硬伤
看看UTM这个项目,KVM做沙箱在项目交付的时候就知道有多坑了,依赖硬件虚拟化、嵌套虚拟化的原因你无法在云环境上KVM套娃,信创项目国产化CPU兼容问题,给你个arm服务器咋跑X86?,跑跑样本TCG完全够了 又不做外挂
雪    币: 103
活跃值: 活跃值 (170)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lcys 活跃值 2021-11-1 18:57
16
0
不过你们是甲方,和乙方思维不一样,自己内部搞个x86沙箱流程就建议KVM了,不过后续你想支持arm mips又有工作量了
雪    币: 202
活跃值: 活跃值 (241)
能力值: ( LV4,RANK:41 )
在线值:
发帖
回帖
粉丝
17
0
1. pdb解析没必要用wine,例如 https://github.com/willglynn/pdb
感觉是时间紧促随意解决的

2. 断点使用int3, 如果你读了tcg的实现后你肯定不会这样实现,因为代码的模拟是实时翻译,如果你修改了代码,就会发生重翻译,我觉得没有必要去修改代码,你有多种方式可以实现,比如翻译过程中会有映射表,你直接拦截物理执行地址,内部完全没有感知,或者是你都开始调试了,你完全可以将执行模式换成单步模式,那么每次执行都会发出信号。其他还有很多方式,建议修改tcg来搞。

3. 内存修改,你可以做出修改内部实现,但是内部读取却还是原来的样子,比如代码检查,读取的和执行的可以不一致,因为这个完全由映射来的,读取的时候本身可以产生分离。
雪    币: 1012
活跃值: 活跃值 (712)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
jhthaotian 活跃值 1 2022-4-6 11:44
18
0
wx_卖女孩的小火柴_588616 1. pdb解析没必要用wine,例如 https://github.com/willglynn/pdb 感觉是时间紧促随意解决的 2. 断点使用int3, 如果你读了tcg的实现后你肯定不会 ...


最后于 2022-4-6 11:45 被jhthaotian编辑 ,原因:
游客
登录 | 注册 方可回帖
返回