场景介绍
最近有用户使用Virbox Protector工具对jar包采用java vme方式进行保护后在麒麟系统上运行异常,异常日志显示sense loader exception: /tmp/sense_loader/CC000xxxx_loader_linux_x64.so无法从共享目标中映射段,如图所示:

问题分析
安全机制
银河麒麟作为国产化操作系统,广泛应用于政府、国防、金融等关键领域,其核心安全目标之一是确保系统底层的完整性和可信性。必须确保每一个在系统上运行的底层程序都是经过授权、未被篡改的,如果一些软件没有可信来源时,那么系统就会阻止其加载运行。
签名作用
1. JAR包为什么通常不需要签名?
JAR包本质上是一个压缩文件,里面包含了Java字节码,它不是本地机器码,JAR包运行需要调用java程序,而Java程序的行为受到JVM安全策略的严格限制。
一般情况下,一个普通的Java程序无法直接访问底层硬件、任意读写文件系统或执行系统命令,它的权限是被JVM代理和约束的。
2. 二进制文件为什么需要签名?
二进制文件(如ELF格式的文件)是直接由CPU执行的本地机器码。
当二进制文件运行时,它直接与操作系统内核交互,可以调用系统调用,访问硬件等,其行为几乎不受限制(在用户权限范围内);
3. 签名作用
签名可以证明了此二进制文件来自可信的发布者(例如,麒麟软件官方、经过审核的软件开发商);
操作系统在运行为签名的二进制文件之前,会校验其签名,如果签名无效或来自未知发布者,系统会拒绝执行或弹出严重警告。
文件目录
保护前的jar包能直接运行,加固后的jar包为什么运行会出现上述问题?
首先我们先分析下保护前和保护后jar包的文件结构,如下图所示:
- Jar包目录
原程序jar包的文件目录,如图所示:

- 加固后Jar包目录
- 使用Java vme方式保护后,加固后的jar包的文件目录,如图所示:

- 进入到这个
CC0000006916935900021FFC5AC54D5D(这是个随机定义的Java Class)目录下,可以看到Virbox Protector工具保护后所产生的loader库文件,该库文件是 C/C++ 语言编写的,主要用来解释执行由JVM字节码(Java方法的JVM指令)转换为自定义虚拟机字节码(VM Code)。

因此,麒麟系统上运行报错,是因为它无法判断该二进制文件的来源以及是否符合系统要求,进而就直接阻止的我们so库进行加载。
解决方式
想避免上述问题,目前的解决方式有两种:
- 第一种,在安全中心添加对so库文件的认证,防止系统阻止;
- 第二种,对so库文件进行签名,可以让该文件被信任进而执行。
安全中心
若该系统有类似安全中心进行管控软件的加载,可以在安全中⼼的应⽤程序执⾏控制中可以添加认证,让系统不再检查loader库⽂件即可。
签名流程
若系统没有类似安全中心的管控,可以直接对so库进行签名,也能让so库被信任而执行。
申请证书
- 登录麒麟应用软件分发平台;
- 参考官网提供的操作指引申请证书。
进行签名
- 插入UKEY;
- 打开终端,输入签名命令。

- 解压加固后的jar包,根据系统架构获取对应的so库,如果是arm架构就对loader_linux_a64.so进行签名,如果是x64架构就对loader_linux_x64.so签名;
- 之后根据提示输入UKey的密码,签名成功则会提示信息;

- 签名成功后,将签名后的so库替换一下,在进行打包成jar包,命令如下:进入到解压的demo_new目录下
执行命令:jar -cfM0 <jar包名称> ./*
例如:jar -cfM0 demo_new.jar ./* - 运行打包后的jar包可以直接运行,so库不会被阻止了。
