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-------------- ...
随机推荐
- 线段树 SP2713 GSS4 - Can you answer these queries IV暨 【洛谷P4145】 上帝造题的七分钟2 / 花神游历各国
SP2713 GSS4 - Can you answer these queries IV 「题意」: n 个数,每个数在\(10^{18}\) 范围内. 现在有「两种」操作 0 x y把区间\([x ...
- IIS反向代理
- linux查找包含某个字符的文件并导出文件名
find ./ -name "*" | xargs grep -l "字符串" > 1.txt
- 再谈hive-1.0.0与hive-1.2.1到JDBC编程忽略细节问题
不多说,直接上干货,这个问题一直迷惑已久,今天得到亲身醒悟. 所以,建议hadoop-2.6.0.tar.gz的用户与hive-1.0.0搭配使用.当然,也可以去用高版本去覆盖它. log4j:WAR ...
- vi或vim下按方向键改变方向变成ABCD这类字符
遇到这种问题肯定很恼火,按方向键改变文本的方向有时候变成输入ABCD,有时候并不是我们想要的结果 解决方法: $ echo "set nocp" >> ~/.vimrc ...
- loadrunner学习--基础知识
性能测试相关术语: 1.响应时间:指系统从发出请求开始到客户端接受到所有数据所消耗的时间. 2.并发用户:指同一时刻与服务器进行数据交互的所有用户数量.计算公式F=Nvu x R/T 其中F表示吞吐量 ...
- Hive学习(一)
https://www.cnblogs.com/qingyunzong/p/8707885.html http://www.360doc.com/content/16/1006/23/15257968 ...
- Mybatis学习笔记9 - 鉴别器discriminator
鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为. 示例如下: DeptmentMapper接口定义: package com.mybatis.dao ...
- 剑指offer中经典的算法题之从头到尾打印链表
话不多说上代码: 我自己的算法是: /** * public class ListNode { * int val; * ListNode next = null; * * ListNode(int ...
- echarts自定义tooltip提示框内容
1.echarts自定义tooltip提示框内容 https://blog.csdn.net/dreamsup/article/details/56667330 2.关于Echarts的formatt ...