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() 表示最长公共子序列.
   311   312   313   314   315   316   317   318   319   320   321