Page 316 - 《软件学报》2024年第6期
P. 316
2892 软件学报 2024 年第 35 卷第 6 期
义的属性其类型为类类型 Class B , 则说 Class A 属性依赖于 Class B .
● 方法签名, Sig , 是类中方法的访问标志和方法依赖组成的字符串映射成的哈希值. 若类 Class A 中定义的方
m
法使用了类 Class B 的作为方法形式参数或者返回值, 则说 Class A 方法依赖于 Class B .
Class A 通过上述 3 种依赖
将继承依赖、属性依赖和方法依赖等采用统一的方式进行编码, 生成字符串. 假设类
方式之一与类 Class B 形成依赖关系, 编码方法考虑了类 Class B 的类型和名称, 将两者连接在一起构造字符串. 具体的:
Class B 的类型. 考虑 3 种可能的类型: 系统类、同一包中的类、其它包中的类, 使用唯一的整数来表示每
● 类
种类型, 这里采用了整数 0, 1 和 2 依次表示它们.
Class B 的名称. 类的类型决定了编码中采用的类名称. 鉴于在混淆中, 混淆器仅对非系统类进行混淆. 因
● 类
Class B 是一个系统类, 则在编码中直接采用类名称, 否则编码中使用一个常量字
此, 区分系统类和非系统类, 若类
符作为类名的替代.
算法 3. 基于依赖关系的类签名.
输入: 类 A;
输出: Sig (A), Sig (A), Sig (A), Sig (A) .
m
b
a
c
1. Class B = getSuperClass(A); //类 A 的父类
getAccessModifier(A) ; //类 A 的访问控制符
2. Modifer AMC=
3. Type c_type = getClassType(B); // 获取类 B 的类型
4. String str = getEncoding(B, AMC, c_type);
Sig (A) = hash(str) ;
5. b
6. Class[] F = getAllClassofFields(A); //类 A 的属性对应的类
getAccessModifierofField(A) ; //类 A 的属性访问控制符
7. Modifer[] AMF=
8. Type[] f_type = getClassType(F);
9. for i ← 0 to n ← |F| do
10. str += getEncoding(F[i], AMF[i], f_type[i]);
11. end for (2) 所示, 其中
Sig (A) = hash(str) ;
12. a
13. Class[] M = getAllClassofMethods(A); //类 A 的方法申明中出现的类
getAccessModifierofMethod(A) ; //类 A 的方法访问控制符
14. Modifer[] AMM=
15. Type[] m_type = getClassType(M);
16. for i ← 0 to n ← |F| do
17. str += getEncoding(M[i], AMM[i], m_type[i]);
18. end for
19. Sig (A) = hash(str) ;
m
+
+
20. Sig (A) = Sig (A) Sig (A) Sig (A) ;
c b a m
Sig (A),Sig (A),Sig (A),Sig (A) ;
21. return b a m c
在得到了类的基本签名、属性签名、方法签名和类签名后, 可以度量两个类之间的相似性. 假设类 A 和 B 分
别为 APP 和 TPL 中的类, 计算方法如公式 sim b_to_b 、 sim a_to_a 和 sim m_to_m 分别表示类基本签名、类
∑ 3
属性签名、类方法签名的相似性, 分别如公式 (3)–公式 (5) 所示, w 1 、 w 2 和 w 3 分别为各自的权重, w i = 1 .
i=1
对于 APP 中引入的 TPL 而言, 如果在混淆阶段没有移除或修改类成员, 则类签名相同, 类相似性为 1, 否则分别度
量类的基本签名、属性签名和方法签名的相似性, 并通过加权方式获得类签名相似性. 公式 (3)–公式 (5) 中的函数
lcs() 表示最长公共子序列.