【软件逆向-某相安全平台jar加密逆向】此文章归类为:软件逆向。
某相安全平台加密,除Main类外,其他class文件均被加密,熵值非常高
除jar外,还有一个.so
文件。在启动时,需要指定-agentpath:./.so
命令行参数。由于未确定其加固方案(比如),于是手动逆向其流程。
基本启动流程
jvm在指定-agentpath:./.so
后,会先加载此so文件,然后运行此入口函数:
1
|
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm,
char
*options,
void
*reserved)
|
参考:
容易推测,jvm会先通过此入口函数进行初始化,包括实现一个Loader,其在运行时会对Class文件进行解密。
so脱壳
拖入IDAPro对so文件进行分析,从导出表进入查看其代码,发现被加密,其他函数也是加密状态:
很明显so本身也加壳,并且未能确定so壳类型。由于so在加载时,操作系统会调用其_init_proc
函数。于是查看此函数,发现未被加密:
可推测此函数进行了so的解密流程。于是手动编写加载程序test.c
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <stdio.h>
#include <dlfcn.h>
int
main(
int
argc,
char
* argv[]) {
void
* handle;
char
* error;
handle = dlopen(argv[1], RTLD_NOW);
if
(handle == NULL) {
printf
(
"Open library *s error: *s\n"
, argv[1], dlerror());
return
-1;
}
printf
(
"Open success! %x %s\n"
, handle, argv[1]);
while
(1) {}
return
0;
}
|
编译后通过ida进行远程调试,待so被加载后查看其内存段:
进入可执行段,修复ida的函数声明。其中解密后的函数相对段基址的偏移不变,因此可以对照原so对虚拟基址的偏移确定解密后段中函数的位置。
由于dump(参考)后需要修复虚拟地址等,于是直接在此进程中进行分析。为方便分析应使用ctrl+F9
导入jni.h
头文件(参考)
so分析
分析Agent_OnLoad
函数:
通过分析发现so会先注册两个Native函数:
其中参数class_obj
在Agent_OnLoad
通过使用MethodID
获取后传递。后面进行分析发现就是org.springframework.asm.ClassReader
。
然后会使用RegisterNatives
进行注册:
1
|
jint RegisterNatives(jclass clazz,
const
JNINativeMethod* methods, jint nMethods)
|
其中JNINativeMethod
结构体在jni.h
中有声明,需要在IDA中Structures
窗口中添加:
查看两个结构体地址,发现一个是isCipher
函数,一个是decrypt
函数
查看方法签名发现接受一个字节数组作为参数,并返回一个布尔值。后者则接受一个字节数组,返回一个字节数组。
进一步分析isCipher
函数:
发现会检查输入的字节数组前四个字节是否为0BAh, 0BEh, 0CAh, 0FEh
,可以发现加密的class文件头就是如此:
另外正常的class文件头是CAFEBABE
。由此可知此函数用于判断是否为一个加密的class文件
再分析decrypt
函数。发现解密时会使用一个全局16长度字节数组
和加密class
生成aes key
和vi
。
通过交叉引用发现global_bytes_16
在Agent_OnLoad
结尾处进行了初始化,通过一个初始key
和vi
对一个长度0xA150
的密文进行解密并转换提取16个字节生成。
使用AES CBC NoPadding
对密文进行解密,发现就是ClassReader.class
回到正常class解密流程,class密文前21字节
和global_bytes_16
生成aes key
和vi
,再解密21偏移后的内容即可解密class文件。
此文章仅作技术交流,严禁利用文中技术进行非法行为,否则后果自负!
更多【软件逆向-某相安全平台jar加密逆向】相关视频教程:www.yxfzedu.com