ARM平台指令虚拟化初探
0x00:什么是代码虚拟化?
虚拟机保护是这几年比较流行的软件保护技术。这个词源于俄罗斯的著名软件保护软件“VmProtect”,以此为开端引起了软件保护壳领域的革命,各大软件保护壳都将虚拟机保护这一新颖的技术加入到自己的产品中。
代码虚拟化是将程序代码编译为虚拟机指令即虚拟代码(自己定义的代码集),通过虚拟CPU解释并执行的一种方式,大致流程如下:

我们抛开ARM平台CPU流水线机制不谈,简单来说,其实CPU就是遵循一个简单的模式:循环读取、解码、执行这个过程。
0x01:为什么要指令虚拟化
首先我们来回顾下软件保护壳的发展,大致可分为三个阶段。
第一阶段:当壳完成解密目标代码时,它将不会再次控制程序,被保护程序的明文将在内存中展开。在此之前,壳可以调用一切系统手段来防治黑客的调试与逆向。
第二阶段:可以实现分段式的加解密,壳运行完毕后,并不会消失而仍然会在程序运行到某个点时再次启动。
第三阶段:其实最简单的解释是,将被保护的指令使用一套自定义的字节码(逻辑上等价)来替换掉程序中原有的指令,而字节码在执行的时候又由程序中的解释器来解释执行,自定义的字节码只有自己的解释器才能识别,也是因为这一点,基于虚拟机的保护相对其他保护而言要更加难分析。
0x02:一个简单的虚拟机实现
了解过代码虚拟化的原理之后,就是自定义一套字节码,然后使用一个解释器解释运行字节码。所以,我们要实现定义字节码与实现解释器。
字节码只是一个标识,可以随意定义,以下是自定义的字节码,只定义了几个常用的指令,其中每条指令标识都对应于一个字节码。

在定义好指令对应的字节码之后,就须要一个解释器来解释定义的指令字节码了。其实这里的解释器与物理机CPU很相似。在物理机中的程序执行需要处理器、寄存器、栈、堆等环境才可以运行起来,所以需要虚拟寄存器,栈、堆等,以下是处理器。

有了上面结构之后,就可以来动手写解释器了。解释器的工作其实就是判断当前解释的字节码是否可以解析,如果可以就把相应参数传递给相应的处理函数,让处理函数来解释执行这一条指令。以下是解释器代码。

解释器解释执行过程:
首先可以从上面看到解释器vm_CPU执行时pc会指向Vcode,也就是自定义的字节码第一个字节0xa0(对应指令为MOV),之后会判断pc指向的字节码是否为ret指令,ret指令是0xa3,如果pc指向的不是ret,进入exec_Handle函数进行字节码解释。

0xa0就对应着mov指令,所以当解释器遇到0xa0就会调用vm_mov函数来解释mov指令。

在vm_mov函数中首先把PC + 1处的一个字节和PC + 2处2个字节分别保存在dest和src中,dest是寄存器标识,在后面的switch中判断dest是哪个寄存器,在这个例子中dest是0x10,也就是r1寄存器,在case 0x10分支中就把*src赋值给r1。前4个字节就是第一条mov指令,对应着mov r1, xxxx,xxxx就是这4个字节中的后2个。
上面是一个解释器在解释执行字节码时的过程,其实很简单,就是通过一个字节码和解释函数的关系来调用相应的函数(Handle),或者通过一个很长的switch来判断每个字节码,并调用相应函数(Handle) 。而解释函数则通过执行相应的操作来模拟出一个指令。最后,把这些指令串联在一起就可以执行完一个完整的逻辑。
下面是一个简单的CrackMe完整的Vcode


下面是一个简单的CrackMe完整的源代码

0x03:测试与总结
以android平台上测试如下:

总结:
其实这只是最简单的实现,仅仅是为了学习和理解,如果想实现一个基于虚拟机的保护壳还是有些复杂,比如:随机VCode与Handle的关系映射、Handle混淆与乱序、代码变形、重定位等。
bin:
链接: https://pan.baidu.com/s/1nvbmcSp 密码: wduy
ARM平台指令虚拟化初探的更多相关文章
- ARM平台的虚拟化介绍
本篇博文主要介绍虚拟化的基本思想以及在arm平台如何做虚拟化,arm提供的硬件feature等等. 虚拟化技术简介 虚拟化技术 虚拟化是一个概念,单从这个概念的角度来看,只要是用某一种物品去模拟另一种 ...
- 【安卓安全】ARM平台代码保护之虚拟化
简介:代码的虚拟化即不直接通过CPU而是通过虚拟机来执行虚拟指令.代码虚拟化能有效防止逆向分析,可大大地增加了代码分析的难度和所需要的时间,若配合混淆等手段,对于动静态分析有着较强的防御能力. 背景: ...
- [转]ARM平台下独占访问指令LDREX和STREX
参考:ARM平台下独占访问指令LDREX和STREX的原理与使用详解 全文转载如下: 为了实现线程间同步,一般都要在执行关键代码段之前加互斥(Mutex)锁,且在执行完关键代码段之后解锁.为了实现所谓 ...
- (二十三)ARM平台NEON指令的编译和优化
ARM平台NEON指令的编译和优化 本文介绍了ARM平台基于ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7,Cortex-A8, Cortex-A9 ...
- ARM汇编指令调试方法
学习ARM汇编时,少不了对ARM汇编指令的调试.作为支持多语言的调试器,gdb自然是较好的选择.调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控.为了在 ...
- 移植mysql到嵌入式ARM平台
移植MySQL到嵌入式ARM平台 MySQL没有专门针对ARM的版本,移植到ARM没有官方文档可参考,因此,暂时参考这样一篇文档: http://blog.chinaunix.net/space.p ...
- arm平台的调用栈回溯(backtrace)
title: arm平台的调用栈回溯(backtrace) date: 2018-09-19 16:07:47 tags: --- 介绍 arm平台的调用栈与x86平台的调用栈大致相同,稍微有些区别, ...
- GNU ARM 汇编指令
第一部分 Linux下ARM汇编语法尽管在Linux下使用C或C++编写程序很方便,但汇编源程序用于系统最基本的初始化,如初始化堆栈指针.设置页表.操作 ARM的协处理器等.初始化完成后就可以跳转到C ...
- QtCreator动态编译jsoncpp完美支持x86和arm平台
如果是做嵌入式开发. 在Qt下支持JSon最好的办法,可能不是采用qjson这个库.QJson这个库的实例只提供了x86环境下的编译方法. Installing QJson-------------- ...
随机推荐
- HDU6312 Game (多校第二场1004) 简单博弈
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- STS(spring tool suite)修改默认编码
安装STS后首先要做的修改默认编码: 1.windows--perferences--general--workspace,Text file encoding设置成utf-8 2.windows-- ...
- 【bzoj2935】[Poi1999]原始生物
2935: [Poi1999]原始生物 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 145 Solved: 71[Submit][Status][D ...
- Codeforces Round #532 (Div. 2)- B(思维)
Arkady coordinates rounds on some not really famous competitive programming platform. Each round fea ...
- HDU 4507 求指定范围内与7不沾边的所有数的平方和 (数位DP)
题意:求区间[l,r]内所有与7无关的数的平方和(取模)定义与7无关的数: 1.数字的数位上不能有7 ...
- java的Spring学习1--spring引用及属性(setter,getter)注入
1.目录结构 项目->src->main->java->com.test.ppmoney 设置java文件夹为代码 在Project Structure 里的 Modules ...
- 编译安装libimobiledevice
在windows上大家可以使用iTunes来与iPhone进行通信,但是Linux上没有这类的官方软件,所以一些爱好者就破解了iTunes的通信协议,然后在Linux上实现了该协议,也就是libimo ...
- Object与String
Object转为String的几种形式 在java项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能.本文将对常用的转换方法进行一个总结.常用的方法有Object.toString ...
- Hbase 表操作
1. list 操作 2. 创建table column family, 3. 插入数据: put 'user' 3. 检索数据: scan table
- python 安装 第三方包
########1 (python 虚拟环境(如pycharm 中的 project )是一个独立的环境,所以也要重新安装一次第三方包) 上官网搜索 包 https://pypi.org/projec ...