背景:
去年利用开源VT框架做简单应用,Windows x64内核实现系统探针(Msr/Ept Hook),VT可以欺骗PG及Rootkit操作。跳出安全视角审视虚拟化一入深似海,业余学习笔记分享。
环境部署:
Os: Linux localhost.localdomain 2.6.18-419.el5 #1 SMP Fri Feb 24 22:47:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux,Linux内核 2.6.20以后集成KVM,从最原始来探索虚拟化。
Centos5 install
Source Code Download: https://sourceforge.net/projects/kvm/files/?source=navbar
Centos5 ISO Download: http://mirror.nsc.liu.se/centos-store/5.0/isos/i386/
Centos5 Yum Update: https://github.com/astj/docker-centos5-vault/blob/master/yum.repos.d/CentOS-Base.repo
Centos5key认证:CentOS GPG Keys
VS2017 Remote Debug Gdb Centos5 Event
Cmake项目创建:
1) issues: Finished copying files.CMake version '2.6.0.0' identified on the remote,CMake 3.8.x or above is not available on the remote system.
Cmake版本过低,Cmake升级依赖Gcc(c++11),Gcc 4.8 version以上才可以支持c++11:
2) issues: Current Gcc: gcc version 4.1.2 20080704 (Red Hat 4.1.2-55)
参考:https://www.cnblogs.com/edda/p/13061554.html 这个过程比较耗时间,请多点耐心。
3) issues: 升级至Cmake 3.10,Vs2017远程调试需要3.8.x以上的Cmake,不升级gcc,./bootstarp编译过程中会出现不支持c++11
参考:https://blog.csdn.net/u013714645/article/details/77002555
4) issues: make过程中遇到openssl.c:(.text+0xf7a): undefined reference to `EVP_PKEY_id'问题:
参考:升级Openssl(也要安装openssl-devel):https://www.cnblogs.com/madsnotes/articles/6285727.html
CMake工程页面大致如下,配置文件CMakeSettings.json。
Linux项目创建:
工程项目下会有readme\readme.html,操作即可:
Centos5从默认gcc 4.1.8,gcc 4.8或更高支持c++11,这里先不用c11以上的标准,用99/89.
1) Issues: error : unrecognized command line option "-Wempty-body",低版本不支持这个参数/删除:
如下图所示,删除%(CppAdditionalWarning)和empty-body即可:
2) Issues: /usr/bin/ld : error : cannot find -lGL
sudo yum install mesa-libGL-devel mesa-libGLU-devel
sudo yum install freeglut-devel
编译/执行如下:
VS远程调试微软官方文档:
- https://docs.microsoft.com/en-us/cpp/linux/cmake-linux-project?view=msvc-160
- https://devblogs.microsoft.com/cppblog/visual-c-for-linux-development-with-cmake/
KVM编译:
KVM1.0 Download:
https://sourceforge.net/projects/kvm/files/kvm/1/kvm-module-1.tar.gz/download
Cmake方式会出现问题,Centos5原生Gcc是顺利编译成功(kvm1.0),升级gcc编译会出现问题,不过比较好解决,自行谷歌即可。
编译成功生成kvm.ko:
最终文章环境如下:
Centos5.0 + gcc 4.1.x + Vs2017(Linux) + KVM.ko(1.0) + libKvm(1.0),编译完成之后,编写r3来调用kvm.ko探索使用,参考libkvm学习。
LibKVM/KVM 源码分析:
Libkvm/Kernel:
libkvm_main分为详细分析四个函数,kvm_init & kvm_create & kvm_show_regs & kvm_run
kvm_init
初始化R3负责打开驱动kvm文件,获取句柄。申请kvm_context_t结构提内存(保存上线文环境),测试回调赋值及返回kvm结构。
kvm_create:
1) r = ioctl(fd, KVM_SET_MEMORY_REGION, &low_memory);
case KVM_SET_MEMORY_REGION: {
struct kvm_memory_region kvm_mem;
r = -EFAULT;
// 首先将 用户态数据拷贝内核态
if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem))
goto out;
// 分配内存
r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
if (r)
goto out;
break;
}
用户态对应Kernel:
内核态:
Vcpu_load里面会做Vmcs的write操作,其实就是不同状态Exit时候处理用到,后面再对vmcs做相关介绍。
分别设置了如下状态:
HostGdtrBase = 0x00006c0c,
// HostIdtrBase = 0x00006c0e,
HostTrBase = 0x00006c0a,
HostIa32SysenterEsp = 0x00006c10,
2) r = ioctl(fd, KVM_CREATE_VCPU, 0);
用户态
// 发送KVM_CREATE_VCPU
r = ioctl(fd, KVM_CREATE_VCPU, 0);
if (r == -1) {
printf("kvm_create_vcpu: %m\n");
exit(1);
}
内核态:
创建vcpu精髓是vmcs申请/填充,kvm_vcpu_setup()函数的主要的工作。这部分在成熟的框架里面很庞大,16bit/32bit/64bit不同的区域都有填充,kvm1.0代码量就会小很多,后面做详细的填充介绍。
)
vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return); / 22.2.5 /,kvm_vmx_return入口函数.
kvm_show_regs
r = ioctl(fd, KVM_GET_REGS, ®s);
从内核态获取寄存器状态等操作
case KVM_GET_REGS: {
struct kvm_regs kvm_regs;
r = -EFAULT;
if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
goto out;
r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
if (r)
goto out;
r = -EFAULT;
if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs))
goto out;
r = 0;
break;
}
kvm_run
r = ioctl(fd, KVM_RUN, &kvm_run);
负责读取Guest和进入虚拟机等操作
kvm_do_inject_irq() --> inject_rmode_irq() --> kvm_read_guest()
下面就是进入vm汇编代码
#endif
/* Enter guest mode */
"jne launched \n\t"
// 进入
"vmlaunch \n\t"
"jmp kvm_vmx_return \n\t"
// 退出
"launched: vmresume \n\t"
".globl kvm_vmx_return \n\t"
"kvm_vmx_return: "
/* Save guest registers, load host registers, keep flags */
1.0的代码启动还是有__asm内联汇编
梳理libkvm如下:
在进入调试内核环节之前,Libkvm用于观察学习,虚拟机中要开启嵌套虚化,如下:
使用insmod kvm.ko来加载内核,lsmod | grep kvm 加载成功,/dev/kvm如下所示:
这时候可以远程Debug Libkvm或者编写的R3程序了:
Intelx86_x64,Kvm原理性检测一致列举部分如下:
1) cpu_has_kvm_support()
检测CPUID.1:ECX.VMX[bit 5] 是否支持vt
2) vmx_disabled_by_bios
读取msr_ia32_feature_control 检测 lock
3) kvm_init_debug
创建debugfs目录kvm
4) setup_vmcs_descriptor
virtual machine control structure
rdmsr msr_ia32_vmx_basic_msr
高位 size = vmx_msr_high & 1fff
revision_id 要和msr版本一致等等
Vt初始化过程,原来再博客写过一点笔记:https://blog.51cto.com/u_13352079/2545416
虚拟化书籍推荐:
《Intel白皮书》
https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html
《处理器虚拟化技术》邓志 Windows
《深度探索Linux系统虚拟化》王柏生 谢广军 Linux
其它Blog:
- https://www.wilderssecurity.com/forums/sandboxing-virtualization.98/
- https://bbs.pediy.com/thread-257190.htm
- https://www.bookstack.cn/books/learn-kvm
后记:
有想过根据Intel手册学习抄写vt虚拟化框架,尝试两次都以失败告终。能力不行除外,参考项目过于庞大(别人维护了很多年),给人感觉成熟量大的项目越难二次开发,从Win转Linux学习的时候,都是用老古董来入门研究,麻雀虽小五脏俱全。
希望本系笔记能够和大家一起交流进步(有错误之处请指出更正)。
BY:先知论坛
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论