一句话概括就是腾讯自家的虚拟化加密壳。把腾讯的安全产品拉入 PE 工具,看到区段中有 .tvm0
那就没跑了。
这次还原用到的demo是前段时间 游戏安全技术竞赛的决赛附加题 一个非常好的demo,驱动基本上全vm了。
还要特别感谢 这位大佬放出来的脱壳版 ,给我节省了许多验证还原效果的时间。
还原脚本项目地址:xx_tvm
文档我也只说明了一些明显的点,还是看代码更加清晰。
然后给你的idapython
安装以下的库:
1.
可优化成:
直接特征识别即可,请参考idapython/TVMunicornTrace.py .tvmFunTask.mabe_1()
2.
可优化成:
直接特征识别即可,请参考idapython/TVMunicornTrace.py .tvmFunTask.mabe_2()
3.
可优化成:
直接特征识别即可,请参考idapython/TVMunicornTrace.py .tvmFunTask.mabe_3_4()
4.(类似 3)
可优化成:
直接特征识别即可,请参考idapython/TVMunicornTrace.py .tvmFunTask.mabe_3_4()
去混淆前:
去混淆后:
虚拟机的大致架构如下,非常标准。
实际上tvm有多个handle分发器和多张handleTable,但是它们的作用、内容完全一致,所以我就只画出一个handle分发器,下面也只讲解一张handleTable
使用unicorn 跟一次tvm入口到出口,脚本参考:idapython/TVMunicornTrace.py
初始rsp设置为 0x1800
入口:(已去混淆) 完整文件请查看trace_file/tvm入口到出口 去混淆.log
,
未去混淆的查看trace_file/tvm入口到出口 未去混淆.log
从 1400d2ffc
到1400d315f
,tvm第一次保存进入虚拟机前的寄存器状态:
接下来是第二次保存进入虚拟机前的寄存器状态:
从1400d3160
到1400d30aa
,保存状态如下:
接下来保存 虚拟机指令起始点和虚拟机寄存器的起始指针
结构如下:
14006024c
这是当前函数的虚拟指令起始点,可以先记住,后面就知道为什么我这么说了。
接下来进入
进call,return地址入栈:
这个函数,它也会保存一下寄存器状态,但是没啥用:
保存的状态如下:
然后会把V_RIP换个位置;
接下来就开始处理虚拟指令了。先把栈空间的格式整理一下:(这个地方非常重要)
其实只需要记住 R10放着V_REG_P 和 [rbp+8] 放着 V_RIP 。
这是一段 tvmhandle的分发(tvmopcode的处理方式)
[rbp + 8] 是 V_RIP,放入r9,然后从[R9] 取出 tvmopcode 放入r8b 然后异或 0x5D,然后 r9 +1(上面是混淆过的,实际效果就是 + 1 )。
R8b - 1 如果大于0xC8,就跳转到1400D9954
,说明这是未知的tvmopcode,出错。1400D9954
是int3指令。
然后 handleTable 放入 R9,取表项 [R9 + R8 *8],即为这个handle的偏移,加上基址0x140000000,即为这个handle 的实际处理地址:1400d60f2,通过 jmp r8 跳转过去。
(可以看到 取得第一个 tvmopcode 是 0xe8 ,和上面图中的是一样的)
注意,tvm有多张handleTable,但是里面的内容都是一样的。所以拿到一张表就行了
从 tvmopcode^0x5d - 1 < 0xC8
可以推测一共有 0xc8 ( 0~0xc7 )个 tvmopcode,例:
现在我们知道,tvm的handleTable有0xc8个有效项,我们就可以遍历handleTable,并且静态跟踪出handle。看它是如何处理的:
导出handle代码(idapython/TVMHandleOut.py
)
补充:虽然handle有0xc8个有效项,但是很多是重复的,是留作拓展用的,真正有效的handle就 80个:
左边 是 handle处理地址,右边是 tvmopcode
并在在 当前文件夹/handleout 文件夹内,输出全部handle静态跟踪(运行脚本的同时会对handle去简单的混淆)
:(刚好80个不相同的handle,文件名用 tvmopcode)
一共有80个不同功能的tvmopcode,为节省篇幅,我这里挑一个常见的讲解,全部的handle分析,其余的全部放在(handle_out/
)
(那个特别多的是int3,应该是预留以后更新用的)
我静态跟踪handle是以 jnb 为结尾的(就是判断是否大于0xc8后的jnb),所以跟踪文件后半段有一些不用看。
我对 tvmAsm的命名规则:
我这里直接将全部tvmAsm展示出来:(参考 idapython/deTvm.py . tvmHandleTableInit()
)
解释:
TVMTABEL.append 第一个参数是我给tvmAsm取的名字,第二个参数就是 tvmopcode,第三个参数是:如果这个handle要取虚拟寄存器,就必须通过 这个值解密取得虚拟寄存器,就像是我上文中解释的:
这里再挑几个特殊说明一下:
把tvm的跟踪规则写好后,就可以跟踪导出这个函数的虚拟化控制流:跟踪参考
idapython/deTvm.py . traceTask.track()
这是我挑的一个短的函数:0x140001250
参考trace_file/sub_0x140001250.log
使用函数traceTask.track(0) + traceTask.traceOut()
,输出如下
可能会好奇这些 PO_reg 怎么来的,其实这是我对 traceCode的优化:
正常的取 虚拟机寄存器 都是 [r10 + xxx],r10 就是 V_REG_P,前面说过了,看下面这一段(前面也出现过)。
例如 PO_r8 其实就是 [r10 + 0x48]
所以 tvmAsm对 PO_reg 操作 可以理解为对虚拟机外的真实寄存器操作。
这里我使用了 标记working + 赋值表记录 的方法,将所有有意义的 tvmAsm找出来。
先说哪种tvmAsm会被标记为 working:(标记为working表明至少可以还原出一条原始Asm)
只要标记好这几个点,就能还原出全部的Asm。参考(idapython/deTvm.py . traceTask.track()
)
那么我们标记好后,这段 tvm指令就如下:
箭头指着的就是标记为working的TraceCode。那么接下来要干嘛,就很清晰了,把相关的traceCode找出来(变量溯源)。
例子1:
这一句被标记为working,我们找他使用的参数的赋值语句,直到 找到 整数 或 PO_reg
我们把 [r10 + 0xa8]的赋值语句找出来(往上找):
这一句用到了 [r10 + 0xb8],找它的赋值语句:
又是 [r10 + 0xb8],再往上找:
用到 [r10 + 0xb0] 和 [r10 + 0xa0],往上找:
[r10 + 0xa0]找到尽头了,[r10 + 0xb0]还没找到尽头,继续网上找[ r10 + 0xa8 ]的赋值语句:
找到尽头,是将 PO_rsp 放入。我们把这些 traceCode放在一起:
参考 idapython/deTvm.py . traceTask.VRegRecord()
这样也有点不好看,用变量传播优化一下:
参考idapython/deTvm.py . tvmToAsm.optimize()
这一些 traceCode,就可以还原出一句 Asm:(以下我们对这一段可还原成Asm的TraceCode集合统称为一个 tvmToAsm 结构 )
于是这一段就可以还原成:
为什么是 sub rsp,0x28
而不是 lea rsp,[rsp - 0x28]
是有讲究的:
看traceCode中的一句 v_add_oregll_iregll_iregll_oregl
,他是有输出 rflag的,并且放入的位置就是 PO_rf,说明这一句ASM是会影响标志位,而 lea
是不影响标志位的,所以将它还原成 sub
。
我们顺势对这个函数的所有被标记为working 的traceCode进行变量溯源+优化,那么最后就可以得到:tvmToAsmAll
一个函数内的所有 tvmToAsm 组成一个 tvmToAsmAll , 下图中一段一段的就是 tvmToAsm
看,真正有效的就这一些,其余的都可以看作花指令。所以这个函数的原始ASM就是:(手动还原)
上文说过,tvm不能模拟全部的Asm,所以有些Asm需要暂时退出虚拟机执行,然后再返回虚拟机:
我们到0x1400c7588
,然后往下跟(中间是还原真实寄存器),
直到出现 mov rsp,[rsp] ,之后的下一句就是真实需要执行的ASM了。即为 call sub_140005E38。
接下来会重新进入虚拟机,步骤和上文进入虚拟机的步骤大致相同。
所以 v_jmp_ll 是最容易还原成 Asm 之一的 tvmAsm了。
参考idapython/deTvm.py . tvmToAsm.vjmp_handle()
关于如何找到workingTraceCode的相关traceCode,我的方案如下:(如果你有其他方案,可以不用看这一段)
把全部traceCode的赋值语句找出来,然后给相关虚拟机寄存器添加赋值记录,形成一张赋值表,例如:
我就可以得到这么一张表:
当需要检索这一句traceCode的相关traceCode时:
就可以直接查表,先找到[ r10 + 0xa8 ]
的赋值记录栈traceTaskRegList
,然后通过地址找到最近的一次赋值traceTaskReg
,然后traceTaskReg
记录了这一句traceCode,就可以找到了。
于是就找到了相关traceCode:
因为是将 PO_reg 赋值给它,所以到此检索完毕,如果不是,则按照相同的方法继续往上找。
相关代码参考:idapython/deTvm.py . traceTask.VRegRecord()
例如有两个连续的 tvmToAsm,导出的相关traceCode如下:
我们可以发现,有两段相关traceCode是相同的,这就出现问题了:
第一个tvmToAsm可以翻译成 xor edi,edi
,那么第二个tvmToAsm能翻译成什么呢?
如果我们人为识别,就可以将其翻译成 mov ecx,edi
,因为 [r10 + 450]
在前面已经放入了 PO_rdi
,下面又取它放入 PO_rcx
。
于是我们可以进行优化,如果 有一句 v_mov_iregx_iregx(PO_reg , xxxx)
那么我们就可以将 xxxx
的上一次赋值标记为PO_reg
,
还是以上面的那一段代码为例:
[r10 + 0x450]上一次赋值语句为:
我们可以将其标记为 PO_rdi
,那么当其他的workingTraceCode向上进行查找赋值表的时候,就可以找到PO_rdi
,于是就优化为了:
实现代码参考:idapython/deTvm.py . traceTask.VRegRecord()
push:
这是两个连续的 tvmToAsm,
如果按照一般的分析方式,那么这两句可以翻译为:
乍一看没什么问题,就是将 push r13
分开成两句执行,可是如果是pop
,那么情况就有点不同了:
pop:
如果按照一般的分析方式,那么这两句可以翻译为:
这就出问题了,这两句并不等于 pop r13
指令,那么问题出在哪呢,我们取消掉变量传播优化再看看:
问题就出在,这两句 workingTraceCode在进行变量溯源时,都找到了 0x14004dca7
这一句,
将 PO_rsp 放入虚拟机寄存器 [r10 + 0xa8],并且在第一句workingTraceCode中,又更改了 PO_rsp的值,所以导致出错。
幸运的是这种情况只会出现在 push 和 pop 中(参考idapython/deTvm.py . tvmToAsmAll.outerror()
),
所以我们要对 push 和 pop 特殊处理,请参考:idapython/deTvm.py . tvmToAsmAll.findPushAndPop()
特殊处理,优化后的 push 和 pop:
push:
pop:
这就清晰很多了。
前置知识:
各个标志位的位置:
tvm巧妙的利用了and sub setz je 这四种指令模拟一个jcc,例如:
(v_je 的跳转是通过 加减 V_RIP 实现的,我这里直接优化成 绝对地址,省了我们去计算)
上面的代码,先保留 rflag 的zf位,然后再减去zf位,如果结果为0,那么 V_RIP 就变成 v_je 的第二个操作数 0x14003c274
否则 V_RIP变为0x14003c1fe
于是,上面这段tvmasm可以翻译为:
第一个tvmToAsm:
如果 zf = sf = of = 0,则V_RIP = 0x1400369ec
,否则 V_RIP = 0x140036ac6
(其实就是下面那一段,因为优化了所以地址对不上)
第二个tvmToAsm:
如果 zf = 0 且 sf = of = 1,则V_RIP = 0x1400369ec
,否则 VRIP = 0x1400368ef
于是,上面这段tvmasm可以翻译为:
JE 的特征 0x40 0x40 (看上图你就知道是什么特征了)
JG 的特征 0x8c0 0x0 0x8c0 0x880(看上图你就知道是什么特征了)
全部的jcc特征:(代码参考idapython/deTvm.py . tvmToAsm.vjcc_handle()
)
上面我说JBE JNA
的特征是0x41 0x1 0x41 0x40
这其实是错误的:
因为 这只是 jmp if ZF != CF
,真正的 JBE JNA
是 jmp if CF = 1 or ZF = 1
,
对应的特征应该是 0x41 0x1 0x41 0x40 0x41 0x41
,在这个版本的 tvm 中 ,它将 JBE JNA
错误处理成了jmp if ZF != CF
我逆了较新版本的 tvm ,JBE JNA
这里的bug就被修复了,就是0x41 0x1 0x41 0x40 0x41 0x41
。
(看来ACE部门用的tvm版本不够新啊)
参考idapython/deTvm.py . tvmToAsmAll.AllTvmAsmToAsm()
push 和 pop 在上文已经识别出来了,
jcc 在上文也识别出来了,
tvm没有模拟的Asm,也可以通过跟踪 v_jmp_ll 得到,上文也说了。
一些明显的 tvmAsm也可以直接识别原本的AsmOpcode:
如果tvmToAsm中的traceCode的tvmAsm含有以上的字符串,
那么可以直接将这个tvmtoAsm的AsmOpcode设置为对应项,例如:
可以直接将Asm的Opcode 设置成 xor,如果要翻译成Asm的话,就翻译成了 xor edx,edx
以上部分,参考代码:idapython/deTvm.py . tvmToAsm.setASMOpcode_1()
识别 lea mov add sub ,这部分比较复杂,如果是人为识别就简单。
我们先对每一个tvmToAsm内的traceCode再进行一次变量分析,列出一个赋值表,类似于上文赋值表的结构。
除此之外,我们还要对其进行标记设置,例如:
标记的结构:[handle,tvmPara,IsUseRflag],依次是处理手段、虚拟机寄存器、是否使用(输出)标志位
有了这些标记,再加上14004a507
这一句指令,我们就可以识别这个tvmToAsm的AsmOpcode了:
有了这些标记,再加上14006280b
这一句指令,我们就可以识别这个tvmToAsm的AsmOpcode了:
有了这些标记,再加上14004a82c
这一句指令,我们就可以识别这个tvmToAsm的AsmOpcode了:
有了这些标记,再加上140062837
这一句指令,我们就可以识别这个tvmToAsm的AsmOpcode了:
以上部分都只是一些简单例子,关于更加严格的 sub add lea mov
分类,参考代码:
idapython/deTvm.py . tvmToAsm.record_tage()
负责跟踪标记
idapython/deTvm.py . tvmToAsm.setASMOpcode_2()
负责分类 sub add lea mov
到这里的时候,全部 tvmToAsm 的 AsmOpcode都已经全部识别。
首先介绍一个工具函数 :GetAsmPara
可以将标记转换成Asm操作数的格式。
例子和上图是一样的。转换为标记如下:
看到140062837
这一条workingTraceCode:
v_mov_iregb_iregb ( iregb :PO_rax ,iregb :[ r10 + 0x90 ] );
代码参考:idapython/deTvm.py . tvmToAsm.mov_handle()
例子和上图是一样的。转换为标记如下:
看到14004a82c
这一条workingTraceCode:
v_mov_iregll_iregll ( iregll :PO_r8 ,iregll :[ r10 + 0xa0 ] );
代码参考:idapython/deTvm.py . tvmToAsm.lea_handle()
用上面add的例子,但是进行GetAsmPara
的是红框框起来的这两个:(对于sub的处理是一样的)
对红框的两个参数进行GetAsmPara
:
代码参考:idapython/deTvm.py . tvmToAsm.add_sub_handle()
以下都是 对 红框框框起来的 tvmPara 进行GetAsmPara
代码参考:idapython/deTvm.py . tvmToAsm.push_handle()
代码参考:idapython/deTvm.py . tvmToAsm.pop_handle()
cmp:
test:
代码参考:idapython/deTvm.py . tvmToAsm.cmp_test_handle()
举例如果 opcode是 movzx
:
其余的一样,取 opcode 对应的 第二个参数,然后 workingTraceCode的第一个参数进行GetAsmPara
代码参考:idapython/deTvm.py . tvmToAsm.movzx_movsx_movsxd_handle()
取 tvmAsmOpcode内含有 "not"字符串的那一句traceCode,取第二个参数进行 GetAsmPara
代码参考:idapython/deTvm.py . tvmToAsm.not_handle()
取 tvmAsmOpcode含有 上述opcode 的traceCode,取第三个参数进行 GetAsmPara
取workingTraceCode的第一个参数进行GetAsmPara
,以xor
为例:
代码参考:idapython/deTvm.py . tvmToAsm.xxx_handle()
上面我们已经获取了 jcc的类型,和它的两个跳转地址,虽然都是 V_RIP,
我们对这两个V_RIP往下找第一个 workingTrace
,它所在的 tvmToAsm
就是对应的跳转地址,
我们可以给这个地址的的Asm打上跳转目的地标签,例如:
可以翻译为:
参考代码:idapython/deTvm.py . tvmToAsm.jcc_handle()
这部分略,比较简单,就是通过keystone
库函数将Asm编译成十六进制机器码,然后再创建一个段,把内存写进去。详情参考:idapython/deTvm.py . tvmToAsmAll.WriteHex()
和main0
函数。
值得一提的是,我发现了keystone
的一个bug,你们可以试一下:
输出的结果是:
将其转换成 ASM,是
这明显是错误的,0x1400ef00a+0x7+0x4000d250 != 0x14000d250
就能输出正确的字节码。
所以我采用的方法是一句一句将Asm转换成HEX,如果遇到 mov reg,qword ptr[xxx]
,
就把格式改成 mov reg,qword ptr[rip + yyy]
,详情参考代码:
idapython/deTvm.py . Asm.AsmToHex()
main0
是对全部ida识别的函数进行特征分析,如果符合tvm函数特征,就对它进行还原。
可以算是一键还原全部tvm函数了,有可能有些tvm函数不符合特征,你也可以手动添加还原函数。
例如:
你知道一个函数0x140001250
它是被vm的,那么你这么写,脚本就会自动特征识别V_RIP。
如果你这个被vm的函数不符合我写的特征,但它确实是tvm的函数,那么可以这么写,自己设置V_RIP:
traceOut(0)输出的结果如下:( 基本没做处理)
如果想看 对标记working的traceCode进行变量溯源的结果,你可以这么写:
输出:
如果想进一步的进行变量传播优化还有 push、pop 优化,可以这么写:
输出:
如果想看还原成 ASM是什么样的,可以这样写:
输出:
如果想看 tvmToAsm和Asm对应起来的输出,可以这样写:
输出:
总所周知 ACE-BASE.sys 的DriverUnload函数是被vm了的,那么我们就用它来看看还原效果:
不错,很符合我对DriverUnload的想象。
左边 命名为 icxxx
的函数均为还原成功的函数。
还原脚本项目地址:xx_tvm
这个脚本只适用于这个版本的 tvm (ACE用的版本)。
新一点的tvm,虽然用的是同一套虚拟化指令集,但它会对整数进行加密,读取时进行简单的xor解密,并且新增了一些 虚拟指令。
而且 进入虚拟机的特征也有点不一样,不过对脚本进行简单的修改即可兼容。
ACE你快用新版的tvm,你现在用的版本是有bug的(JBE JNA
的模拟是错的)。
import
capstone
import
keystone
import
copy
import
unicorn
import
capstone
import
keystone
import
copy
import
unicorn
1400d302c
:
not
r10 ,R10 <
-
-
ffffffffffffffff
1400d302f
: xchg rax, r10 ,RAX <
-
-
ffffffffffffffff ,R10 <
-
-
0
1400d3031
: mov [rbp
+
var_s8], r10
1400d3035
:
not
rax ,RAX <
-
-
0
1400d3038
: xchg rax, r10
1400d302c
:
not
r10 ,R10 <
-
-
ffffffffffffffff
1400d302f
: xchg rax, r10 ,RAX <
-
-
ffffffffffffffff ,R10 <
-
-
0
1400d3031
: mov [rbp
+
var_s8], r10
1400d3035
:
not
rax ,RAX <
-
-
0
1400d3038
: xchg rax, r10
1400d3031
: mov [rbp
+
var_s8], rax
1400d3031
: mov [rbp
+
var_s8], rax
1400d5b36
: xchg rax, r11 ,RAX <
-
-
14006024c
,R11 <
-
-
0
1400d5b38
: mov rax, [rbp
+
98h
]
1400d5b3f
:
not
rax ,RAX <
-
-
fffffffebff9fdb3
1400d9148
: xchg rax, r11 ,RAX <
-
-
0
,R11 <
-
-
fffffffebff9fdb3
1400d914a
:
not
r11 ,R11 <
-
-
14006024c
1400d5b36
: xchg rax, r11 ,RAX <
-
-
14006024c
,R11 <
-
-
0
1400d5b38
: mov rax, [rbp
+
98h
]
1400d5b3f
:
not
rax ,RAX <
-
-
fffffffebff9fdb3
1400d9148
: xchg rax, r11 ,RAX <
-
-
0
,R11 <
-
-
fffffffebff9fdb3
1400d914a
:
not
r11 ,R11 <
-
-
14006024c
1400d5b38
: mov r11, [rbp
+
98h
]
1400d5b38
: mov r11, [rbp
+
98h
]
1400d9156
: push r10 ,RSP <
-
-
1500
1400d9158
: lea r10, loc_1400E1D70
+
2
,R10 <
-
-
1400e1d72
1400d915f
: lea r10, [r10
-
0A812h
] ,R10 <
-
-
1400d7560
1400d9166
: jmp r10
1400d7560
: pop r10 ,RSP <
-
-
1508
,R10 <
-
-
0
1400d9156
: push r10 ,RSP <
-
-
1500
1400d9158
: lea r10, loc_1400E1D70
+
2
,R10 <
-
-
1400e1d72
1400d915f
: lea r10, [r10
-
0A812h
] ,R10 <
-
-
1400d7560
1400d9166
: jmp r10
1400d7560
: pop r10 ,RSP <
-
-
1508
,R10 <
-
-
0
1400d9156
: jmp
1400d7560
1400d7560
: nop
1400d9156
: jmp
1400d7560
1400d7560
: nop
1400d7240
: push r10 ,RSP <
-
-
1500
1400d7242
: mov r10,
14011A470h
,R10 <
-
-
14011a470
1400d724c
: pushfq ,RSP <
-
-
14f8
1400d724d
: add r10,
0FFFFFFFFFFFBF569h
,R10 <
-
-
1400d99d9
,RF <
-
-
3
1400d7254
: popfq ,RSP <
-
-
1500
,RF <
-
-
12
1400d7255
: jmp r10
1400d99d9
: pop r10 ,RSP <
-
-
1508
,R10 <
-
-
1638
1400d7240
: push r10 ,RSP <
-
-
1500
1400d7242
: mov r10,
14011A470h
,R10 <
-
-
14011a470
1400d724c
: pushfq ,RSP <
-
-
14f8
1400d724d
: add r10,
0FFFFFFFFFFFBF569h
,R10 <
-
-
1400d99d9
,RF <
-
-
3
1400d7254
: popfq ,RSP <
-
-
1500
,RF <
-
-
12
1400d7255
: jmp r10
1400d99d9
: pop r10 ,RSP <
-
-
1508
,R10 <
-
-
1638
1400d7240
: jmp
1400d99d9
1400d99d9
: nop
1400d7240
: jmp
1400d99d9
1400d99d9
: nop
140086efa
: call sub_1400085E8 ,RSP <
-
-
17f8
/
/
这个函数被vm
1400085e8
: jmp sub_1400D2FF4
1400d2ff4
: lea rsp, [rsp
-
248h
] ,RSP <
-
-
15b0
/
/
开辟虚拟机栈空间
1400d2ffc
: mov [rsp
+
10h
], rbp
/
/
保存进入虚拟机时的寄存器状态
1400d3001
: mov rbp, rsp ,RBP <
-
-
15b0
1400d3004
: pushfq ,RSP <
-
-
15a8
1400d3005
: pop [rbp
+
0h
] ,RSP <
-
-
15b0
1400d3008
: mov [rbp
+
78h
], r14
1400d3012
: mov [rbp
+
30h
], rdx
1400d3022
: mov [rbp
+
50h
], r9
1400d3031
: mov [rbp
+
8h
], rax
1400d303f
: mov [rbp
+
60h
], r11
1400d3043
: jmp short loc_1400D3054
1400d305a
: mov [rbp
+
18h
], rbx
1400d305e
: mov [rbp
+
40h
], rsp
1400d3062
: mov [rbp
+
28h
], rdi
1400d3066
: mov [rbp
+
70h
], r13
1400d306f
: mov [rbp
+
48h
], r8
1400d3078
: mov [rbp
+
80h
], r15
1400d3085
: mov [rbp
+
58h
], r10
1400d308f
: mov [rbp
+
38h
], rsi
1400d3093
: mov [rbp
+
68h
], r12
1400d3097
: jmp loc_1400D3145
1400d314c
: mov [rbp
+
20h
], rcx
1400d3156
: pushfq ,RSP <
-
-
15a8
1400d3157
: add qword ptr [rbp
+
40h
],
248h
1400d315f
: popfq ,RSP <
-
-
15b0
1400d3160
: lea r11, [rbp
+
90h
] ,R11 <
-
-
1640
1400d3167
: push qword ptr [rbp
+
8
] ,RSP <
-
-
15a8
1400d316a
: pop qword ptr [r11] ,RSP <
-
-
15b0
1400d316d
: push qword ptr [rbp
+
18h
] ,RSP <
-
-
15a8
1400d3170
: pop qword ptr [r11
+
8
] ,RSP <
-
-
15b0
1400d3174
: push qword ptr [rbp
+
20h
] ,RSP <
-
-
15a8
1400d3177
: pop qword ptr [r11
+
10h
] ,RSP <
-
-
15b0
1400d317b
: push qword ptr [rbp
+
30h
] ,RSP <
-
-
15a8
1400d317e
: pop qword ptr [r11
+
18h
] ,RSP <
-
-
15b0
1400d3182
: push qword ptr [rbp
+
40h
] ,RSP <
-
-
15a8
1400d3185
: pop qword ptr [r11
+
20h
] ,RSP <
-
-
15b0
1400d3189
: push qword ptr [rbp
+
10h
] ,RSP <
-
-
15a8
1400d318c
: jmp loc_1400D30DC
1400d30dd
: pop qword ptr [r11
+
28h
] ,RSP <
-
-
15b0
1400d30e1
: push qword ptr [rbp
+
38h
] ,RSP <
-
-
15a8
1400d30e4
: pop qword ptr [r11
+
30h
] ,RSP <
-
-
15b0
1400d30e8
: push qword ptr [rbp
+
28h
] ,RSP <
-
-
15a8
1400d30eb
: pop qword ptr [r11
+
38h
] ,RSP <
-
-
15b0
1400d30ef
: push qword ptr [rbp
+
48h
] ,RSP <
-
-
15a8
1400d30f2
: pop qword ptr [r11
+
40h
] ,RSP <
-
-
15b0
1400d30f6
: push qword ptr [rbp
+
50h
] ,RSP <
-
-
15a8
1400d30f9
: pop qword ptr [r11
+
48h
] ,RSP <
-
-
15b0
1400d30fd
: push qword ptr [rbp
+
58h
] ,RSP <
-
-
15a8
1400d3100
: pop qword ptr [r11
+
50h
] ,RSP <
-
-
15b0
1400d3104
: push qword ptr [rbp
+
60h
] ,RSP <
-
-
15a8
1400d3107
: pop qword ptr [r11
+
58h
] ,RSP <
-
-
15b0
1400d310b
: push qword ptr [rbp
+
68h
] ,RSP <
-
-
15a8
1400d310e
: pop qword ptr [r11
+
60h
] ,RSP <
-
-
15b0
1400d3112
: push qword ptr [rbp
+
70h
] ,RSP <
-
-
15a8
1400d3115
: pop qword ptr [r11
+
68h
] ,RSP <
-
-
15b0
1400d3119
: push qword ptr [rbp
+
78h
] ,RSP <
-
-
15a8
1400d311c
: pop qword ptr [r11
+
70h
] ,RSP <
-
-
15b0
1400d3120
: push qword ptr [rbp
+
80h
] ,RSP <
-
-
15a8
1400d3126
: pop qword ptr [r11
+
78h
] ,RSP <
-
-
15b0
1400d312a
: push qword ptr [rbp
+
0
] ,RSP <
-
-
15a8
1400d312d
: jmp loc_1400D30A8
1400d30aa
: pop qword ptr [r11
+
80h
] ,RSP <
-
-
15b0
1400d30b1
: lea r11, byte_14006024B
+
1
,R11 <
-
-
14006024c
1400d30b8
: lea r10, [rbp
+
88h
] ,R10 <
-
-
1638
1400d30bf
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a8
1400d30c4
: mov [rsp], r10
1400d30c8
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a0
1400d30cd
: mov [rsp], r11
1400d30d1
: call sub_1400D5B02 ,RSP <
-
-
1598
1400d5b02
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1590
1400d5b07
: mov [rsp
+
8
+
var_8], rbx
1400d5b0b
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1588
1400d5b10
: mov [rsp
+
10h
+
var_10], rsi
1400d5b14
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1580
1400d5b19
: mov [rsp
+
18h
+
var_18], rdi
1400d5b1d
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1578
1400d5b22
: mov [rsp
+
20h
+
var_20], rbp
1400d5b26
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1570
1400d5b2b
: mov [rsp
+
28h
+
var_28], r15
1400d5b2f
: sub rsp,
68h
,RSP <
-
-
1508
,RF <
-
-
12
1400d5b33
: mov rbp, rsp ,RBP <
-
-
1508
1400d5b38
: mov r11, [rbp
+
98h
] ,R11 <
-
-
V_RIP
1400d5b42
: jmp loc_1400D9146
1400d914f
: mov r10, [rbp
+
0A0h
] ,R10 <
-
-
V_REG_p
1400d9156
: jmp loc_1400D7560
1400d756a
: call loc_1400DA21F ,RSP <
-
-
1500
1400da21f
: lea rsp, [rsp
+
8
] ,RSP <
-
-
1508
1400da224
: lea r9, loc_1400E47B0 ,R9 <
-
-
1400e47b0
1400da22e
: jmp loc_1400D8689
1400d868e
: mov [rbp
+
0
], r9
1400d8695
: jmp loc_1400DB455
1400db45f
: mov [rbp
+
8
], r11
140086efa
: call sub_1400085E8 ,RSP <
-
-
17f8
/
/
这个函数被vm
1400085e8
: jmp sub_1400D2FF4
1400d2ff4
: lea rsp, [rsp
-
248h
] ,RSP <
-
-
15b0
/
/
开辟虚拟机栈空间
1400d2ffc
: mov [rsp
+
10h
], rbp
/
/
保存进入虚拟机时的寄存器状态
1400d3001
: mov rbp, rsp ,RBP <
-
-
15b0
1400d3004
: pushfq ,RSP <
-
-
15a8
1400d3005
: pop [rbp
+
0h
] ,RSP <
-
-
15b0
1400d3008
: mov [rbp
+
78h
], r14
1400d3012
: mov [rbp
+
30h
], rdx
1400d3022
: mov [rbp
+
50h
], r9
1400d3031
: mov [rbp
+
8h
], rax
1400d303f
: mov [rbp
+
60h
], r11
1400d3043
: jmp short loc_1400D3054
1400d305a
: mov [rbp
+
18h
], rbx
1400d305e
: mov [rbp
+
40h
], rsp
1400d3062
: mov [rbp
+
28h
], rdi
1400d3066
: mov [rbp
+
70h
], r13
1400d306f
: mov [rbp
+
48h
], r8
1400d3078
: mov [rbp
+
80h
], r15
1400d3085
: mov [rbp
+
58h
], r10
1400d308f
: mov [rbp
+
38h
], rsi
1400d3093
: mov [rbp
+
68h
], r12
1400d3097
: jmp loc_1400D3145
1400d314c
: mov [rbp
+
20h
], rcx
1400d3156
: pushfq ,RSP <
-
-
15a8
1400d3157
: add qword ptr [rbp
+
40h
],
248h
1400d315f
: popfq ,RSP <
-
-
15b0
1400d3160
: lea r11, [rbp
+
90h
] ,R11 <
-
-
1640
1400d3167
: push qword ptr [rbp
+
8
] ,RSP <
-
-
15a8
1400d316a
: pop qword ptr [r11] ,RSP <
-
-
15b0
1400d316d
: push qword ptr [rbp
+
18h
] ,RSP <
-
-
15a8
1400d3170
: pop qword ptr [r11
+
8
] ,RSP <
-
-
15b0
1400d3174
: push qword ptr [rbp
+
20h
] ,RSP <
-
-
15a8
1400d3177
: pop qword ptr [r11
+
10h
] ,RSP <
-
-
15b0
1400d317b
: push qword ptr [rbp
+
30h
] ,RSP <
-
-
15a8
1400d317e
: pop qword ptr [r11
+
18h
] ,RSP <
-
-
15b0
1400d3182
: push qword ptr [rbp
+
40h
] ,RSP <
-
-
15a8
1400d3185
: pop qword ptr [r11
+
20h
] ,RSP <
-
-
15b0
1400d3189
: push qword ptr [rbp
+
10h
] ,RSP <
-
-
15a8
1400d318c
: jmp loc_1400D30DC
1400d30dd
: pop qword ptr [r11
+
28h
] ,RSP <
-
-
15b0
1400d30e1
: push qword ptr [rbp
+
38h
] ,RSP <
-
-
15a8
1400d30e4
: pop qword ptr [r11
+
30h
] ,RSP <
-
-
15b0
1400d30e8
: push qword ptr [rbp
+
28h
] ,RSP <
-
-
15a8
1400d30eb
: pop qword ptr [r11
+
38h
] ,RSP <
-
-
15b0
1400d30ef
: push qword ptr [rbp
+
48h
] ,RSP <
-
-
15a8
1400d30f2
: pop qword ptr [r11
+
40h
] ,RSP <
-
-
15b0
1400d30f6
: push qword ptr [rbp
+
50h
] ,RSP <
-
-
15a8
1400d30f9
: pop qword ptr [r11
+
48h
] ,RSP <
-
-
15b0
1400d30fd
: push qword ptr [rbp
+
58h
] ,RSP <
-
-
15a8
1400d3100
: pop qword ptr [r11
+
50h
] ,RSP <
-
-
15b0
1400d3104
: push qword ptr [rbp
+
60h
] ,RSP <
-
-
15a8
1400d3107
: pop qword ptr [r11
+
58h
] ,RSP <
-
-
15b0
1400d310b
: push qword ptr [rbp
+
68h
] ,RSP <
-
-
15a8
1400d310e
: pop qword ptr [r11
+
60h
] ,RSP <
-
-
15b0
1400d3112
: push qword ptr [rbp
+
70h
] ,RSP <
-
-
15a8
1400d3115
: pop qword ptr [r11
+
68h
] ,RSP <
-
-
15b0
1400d3119
: push qword ptr [rbp
+
78h
] ,RSP <
-
-
15a8
1400d311c
: pop qword ptr [r11
+
70h
] ,RSP <
-
-
15b0
1400d3120
: push qword ptr [rbp
+
80h
] ,RSP <
-
-
15a8
1400d3126
: pop qword ptr [r11
+
78h
] ,RSP <
-
-
15b0
1400d312a
: push qword ptr [rbp
+
0
] ,RSP <
-
-
15a8
1400d312d
: jmp loc_1400D30A8
1400d30aa
: pop qword ptr [r11
+
80h
] ,RSP <
-
-
15b0
1400d30b1
: lea r11, byte_14006024B
+
1
,R11 <
-
-
14006024c
1400d30b8
: lea r10, [rbp
+
88h
] ,R10 <
-
-
1638
1400d30bf
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a8
1400d30c4
: mov [rsp], r10
1400d30c8
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a0
1400d30cd
: mov [rsp], r11
1400d30d1
: call sub_1400D5B02 ,RSP <
-
-
1598
1400d5b02
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1590
1400d5b07
: mov [rsp
+
8
+
var_8], rbx
1400d5b0b
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1588
1400d5b10
: mov [rsp
+
10h
+
var_10], rsi
1400d5b14
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1580
1400d5b19
: mov [rsp
+
18h
+
var_18], rdi
1400d5b1d
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1578
1400d5b22
: mov [rsp
+
20h
+
var_20], rbp
1400d5b26
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1570
1400d5b2b
: mov [rsp
+
28h
+
var_28], r15
1400d5b2f
: sub rsp,
68h
,RSP <
-
-
1508
,RF <
-
-
12
1400d5b33
: mov rbp, rsp ,RBP <
-
-
1508
1400d5b38
: mov r11, [rbp
+
98h
] ,R11 <
-
-
V_RIP
1400d5b42
: jmp loc_1400D9146
1400d914f
: mov r10, [rbp
+
0A0h
] ,R10 <
-
-
V_REG_p
1400d9156
: jmp loc_1400D7560
1400d756a
: call loc_1400DA21F ,RSP <
-
-
1500
1400da21f
: lea rsp, [rsp
+
8
] ,RSP <
-
-
1508
1400da224
: lea r9, loc_1400E47B0 ,R9 <
-
-
1400e47b0
1400da22e
: jmp loc_1400D8689
1400d868e
: mov [rbp
+
0
], r9
1400d8695
: jmp loc_1400DB455
1400db45f
: mov [rbp
+
8
], r11
rsp
=
rbp
=
15b0
[
15b0
](rbp
+
0
) rflag
[
15b8
](rbp
+
8
) rax
[
15c0
](rbp
+
10
) rbp (原来的栈底)
[
15c8
](rbp
+
18
) rbx
[
15d0
](rbp
+
20
) rcx
[
15d8
](rbp
+
28
) rdi
[
15e0
](rbp
+
30
) rdx
[
15e8
](rbp
+
38
) rsi
[
15f0
](rbp
+
40
) rsp (原来的栈顶)
[
15f8
](rbp
+
48
) r8
[
1600
](rbp
+
50
) r9
[
1608
](rbp
+
58
) r10
[
1610
](rbp
+
60
) r11
[
1618
](rbp
+
68
) r12
[
1620
](rbp
+
70
) r13
[
1628
](rbp
+
78
) r14
[
1630
](rbp
+
80
) r15
rsp
=
rbp
=
15b0
[
15b0
](rbp
+
0
) rflag
[
15b8
](rbp
+
8
) rax
[
15c0
](rbp
+
10
) rbp (原来的栈底)
[
15c8
](rbp
+
18
) rbx
[
15d0
](rbp
+
20
) rcx
[
15d8
](rbp
+
28
) rdi
[
15e0
](rbp
+
30
) rdx
[
15e8
](rbp
+
38
) rsi
[
15f0
](rbp
+
40
) rsp (原来的栈顶)
[
15f8
](rbp
+
48
) r8
[
1600
](rbp
+
50
) r9
[
1608
](rbp
+
58
) r10
[
1610
](rbp
+
60
) r11
[
1618
](rbp
+
68
) r12
[
1620
](rbp
+
70
) r13
[
1628
](rbp
+
78
) r14
[
1630
](rbp
+
80
) r15
1400d3160
: lea r11, [rbp
+
90h
] ,R11 <
-
-
1640
1400d3160
: lea r11, [rbp
+
90h
] ,R11 <
-
-
1640
[
1640
](r11
+
0
) rax
[
1648
](r11
+
8
) rbx
[
1650
](r11
+
10
) rcx
[
1658
](r11
+
18
) rdx
[
1660
](r11
+
20
) rsp
[
1668
](r11
+
28
) rbp
[
1670
](r11
+
30
) rsi
[
1678
](r11
+
38
) rdi
[
1680
](r11
+
40
) r8
[
1688
](r11
+
48
) r9
[
1690
](r11
+
50
) r10
[
1698
](r11
+
58
) r11
[
16a0
](r11
+
60
) r12
[
16a8
](r11
+
68
) r13
[
16b0
](r11
+
70
) r14
[
16b8
](r11
+
78
) r15
[
16c0
](r11
+
80
) rflag
[
1640
](r11
+
0
) rax
[
1648
](r11
+
8
) rbx
[
1650
](r11
+
10
) rcx
[
1658
](r11
+
18
) rdx
[
1660
](r11
+
20
) rsp
[
1668
](r11
+
28
) rbp
[
1670
](r11
+
30
) rsi
[
1678
](r11
+
38
) rdi
[
1680
](r11
+
40
) r8
[
1688
](r11
+
48
) r9
[
1690
](r11
+
50
) r10
[
1698
](r11
+
58
) r11
[
16a0
](r11
+
60
) r12
[
16a8
](r11
+
68
) r13
[
16b0
](r11
+
70
) r14
[
16b8
](r11
+
78
) r15
[
16c0
](r11
+
80
) rflag
1400d30b1
: lea r11, byte_14006024B
+
1
,R11 <
-
-
14006024c
/
/
这个是V_RIP (即虚拟指令起始点)
1400d30b8
: lea r10, [rbp
+
88h
] ,R10 <
-
-
1638
/
/
这个是 V_REG_P
1400d30bf
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a8
1400d30c4
: mov [rsp], r10
1400d30c8
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a0
1400d30cd
: mov [rsp], r11
1400d30b1
: lea r11, byte_14006024B
+
1
,R11 <
-
-
14006024c
/
/
这个是V_RIP (即虚拟指令起始点)
1400d30b8
: lea r10, [rbp
+
88h
] ,R10 <
-
-
1638
/
/
这个是 V_REG_P
1400d30bf
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a8
1400d30c4
: mov [rsp], r10
1400d30c8
: lea rsp, [rsp
-
8
] ,RSP <
-
-
15a0
1400d30cd
: mov [rsp], r11
[
15a0
] V_RIP 虚拟指令起始点
[
15a8
] V_REG_P
1638
(虚拟机寄存器)
[
15a0
] V_RIP 虚拟指令起始点
[
15a8
] V_REG_P
1638
(虚拟机寄存器)
1400d30d1
: call sub_1400D5B02 ,RSP <
-
-
1598
1400d30d1
: call sub_1400D5B02 ,RSP <
-
-
1598
[
1598
]
=
return
add(call sub_1400D5B02 下一行的地址 是int3)
[
1598
]
=
return
add(call sub_1400D5B02 下一行的地址 是int3)
1400d5b02
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1590
1400d5b07
: mov [rsp
+
8
+
var_8], rbx
1400d5b0b
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1588
1400d5b10
: mov [rsp
+
10h
+
var_10], rsi
1400d5b14
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1580
1400d5b19
: mov [rsp
+
18h
+
var_18], rdi
1400d5b1d
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1578
1400d5b22
: mov [rsp
+
20h
+
var_20], rbp
1400d5b26
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1570
1400d5b2b
: mov [rsp
+
28h
+
var_28], r15
1400d5b02
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1590
1400d5b07
: mov [rsp
+
8
+
var_8], rbx
1400d5b0b
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1588
1400d5b10
: mov [rsp
+
10h
+
var_10], rsi
1400d5b14
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1580
1400d5b19
: mov [rsp
+
18h
+
var_18], rdi
1400d5b1d
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1578
1400d5b22
: mov [rsp
+
20h
+
var_20], rbp
1400d5b26
: lea rsp, [rsp
-
8
] ,RSP <
-
-
1570
1400d5b2b
: mov [rsp
+
28h
+
var_28], r15
[
1570
] r15 rbp
=
15b0
[
1578
] rbp
[
1580
] rdi
[
1588
] rsi
[
1590
] rbx
[
1570
] r15 rbp
=
15b0
[
1578
] rbp
[
1580
] rdi
[
1588
] rsi
[
1590
] rbx
1400d5b2f
: sub rsp,
68h
,RSP <
-
-
1508
,RF <
-
-
12
1400d5b33
: mov rbp, rsp ,RBP <
-
-
1508
1400d5b38
: mov r11, [rbp
+
98h
] ,R11 <
-
-
V_RIP
1400d5b42
: jmp loc_1400D9146
1400d914f
: mov r10, [rbp
+
0A0h
] ,R10 <
-
-
V_REG_p
1400d9156
: jmp loc_1400D7560
1400d756a
: call loc_1400DA21F ,RSP <
-
-
1500
1400da21f
: lea rsp, [rsp
+
8
] ,RSP <
-
-
1508
/
/
进call又rsp
+
8
,假装是jmp
1400da224
: lea r9, loc_1400E47B0 ,R9 <
-
-
1400e47b0
/
/
这是int3 指令的地址
1400da22e
: jmp loc_1400D8689
1400d868e
: mov [rbp
+
0
], r9
1400d8695
: jmp loc_1400DB455
1400db45f
: mov [rbp
+
8
], r11 V_RIP 放到 [
1510
]
1400d5b2f
: sub rsp,
68h
,RSP <
-
-
1508
,RF <
-
-
12
1400d5b33
: mov rbp, rsp ,RBP <
-
-
1508
1400d5b38
: mov r11, [rbp
+
98h
] ,R11 <
-
-
V_RIP
1400d5b42
: jmp loc_1400D9146
1400d914f
: mov r10, [rbp
+
0A0h
] ,R10 <
-
-
V_REG_p
1400d9156
: jmp loc_1400D7560
1400d756a
: call loc_1400DA21F ,RSP <
-
-
1500
1400da21f
: lea rsp, [rsp
+
8
] ,RSP <
-
-
1508
/
/
进call又rsp
+
8
,假装是jmp
1400da224
: lea r9, loc_1400E47B0 ,R9 <
-
-
1400e47b0
/
/
这是int3 指令的地址
1400da22e
: jmp loc_1400D8689
1400d868e
: mov [rbp
+
0
], r9
1400d8695
: jmp loc_1400DB455
1400db45f
: mov [rbp
+
8
], r11 V_RIP 放到 [
1510
]
虚拟机内RBP
=
RSP
=
1508
,R10
=
V_REG_P
[
1508
] int3指令指针
[
1510
] V_RIP
/
/
当前执行到的位置
.....
[
1570
] r15 rbp
=
15b0
[
1578
] rbp
[
1580
] rdi
[
1588
] rsi
[
1590
] rbx
[
1598
]
=
return
add(sub_1400D5B02 下一行的地址 是int3)
[
15a0
] V_RIP
/
/
虚拟指令起始点,这是不会变的
[
15a8
] V_REG_P
/
/
1638
(虚拟机寄存器),这是不会变的
[
15b0
](rbp
+
0
) rflag
/
/
这里以下是进入虚拟机前的寄存器状态
[
15b8
](rbp
+
8
) rax
[
15c0
](rbp
+
10
) rbp (原来的栈底)
[
15c8
](rbp
+
18
) rbx
[
15d0
](rbp
+
20
) rcx
[
15d8
](rbp
+
28
) rdi
[
15e0
](rbp
+
30
) rdx
[
15e8
](rbp
+
38
) rsi
[
15f0
](rbp
+
40
) rsp (原来的栈顶)
[
15f8
](rbp
+
48
) r8
[
1600
](rbp
+
50
) r9
[
1608
](rbp
+
58
) r10
[
1610
](rbp
+
60
) r11
[
1618
](rbp
+
68
) r12
[
1620
](rbp
+
70
) r13
[
1628
](rbp
+
78
) r14
[
1630
](rbp
+
80
) r15
[
1638
] UnKnow V_REG_P
=
r10
=
1638
/
/
虚拟机的虚拟寄存器从
1638
开始往下都是
[
1640
](r11
+
0
) rax
/
/
这里以下是进入虚拟机前的寄存器状态
[
1648
](r11
+
8
) rbx
[
1650
](r11
+
10
) rcx
[
1658
](r11
+
18
) rdx
[
1660
](r11
+
20
) rsp
[
1668
](r11
+
28
) rbp
[
1670
](r11
+
30
) rsi
[
1678
](r11
+
38
) rdi
[
1680
](r11
+
40
) r8
[
1688
](r11
+
48
) r9
[
1690
](r11
+
50
) r10
[
1698
](r11
+
58
) r11
[
16a0
](r11
+
60
) r12
[
16a8
](r11
+
68
) r13
[
16b0
](r11
+
70
) r14
[
16b8
](r11
+
78
) r15
[
16c0
](r11
+
80
) rflag
虚拟机内RBP
=
RSP
=
1508
,R10
=
V_REG_P
[
1508
] int3指令指针
[
1510
] V_RIP
/
/
当前执行到的位置
.....
[
1570
] r15 rbp
=
15b0
[
1578
] rbp
[
1580
] rdi
[
1588
] rsi
[
1590
] rbx
[
1598
]
=
return
add(sub_1400D5B02 下一行的地址 是int3)
[
15a0
] V_RIP
/
/
虚拟指令起始点,这是不会变的
[
15a8
] V_REG_P
/
/
1638
(虚拟机寄存器),这是不会变的
[
15b0
](rbp
+
0
) rflag
/
/
这里以下是进入虚拟机前的寄存器状态
[
15b8
](rbp
+
8
) rax
[
15c0
](rbp
+
10
) rbp (原来的栈底)
[
15c8
](rbp
+
18
) rbx
[
15d0
](rbp
+
20
) rcx
[
15d8
](rbp
+
28
) rdi
[
15e0
](rbp
+
30
) rdx
[
15e8
](rbp
+
38
) rsi
[
15f0
](rbp
+
40
) rsp (原来的栈顶)
[
15f8
](rbp
+
48
) r8
[
1600
](rbp
+
50
) r9
[
1608
](rbp
+
58
) r10
[
1610
](rbp
+
60
) r11
[
1618
](rbp
+
68
) r12
[
1620
](rbp
+
70
) r13
[
1628
](rbp
+
78
) r14
[
1630
](rbp
+
80
) r15
[
1638
] UnKnow V_REG_P
=
r10
=
1638
/
/
虚拟机的虚拟寄存器从
1638
开始往下都是
[
1640
](r11
+
0
) rax
/
/
这里以下是进入虚拟机前的寄存器状态
[
1648
](r11
+
8
) rbx
[
1650
](r11
+
10
) rcx
[
1658
](r11
+
18
) rdx
[
1660
](r11
+
20
) rsp
[
1668
](r11
+
28
) rbp
[
1670
](r11
+
30
) rsi
[
1678
](r11
+
38
) rdi
[
1680
](r11
+
40
) r8
[
1688
](r11
+
48
) r9
[
1690
](r11
+
50
) r10
[
1698
](r11
+
58
) r11
[
16a0
](r11
+
60
) r12
[
16a8
](r11
+
68
) r13
[
16b0
](r11
+
70
) r14
[
16b8
](r11
+
78
) r15
[
16c0
](r11
+
80
) rflag
1400d7234
: mov r9, [rbp
+
8
] ,R9 <
-
-
14006024c
1400d7240
: jmp loc_1400D99D9
1400d99db
: mov r8b, [r9] ,R8 <
-
-
e8
1400d99de
: xor r8b,
5Dh
,R8 <
-
-
b5 ,RF <
-
-
82
1400d99e2
: mov rdx,
25E9ECA9BDE22AEAh
,RDX <
-
-
25e9eca9bde22aea
1400d99ec
:
not
rdx ,RDX <
-
-
da161356421dd515
1400d99ef
: lea rdx, [r9
+
rdx] ,RDX <
-
-
da1613578223d761
1400d99f3
: jmp loc_1400D86A6
1400d86a8
: mov r9,
0DA161356421DD513h
,R9 <
-
-
da161356421dd513
1400d86b2
:
not
r9 ,R9 <
-
-
25e9eca9bde22aec
1400d86b5
: lea r9, [rdx
+
r9] ,R9 <
-
-
14006024d
1400d86bf
: mov [rbp
+
8
], r9
1400d86c9
: movzx r8, r8b
1400d86cd
: sub r8,
1
,R8 <
-
-
b4 ,RF <
-
-
6
1400d86d1
: jmp loc_1400D7E10
1400d7e11
:
cmp
r8,
0C8h
,RF <
-
-
93
1400d7e18
: jnb loc_1400D9954
1400d7e1e
: lea r9, word_1400DB5AA ,R9 <
-
-
1400db5aa
1400d7e25
: mov r8, [r9
+
r8
*
8
] ,R8 <
-
-
d60f2
1400d7e29
: lea r9, cs:
140000000h
,R9 <
-
-
140000000
1400d7e30
: jmp loc_1400D6558
1400d6559
: add r8, r9 ,R8 <
-
-
1400d60f2
,RF <
-
-
2
1400d655c
: jmp r8
/
/
进入handle
1400d7234
: mov r9, [rbp
+
8
] ,R9 <
-
-
14006024c
1400d7240
: jmp loc_1400D99D9
1400d99db
: mov r8b, [r9] ,R8 <
-
-
e8
1400d99de
: xor r8b,
5Dh
,R8 <
-
-
b5 ,RF <
-
-
82
1400d99e2
: mov rdx,
25E9ECA9BDE22AEAh
,RDX <
-
-
25e9eca9bde22aea
1400d99ec
:
not
rdx ,RDX <
-
-
da161356421dd515
1400d99ef
: lea rdx, [r9
+
rdx] ,RDX <
-
-
da1613578223d761
1400d99f3
: jmp loc_1400D86A6
1400d86a8
: mov r9,
0DA161356421DD513h
,R9 <
-
-
da161356421dd513
1400d86b2
:
not
r9 ,R9 <
-
-
25e9eca9bde22aec
1400d86b5
: lea r9, [rdx
+
r9] ,R9 <
-
-
14006024d
1400d86bf
: mov [rbp
+
8
], r9
1400d86c9
: movzx r8, r8b
1400d86cd
: sub r8,
1
,R8 <
-
-
b4 ,RF <
-
-
6
1400d86d1
: jmp loc_1400D7E10
1400d7e11
:
cmp
r8,
0C8h
,RF <
-
-
93
1400d7e18
: jnb loc_1400D9954
1400d7e1e
: lea r9, word_1400DB5AA ,R9 <
-
-
1400db5aa
1400d7e25
: mov r8, [r9
+
r8
*
8
] ,R8 <
-
-
d60f2
1400d7e29
: lea r9, cs:
140000000h
,R9 <
-
-
140000000
1400d7e30
: jmp loc_1400D6558
1400d6559
: add r8, r9 ,R8 <
-
-
1400d60f2
,RF <
-
-
2
1400d655c
: jmp r8
/
/
进入handle
handleTableBase
=
0x1400db5aa
Dllbase
=
0x140000000
handle
=
Dllbase
+
qword[(tvmopcode^
0x5d
-
1
)
*
8
+
handleTableBase]
handleTableBase
=
0x1400db5aa
Dllbase
=
0x140000000
handle
=
Dllbase
+
qword[(tvmopcode^
0x5d
-
1
)
*
8
+
handleTableBase]
handleTable的第
0x00
项: tvmopcode
=
(
0x00
+
1
) ^
0x5d
=
0x5c
......
handleTable的第
0x3c
项: tvmopcode
=
(
0x3c
+
1
) ^
0x5d
=
0x60
......
handleTable的第
0xc7
项: tvmopcode
=
(
0xc7
+
1
) ^
0x5d
=
0x95
handleTable的第
0x00
项: tvmopcode
=
(
0x00
+
1
) ^
0x5d
=
0x5c
......
handleTable的第
0x3c
项: tvmopcode
=
(
0x3c
+
1
) ^
0x5d
=
0x60
......
handleTable的第
0xc7
项: tvmopcode
=
(
0xc7
+
1
) ^
0x5d
=
0x95
1400d9954
:
9a
9b
98
99
9c
9d
e2 e3 e0 e1 e6 e7 e4 eb ec ed f2 f3 f0 f1 f6 f7 f5 fa fb f9 fe ff c2 c0 c1 c6 c7 c4 c5 c8 ce cf cc cd db d8 de df dc dd
23
26
27
24
2a
28
2e
2c
2d
32
33
30
31
36
37
34
35
3a
3b
38
39
3e
3f
3d
02
03
00
07
04
05
0a
0b
08
0e
0f
0d
12
13
10
17
14
15
1a
1b
18
1e
1f
1c
63
61
66
67
64
6b
69
6f
6c
71
76
77
74
7b
79
7e
7f
7c
53
50
55
5b
58
59
5e
5f
5c
1400d8eb1
:
5a
1400d5b5a
:
54
1400d5cd8
:
57
1400db3d3
:
56
1400d761b
:
51
1400da3e5
:
52
1400dabb0
:
4d
1400d8196
:
4c
1400d6c8c
:
4f
1400d82fa
:
4e
1400d6e7d
:
49
1400d7172
:
48
1400d9374
:
4b
1400daa8e
:
4a
1400db0f9
:
45
1400dae51
:
44
1400d8be2
:
47
1400d946b
:
46
1400d995a
:
41
1400daf90
:
40
1400d7a8a
:
43
1400d5e10
:
42
1400d7258
:
7d
1400daecb
:
78
1400d5d02
:
7a
1400d974c
:
75
1400d7f26
:
70
1400d8e1b
:
73
1400d8dbf
:
72
1400d8362
:
6d
1400d6fc9
:
6e
1400d7c1f
:
68
1400d63cd
:
6a
1400d9abb
:
65
1400d8431
:
60
1400d7797
:
62
1400da161
:
1d
1400d7313
:
19
1400d92b0
:
16
1400d9c5c
:
11
1400dab1e
:
0c
1400d86e2
:
09
1400d7352
:
06
1400dad5e
:
01
1400d9524
:
3c
1400dad2c
:
2f
1400d8b8d
:
29
1400d7d39
:
2b
1400d8f7b
:
25
1400d696f
:
21
1400d71f5
:
20
1400d71b3
:
22
1400d770e
: d9
1400da48c
: da
1400d74d2
: d5
1400d70ee
: d4
1400d95ad
: d7
1400d6f6c
: d6
1400d84d0
: d1
1400da357
: d0
1400d78f9
: d3
1400d7998
: d2
1400d8561
: c9
1400d624c
: cb
1400d9169
: ca
1400d64ac
: c3
1400d5c7b
: fd
1400d9dd5
: fc
1400d6913
: f8
1400dafcf
: f4
1400d7bc7
: ef
1400d7fc4
: ee
1400d9446
: e9
1400d60f2
: e8
1400d69e8
: ea
1400d9584
: e5
1400da10c
:
9f
1400d8e89
:
9e
1400d8cdd
:
95
1400d9954
:
9a
9b
98
99
9c
9d
e2 e3 e0 e1 e6 e7 e4 eb ec ed f2 f3 f0 f1 f6 f7 f5 fa fb f9 fe ff c2 c0 c1 c6 c7 c4 c5 c8 ce cf cc cd db d8 de df dc dd
23
26
27
24
2a
28
2e
2c
2d
32
33
30
31
36
37
34
35
3a
3b
38
39
3e
3f
3d
02
03
00
07
04
05
0a
0b
08
0e
0f
0d
12
13
10
17
14
15
1a
1b
18
1e
1f
1c
63
61
66
67
64
6b
69
6f
6c
71
76
77
74
7b
79
7e
7f
7c
53
50
55
5b
58
59
5e
5f
5c
1400d8eb1
:
5a
1400d5b5a
:
54
1400d5cd8
:
57
1400db3d3
:
56
1400d761b
:
51
1400da3e5
:
52
1400dabb0
:
4d
1400d8196
:
4c
1400d6c8c
:
4f
1400d82fa
:
4e
1400d6e7d
:
49
1400d7172
:
48
1400d9374
:
4b
1400daa8e
:
4a
1400db0f9
:
45
1400dae51
:
44
1400d8be2
:
47
1400d946b
:
46
1400d995a
:
41
1400daf90
:
40
1400d7a8a
:
43
1400d5e10
:
42
1400d7258
:
7d
1400daecb
:
78
1400d5d02
:
7a
1400d974c
:
75
1400d7f26
:
70
1400d8e1b
:
73
1400d8dbf
:
72
1400d8362
:
6d
1400d6fc9
:
6e
1400d7c1f
:
68
1400d63cd
:
6a
1400d9abb
:
65
1400d8431
:
60
1400d7797
:
62
1400da161
:
1d
1400d7313
:
19
1400d92b0
:
16
1400d9c5c
:
11
1400dab1e
:
0c
1400d86e2
:
09
1400d7352
:
06
1400dad5e
:
01
1400d9524
:
3c
1400dad2c
:
2f
1400d8b8d
:
29
1400d7d39
:
2b
1400d8f7b
:
25
1400d696f
:
21
1400d71f5
:
20
1400d71b3
:
22
1400d770e
: d9
1400da48c
: da
1400d74d2
: d5
1400d70ee
: d4
1400d95ad
: d7
1400d6f6c
: d6
1400d84d0
: d1
1400da357
: d0
1400d78f9
: d3
1400d7998
: d2
1400d8561
: c9
1400d624c
: cb
1400d9169
: ca
1400d64ac
: c3
1400d5c7b
: fd
1400d9dd5
: fc
1400d6913
: f8
1400dafcf
: f4
1400d7bc7
: ef
1400d7fc4
: ee
1400d9446
: e9
1400d60f2
: e8
1400d69e8
: ea
1400d9584
: e5
1400da10c
:
9f
1400d8e89
:
9e
1400d8cdd
:
95
0xe8
p_a b_ULONG64
0x3F26
*
(PULONG64)p_a
=
b_ULONG64;
v_mov_iregll_ll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
虚线以上是分析出来的
0x1400d60f5
: mov r9, [rbp
+
8
]
0x1400d6102
: mov r8w, [r9] 这里取
2
字节 (取虚拟寄存器都是取
2
字节)
0x1400d6106
: xor r8w,
3F26h
异或
3F26
(不同的handl异或的值不同) 得到 a,
0x1400d610c
: mov rdx,
0F84A86395161A270h
所以就是取虚拟机寄存器 V_REG_P
+
a
0x1400d6116
:
not
rdx
0x1400d6119
: jmp loc_1400D9077
0x1400d9078
: lea rdx, [r10
+
rdx]
0x1400d907c
: movzx r8, r8w
0x1400d9080
: mov rcx,
7B579C6AE9E5D8Eh
0x1400d908a
:
not
rcx
0x1400d908d
: add r8, rcx
0x1400d9090
: lea r8, [rdx
+
r8] p_a
=
r8
=
V_REG_P
+
a
0x1400d9094
: lea r9, [r9
+
2
] V_RIP
+
=
2
0x1400d909b
: mov rdx, [r9] b_ULONG64 从tvm指令表中取
8
字节
0x1400d909e
: jmp loc_1400DA2DD
0x1400da2ed
: mov [r8], rdx 放入 [r8],即放入 p_a
0x1400da2f0
: jmp loc_1400DA9AC
0x1400da9b4
: lea r9, [r9
+
8
] V_RIP
+
=
8
0x1400da9be
: mov [rbp
+
8
], r9 V_RIP放回[rbp
+
8
]
0x1400da9c8
: jmp loc_1400DAC79
0x1400dac7c
: mov r9, [rbp
+
8
] 这里以下属于下一个handle分发,不用看
0x1400dac89
: mov r8b, [r9]
0x1400dac8c
: xor r8b,
5Dh
0x1400dac90
: mov rdx,
0D3676A56DAFF3C65h
0x1400dac9a
: jmp loc_1400D7763
0x1400d7764
:
not
rdx
0x1400d7767
: lea rdx, [r9
+
rdx]
0x1400d776b
: mov r9,
2C9895A92500C398h
0x1400d7775
:
not
r9
0x1400d7778
: lea r9, [rdx
+
r9]
0x1400d777f
: jmp loc_1400D5B91
0x1400d5b95
: mov [rbp
+
8
], r9
0x1400d5b9e
: movzx r8, r8b
0x1400d5ba2
: sub r8,
1
; switch
200
cases
0x1400d5ba6
: jmp loc_1400D98A8
0x1400d98aa
:
cmp
r8,
0C8h
0x1400d98b1
: jnb def_1400D655C;
0xe8
p_a b_ULONG64
0x3F26
*
(PULONG64)p_a
=
b_ULONG64;
v_mov_iregll_ll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
虚线以上是分析出来的
0x1400d60f5
: mov r9, [rbp
+
8
]
0x1400d6102
: mov r8w, [r9] 这里取
2
字节 (取虚拟寄存器都是取
2
字节)
0x1400d6106
: xor r8w,
3F26h
异或
3F26
(不同的handl异或的值不同) 得到 a,
0x1400d610c
: mov rdx,
0F84A86395161A270h
所以就是取虚拟机寄存器 V_REG_P
+
a
0x1400d6116
:
not
rdx
0x1400d6119
: jmp loc_1400D9077
0x1400d9078
: lea rdx, [r10
+
rdx]
0x1400d907c
: movzx r8, r8w
0x1400d9080
: mov rcx,
7B579C6AE9E5D8Eh
0x1400d908a
:
not
rcx
0x1400d908d
: add r8, rcx
0x1400d9090
: lea r8, [rdx
+
r8] p_a
=
r8
=
V_REG_P
+
a
0x1400d9094
: lea r9, [r9
+
2
] V_RIP
+
=
2
0x1400d909b
: mov rdx, [r9] b_ULONG64 从tvm指令表中取
8
字节
0x1400d909e
: jmp loc_1400DA2DD
0x1400da2ed
: mov [r8], rdx 放入 [r8],即放入 p_a
0x1400da2f0
: jmp loc_1400DA9AC
0x1400da9b4
: lea r9, [r9
+
8
] V_RIP
+
=
8
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-5-30 15:15
被icey_编辑
,原因: