181111 逆向-HCTF

本文详细介绍了HCTF中Reverse挑战的解析过程,重点分析了Spiral驱动的检查机制,包括sub_12F430和spiral_core.sys的处理流程。涉及到硬件虚拟化技术,如VMXON、VMLAUNCH、VMEXITPROC,以及CPUID、INVD、VMCALL等指令的处理。通过解码和模拟执行,最终解决数独式校验问题。
摘要由CSDN通过智能技术生成

感谢HCTF的师傅们献上的题目~
相对而言比较喜欢v爷爷出的spiral(虽然有多解(斜眼
其他几题难度差了点儿_(:з」∠)_

Reverse

spiral

main函数中比较简单
输入通过argv[1]送入
sub_12F9E0中检查格式,并返回除"hctf{}"外的字符个数,要求为73
sub_12FB10中分隔输入,处理为46+27两段内容
sub_12F430中检查第一段46个字符
sub_12F070中解码并写出一个驱动
sub_12E430中在注册表里注册该驱动

下文所有关于硬件虚拟化的了解都是基于做题时搜索查询的,可能会有不少错误,还望指出海涵。

check1(sub_12F430)

将每个字符分为高5位和低3位,分别保存成两个数组
根据低3位在sub_12F650中变化高5位,变化的方法都是很简单的加和异或
然后将两个数组合成一个,最后比较
反向处理根据结果的奇数位字节反向变换偶数位字节,再合并即可

check2(spiral_core.sys)

在写出的函数中将后27个字符放入字节数组中,即作为驱动的data保存
动调可获得完整内容

入口

驱动入口为DriverEntry,几个处理函数用处都不大,关键只有sub_403310这一个函数
开始read了cr寄存器和msr寄存器,申请了几个内存,保存了各种寄存器,不用太关心
但是从sub_401596中可以看到一个不常见的指令:vmxon
这里开始才显露出这个题目的真正獠牙:硬件虚拟化
vmxon表示VMX(Virtual-Machine Extensions)的启动

关键在sub_402B60中的一系列操作
大部分的东西其实都是不用看的,我估计出题人也不是自己一句一句写的(XD,调用的就两个函数VM_WRITE和READ_MSR

关键在最后一个sub_401631,里面是另一个不常见的指令:vmlaunch
vmlaunch表示Guest虚拟机启动,下面运行的指令就都跟外层物理机无关了

相关资料中的流程高度相似,可以以此参考

vmlaunch以后,最大的区别就是一些特殊指令将会被VMX捕获,进入到VMExitProc函数中进行处理
这个函数在0x402f61处绑定到结构体中

vmwrite(0x6C16, (int)VMExitProc);

默认状态下,IDA似乎没有识别到这个函数,只是一个Dword
需要自己找到对应的地址按P来CreateFunction

VMEXITPROC分析

这个函数中基本都是环境的保存和恢复
核心逻辑在sub_402880中
开头的五个调用可以参照上文的相关资料恢复出符号

//获取本次Exit的详细信息
ULONG ExitReason = VMRead_ULONG(VMX_VMCS_RO_EXIT_REASON);//0x4402
ULONG ExitInterruptionInformation = VMRead_ULONG(VMX_VMCS_RO_EXIT_INTERRUPTION_INFO);//0x4404
ULONG ExitInstructionLength = VMRead_ULONG(VMX_VMCS_RO_EXIT_INSTR_LENGTH);//0x440C
ULONG ExitQualification = VMRead_ULONG(VMX_VMCS_RO_EXIT_QUALIFICATION);//0x6400

这里的关键是ExitReason,也就是下面处理的switch的变量
可以参考这篇资料

对照发现,VMExitProc中对CPUID、INVD、VMCALL、CR_ACCESS、MSR_READ、MSR_WRITE这几条指令有特殊处理,之后我们需要特殊分析

通过分析几个handler可以大体构建出整个程序的目的

在处理handler之前,首先要声明两个数据结构
几个handler都是在操作他俩,而IDA由于丢失符号导致这两个结构识别的很破碎,需要自己根据handler和上下文语义来恢复
主要是最后检查的时候范围为data的9x9,而对vm_code的几次操作都不超过10

int vm_code[10]
int data[9][9]
cpuid_handler

根据eax选择对vm_code异或的数组

invd_handler

根据eax变换vm_code
值得一提的是dword_405374这个数组是vm_code-4(byte)的地方

vmcall_handler

首先拆解eax,高1字节作为command,高2字节处理后作为data的index,低2字节选择是否逆序,低1字节作为input的index

主要是根据command和vm_code来处理data
这里有一个很容易误解的点
Dword_405174(point_data)处是一个指针,指针指向data[9][9]的首地址&data[0][0]
从汇编可以很容易看出来

.text:00401CE9                 mov     eax, point_data
.text:00401CEE                 mov     ecx, [eax+edx*4]

我们知道,在C语言中定义一个数组a[10],那么a就是常量&a[0]。此时如果再令指针p=&a[0]=a,则a[x]等价于*(a + x*4)等价于*(p+x*4)等价于p[x]
也就是说,a[x]和p[x]实际上是相同的
而在IDA中,或者说是汇编中,p和a却是两个量:a是常量地址,在汇编中表示为数组首地址,而p则是一个指针,指向数组首地址。
这意味着对a查看交叉引用找不到对p的调用

这么讲很好理解,但是在汇编里我觉得有点懵orz

好的,说了这么多其实就是说point_data等价于data

vm_code对应的几个函数都是修改data的
最后有两个与众不同的,0xdd和0xff
0xdd里有vmxoff的调用,显然是退出虚拟机用的
0xff里则是一个检查data的函数
简单理一下可以看出来&

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值