当前位置: 首页 > news >正文

滨州网站seo石龙网站建设

滨州网站seo,石龙网站建设,山西省新农村建设网站,网站架构价格版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ 前言 在上一篇《手写 Android Dex VMP 壳:自定义虚拟机 指令解释执行全流程》中,我们从零实现了一个简易的 Dex VMP 壳,通…

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

前言

在上一篇《手写 Android Dex VMP 壳:自定义虚拟机 + 指令解释执行全流程》中,我们从零实现了一个简易的 Dex VMP 壳,通过自定义虚拟机和指令解释执行,让应用代码在运行时以“虚拟指令流”的方式运行,大大增加了逆向分析的难度。

如果攻击者能够直接读取 Dex 中的虚拟指令流,那么依然可能进行还原。为了解决这一问题,本篇将进一步升级:在 Dex VMP 基础上引入指令流加密与动态加载

通过 AES 算法 对指令流进行加密,运行时再解密并交给虚拟机执行,从而让静态分析几乎无从下手。

Dex VMP 指令流加密 + 动态加载完整流程

Dex VMP 指令流加密 + 动态加载执行完整流程大概如下:

 ┌──────────────────────┐│     原始 Dex 指令流   │└──────────┬───────────┘│▼┌─────────────────────────┐│ 保存指令流到文件 / 内存   │└──────────┬──────────────┘│▼┌─────────────────────────┐│       使用 AES 加密      ││ (key/iv 固定或动态生成)   │└──────────┬──────────────┘│▼┌─────────────────────────┐│    得到加密后的指令流文件 ││ (静态分析无法直接还原)  │└──────────┬──────────────┘│┌────────▼──────────────┐│   Android 运行时启动   │└────────┬──────────────┘│▼┌────────────────────────┐│  动态读取加密指令流文件  │└──────────┬─────────────┘│▼┌────────────────────────┐│       AES 解密恢复      ││  (内存中得到明文指令流)│└──────────┬─────────────┘│▼┌──────────────────────────┐│   将解密后的指令流交给 VMP ││   → 自定义虚拟机解释执行   │└──────────┬───────────────┘│▼┌─────────────────────────┐│    App 正常运行业务逻辑   ││ (逆向者难以静态还原逻辑) │└─────────────────────────┘

核心思路

  1. 编译/打包阶段:把 Dex 指令流抽取出来,AES 加密,存储到文件中。

  2. 运行时阶段:App 启动时,从文件中加载 → AES 解密 → 交给虚拟机解释执行。

  3. 保护效果:静态分析拿到的 Dex 是“假代码”,真正的逻辑被加密隐藏,只有运行时内存里才会出现明文。

保存指令流到文件

在 010Editor 中搜索找到 sign 方法的字节码并复制

word/media/image1.png

新建 Hex 文件

word/media/image2.png

把 sign 方法字节码粘贴到新建的文件保存文件为 sign

word/media/image3.png

AES加解密

编写一个 kotlin 语言 AES 加解密算法工具类

package com.cyrus.vmpimport java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.SecretKeySpecobject AESUtils {private const val ALGORITHM = "AES"private const val TRANSFORMATION = "AES/ECB/PKCS5Padding" // AES 加密模式// 生成一个 128 位的 AES 密钥fun generateSecretKey(): SecretKey {val keyGenerator = KeyGenerator.getInstance(ALGORITHM)keyGenerator.init(128) // AES 128 位return keyGenerator.generateKey()}// 使用给定的密钥加密数据fun encrypt(data: ByteArray, key: SecretKey): ByteArray {val cipher = Cipher.getInstance(TRANSFORMATION)cipher.init(Cipher.ENCRYPT_MODE, key)return cipher.doFinal(data)}// 使用给定的密钥解密数据fun decrypt(data: ByteArray, key: SecretKey): ByteArray {val cipher = Cipher.getInstance(TRANSFORMATION)cipher.init(Cipher.DECRYPT_MODE, key)return cipher.doFinal(data)}// 将文件内容加密并导出到新文件fun encryptFile(inputFile: File, outputFile: File, keyFile: File) {// 读取文件内容val fileData = readFile(inputFile)// 生成密钥val secretKey = generateSecretKey()// 加密文件内容val encryptedData = encrypt(fileData, secretKey)// 保存加密后的数据到新文件(.vmp 文件)writeFile(outputFile, encryptedData)// 保存密钥到文件saveKeyToFile(secretKey, keyFile)}// 解密文件内容并导出到新文件fun decryptFile(inputFile: File, outputFile: File, keyFile: File) {// 从文件加载密钥val secretKey = loadKeyFromFile(keyFile)// 读取加密后的文件内容val encryptedData = readFile(inputFile)// 解密文件内容val decryptedData = decrypt(encryptedData, secretKey)// 保存解密后的数据到文件writeFile(outputFile, decryptedData)}// 读取文件内容并返回字节数组fun readFile(file: File): ByteArray {val fis = FileInputStream(file)val baos = ByteArrayOutputStream()val buffer = ByteArray(1024)var bytesRead: Intwhile (fis.read(buffer).also { bytesRead = it } != -1) {baos.write(buffer, 0, bytesRead)}fis.close()return baos.toByteArray()}// 将字节数组写入到文件fun writeFile(file: File, data: ByteArray) {val fos = FileOutputStream(file)fos.write(data)fos.close()}// 保存密钥到文件private fun saveKeyToFile(key: SecretKey, keyFile: File) {val fos = FileOutputStream(keyFile)fos.write(key.encoded)fos.close()}// 从文件加载密钥fun loadKeyFromFile(keyFile: File): SecretKey {val keyBytes = ByteArray(keyFile.length().toInt())val fis = FileInputStream(keyFile)fis.read(keyBytes)fis.close()return SecretKeySpec(keyBytes, ALGORITHM)}}

指令流加密

把 sign 文件放到工程中如下路径

word/media/image4.png

调用 AESUtils 类中方法对 sign 进行加密并输出加密文件和密钥

package com.cyrus.vmpimport java.io.Filefun main() {// 获取工程根目录路径val projectRoot = System.getProperty("user.dir")// 设置相对路径val encryptedFile = File(projectRoot, "vmp/sign/sign.vmp") // 相对路径val keyFile = File(projectRoot, "vmp/sign/sign.key") // 相对路径// 输入文件路径val inputFile = File(projectRoot, "vmp/sign/sign") // 需要加密的文件try {// 使用 AES 加密文件AESUtils.encryptFile(inputFile, encryptedFile, keyFile)println("File encryption completed, saved as: ${encryptedFile.absolutePath}")println("Key saved as: ${keyFile.absolutePath}")} catch (e: Exception) {e.printStackTrace()}
}

指令流解密

package com.cyrus.vmpimport com.cyrus.vmp.AESUtils.loadKeyFromFile
import com.cyrus.vmp.AESUtils.readFile
import com.cyrus.vmp.AESUtils.writeFile
import java.io.Filefun main() {// 获取工程根目录路径val projectRoot = System.getProperty("user.dir")// 输入加密文件路径val encryptedFile = File(projectRoot, "vmp/sign/sign.vmp")// 密钥文件路径val keyFile = File(projectRoot, "vmp/sign/sign.key")// 输出解密文件路径val decryptedFile = File(projectRoot, "vmp/sign/sign_")try {// 从文件加载密钥val secretKey = loadKeyFromFile(keyFile)// 解密文件val encryptedData = readFile(encryptedFile)val decryptedData: ByteArray = AESUtils.decrypt(encryptedData, secretKey)// 保存解密后的文件writeFile(decryptedFile, decryptedData)println("File decryption completed, saved as: ${decryptedFile.absolutePath}")} catch (e: Exception) {e.printStackTrace()}
}

Android 中运行时解密并执行指令流

将 .vmp 和 .key 文件放在 Android 应用的 assets 目录下

word/media/image5.png

编写工具类,用于读取 assets 文件并解密

package com.cyrus.example.vmpimport android.content.Context
import java.io.InputStream
import javax.crypto.Cipher
import javax.crypto.SecretKey
import javax.crypto.spec.SecretKeySpecobject AESUtils {private const val ALGORITHM = "AES"private const val TRANSFORMATION = "AES/ECB/PKCS5Padding"// 从 assets 中读取文件并解密fun decryptFileFromAssets(context: Context, vmpFileName: String, keyFileName: String): ByteArray? {// 读取密钥文件val key = loadKeyFromAssets(context, keyFileName)// 读取加密的 vmp 文件val encryptedData = readFileFromAssets(context, vmpFileName)// 解密return decrypt(encryptedData, key)}// 读取文件内容为字节数组private fun readFileFromAssets(context: Context, fileName: String): ByteArray {val inputStream: InputStream = context.assets.open(fileName)return inputStream.readBytes()}// 从 assets 中加载密钥文件private fun loadKeyFromAssets(context: Context, keyFileName: String): SecretKey {val keyBytes = readFileFromAssets(context, keyFileName)return SecretKeySpec(keyBytes, ALGORITHM)}// 解密private fun decrypt(data: ByteArray, key: SecretKey): ByteArray {val cipher = Cipher.getInstance(TRANSFORMATION)cipher.init(Cipher.DECRYPT_MODE, key)return cipher.doFinal(data)}
}

调用解密方法并读取指令流

private fun readInstructionFromAssets(): ByteArray? {// 文件名:在 assets 中放置的加密文件和密钥文件val vmpFileName = "sign.vmp"val keyFileName = "sign.key"// 解密文件val decryptedData = AESUtils.decryptFileFromAssets(this, vmpFileName, keyFileName)return decryptedData
}

得到解密后的指令流后调用 VMP 执行指令流对 input 参数加密

val input = "example"// 解密并执行指令流
val bytecode = readInstructionFromAssets()// 通过 VMP 解析器执行指令流
if (bytecode != null) {val result = SimpleVMP.execute(bytecode, input)// 显示 ToastToast.makeText(this, result, Toast.LENGTH_SHORT).show()
}

测试

执行结果如下

word/media/image6.png

和原来的 sign 算法对比是结果是一样的。

word/media/image7.png

完整源码

开源地址:https://github.com/CYRUS-STUDIO/AndroidExample

http://www.dtcms.com/a/617092.html

相关文章:

  • 网站添加外链客户关系管理名词解释
  • 不锈钢公司网站源码 网站建设 产品3级分类asp源码微信小程序购物平台
  • php网站怎么样可以做机械设计接单的网站
  • 网站建设验收使用情况公路建设管理办公室网站
  • 自己怎么做网站网页云主机 免费
  • 企业品牌文化建设学习网站wordpress 3.5 官方中文版
  • 怎么呢搜到自己建设的网站河北百度推广电话
  • 陵园网站建设价格厦门网站推广公司哪家好
  • 网站开发 策划书常州做网站哪里好
  • 注册过什么网站基于网站开发小程序
  • 请兼职做企业网站设计怎么收费湖南省建设工程造价管理协会网站
  • 网站ip访问做图表许昌住房建设局网站
  • 网站模板下载大全免费网站的代码
  • 上海高玩seo广州seo排名优化服务
  • 这样做网站推广深圳定制网站制作厂家
  • 天津网架公司怎样优化网络
  • 做外贸有哪些免费的网站wordpress 加微信号
  • 做杂志的模板下载网站网站进行规划与设计
  • 为外国企业做中文网站建设营口市住房建设保障办官方网站
  • 网站开发费税率重庆网站建设项目
  • 厦门网站设计多少钱做视频赚钱的网站有哪些
  • 西安seo站内优化阿里云服务器12元一年
  • 通信工程毕设可以做网站吗黑马程序员c++笔记
  • 中国建设部网站宁波今晨发现1例阳性
  • 东莞站福公司工资注册网站给谁交钱
  • 网站开发所需要的语言公众平台安全助手
  • wordpress网站主机网页设计网站
  • 网站建设在哪里找奉化建设局网站
  • 有哪些开发网站公司上海城乡建设网站证件查询
  • 建设项目环保验收平台网站珠海免费模板建站