你好,有人说按手机系统设计一个软件系统分析与设计可以控制微信随机红包的钱数尾数

哪有什么岁月静好只不过有人替你负重前行。而操作系统就扮演了这样一个负重前行的角色

对于一台电脑拆开来看,有鼠标键盘、显卡显示屏、CPU、内存、硬盘、网卡…

但仅有硬件组成的电脑还不能直接使用。"硬件 + 操作系统"才算是我们通常说的电脑以后的学习主要围绕linux系统,这个话题展开我们首先必须承认操作系统的重要性。

想理解外包公司一样理解操作系统

刘超老师将操作系统类比成一家外包公司确实很形象,加深了我对linux系統的理解
内核对于操作系统,相当于公司的老板老板是不轻易干活的(一般有很多部门),所以linux系统中也有很多子系统对应关系有:

公司的客户对接和交付部门

其他:程序相当于项目计划书进程相当于正在进行的项目

为了更好的理解linux的运作机制,老师分析了"用户点击qq"倳件分为如下几个阶段

对于linux而言,驱动捕捉到用户点击事件产生中断。cpu调用到驱动事先安排好的中断处理函数

对于外包公司而言,對接人员记录客户提出的需求进行项目开发的计划。

对于linux而言将qq的程序文件从硬盘加载到内存,内存上以进程启动这个阶段需要思栲几个问题:
1. 硬盘上的文件如何管理?
2. 内存空间上的进程如何管理
3. 多进程如何实现?
4. 进程自身如何实现功能
硬件上的数据有文件系统進行统一管理;进程在内存空间上的映射由内存管理系统完成;多进程的实现通过进程管理系统;系统对进程提供统一的接口,实现核心功能这层接口称为系统调用层

对于外包公司而言从档案库中取出项目计划书,成立项目组划分会议室,完成立项的过程然后执荇项目,通过办事大厅处理业务和各个部门打交道。这些都是动态的过程之后就比较好理解了。

阶段三:进程调出对话框
对于linux而言進程调出显示对话框,进程->显卡驱动->显示界面

对于公司这里显卡驱动相当于客户的交付人员,项目组通过交付人员将项目的成果交付给鼡户

阶段四:用户操作输入框
用户在输入框输入,字符立即显示键盘驱动->进程->显卡驱动->显示界面

对于公司,就是对接人员处理客户不斷提出的需求–交付人员交付的过程

阶段五:用户按回车发送
对于linux系统用户按下回车键,网络发送到远程的另一个用户键盘驱动->进程->網卡驱动

对于公司,有时候为了实现需求需要与其他公司的交互,通过对外合作部门

以一张图片概括我对这篇文章的理解

对于课堂练習,找出linux源码中几个子系统所在的目录(参考同学给出的答案)

}

特别声明:本文是博主阅读大量碩博论文和知网文献后原创非公司内部解决方案。

Java整体架构图如下:

程序预处理分析:对原应用程序进行程序分析预处理为后续混淆奠定结构基础。

布局混淆模块:对代码中有意义的标识符进行重命名

控制流混淆模块:对程序进行控制流混淆,包括插入多余的分支路徑、压扁控制流、强化不透明谓词

字符串混淆模块:加密隐藏代码中的常量字符串。

混淆算法库:对程序的混淆处理主要依靠混淆算法庫支撑算法库中包含一系列的基本块混淆算法。混淆算法库为可扩展

本文先讲理论,后附上demo代码

混淆模块包括三部分:布局混淆控淛流混淆字符串混淆

本模块核心思想:对代码中有意义的标识符进行重命名。

主要包括三步:构造包结构构造继承树标识符混淆

3.1、混淆标识符说明

可以混淆的标识符包括:

不可以混淆的标识符包括:

1、该实例方法实现父类抽象方法或接口方法
2、该实例方法覆盖父類的实例方法

Java应用代码主要有包结构和继承结构。每个类必定继承一个父类默认为java.lang.Object类。每个类可以实现0个或多个接口接口也可以继承接口。通过继承结构可以识别出上面描述的前两类方法,并对其进行统一命名来保证多态性

下图显示了一个Java程序的包结构图:

其对应嘚继承结构图如下所示:

3.3、布局混淆方法实行步骤

1、遍历类信息结构,构建包结构和继承结构初始化包结构根节点为ROOT,继承结构根节点為Object

2、从根节点遍历包结构,对于每个包节点的子节点使用顺序生成名称代替原来的包结构名称。如果生成的名称序列为a、b、c、……那么对于上图包结构图中所示,其混淆后的包结构将如下图所示:

3、遍历从根节点到叶子节点的继承结构对于每种类型,执行以下操作:

1)为每个字段重新顺序生成名称对于相同字段,使用相同的名称进行混淆

2)为每个方法名重新顺序生成名称。需要注意的是要保存其父节点已经遍历过的方法名,并判断该方法名是否可混淆对于不可混淆的,不能混淆

3)替换Java文件中所有的混淆名称。

3.4、布局混淆礻例代码

说明:通过对Android源程序源码文件遍历得到符合混淆条件的代码块;对代码块进行混淆操作,主要分为插入多余的分支路径、压扁控制流、强化不透明谓词三个步骤

4.1、控制流混淆算法

在混淆方案中,为了控制性能开销插入的分支路径实际上并不执行,压扁的结构Φ的语句包括实际路径和不执行的分支路径而不透明谓词采用建立访问控制策略的形式的强化。

控制流混淆方案OBJ(P、Q、R、W、O)定义:

B={b1,b2,b3,……,bn}:为原始程序代码中符合混淆条件的n个代码块的集合
BR:经过插入多余分支路径后的程序代码块集合
Bw:经过压扁控制流后的程序代码块集匼
R={r1,r2,r3,……,rn}:为n种不同类型的代码块对应可插入多余分支路径的集合
w={w1,w2,w3,……,wn}:为n种不同类型的代码块对应压扁控制流方法的集合
O:不透明谓词強化方法
?:进行压扁控制流操作
:强化不透明谓词操作

语言描述:符合混淆条件的代码块集合先进行插入多余分支路径,再进行压扁控制流最后强化不透明谓词。

控制流详细混淆方案详细过程如下:

1、对于P进行词法语法分析遍历得到符合混淆条件的代码块集合B

2、对玳码块集合B分别进行插入多余的分支路径操作对每一个属于B的代码块,在R中找到相应的插入分支代码类型进行插入操作:(BR=B●R)

3、对插入多余路径后的代码块进行压扁控制流操作。对每一个属于BR的代码块在w中找到相应的压扁控制流方法,进行压扁操作:(Bw=BR?w)

4、对压扁控制流后代码块进行不透明谓词强化操作:

5、将混淆后的程序Q返回给用户

控制流混淆方案架构图:

1、在程序中插入实际并不执行的多余控制流路径。

首先在分析完程序控制流结构的基础上,选取程序中完整的结构块其控制结构可能包含多个判断或循环条件基本块,每個判断或条件基本块与其相关语句组成一个基本结构块基本结构块中仍含有判断或条件基本块的结构块定义为嵌套结构块。

其次在结構块中的嵌套结构前插入一个一定为真的不透明谓词,不透明谓词为假的一边中插入与嵌套结构块结构相同但数据按条件随机生成的代码作为不执行的冗余结构块,冗余结构块最后的有向边指向代码中的下一个结构块
最后,将它们封装成一个结构块

2、对部分实际执行蕗径与插入的不执行的分支路径进行压扁处理,再封装

3、构建访问控制策略,强化不透明谓词

将整个程序不透明谓词的判断转化为图遍历问题,构建访问控制策略每个封装好的结构块作为一个节点,节点之间的跳转作为一条边每个节点的访问都需要该节点的key,以及通往下一个节点的password程序通过这条边后,也就运行到了下一个节点同时得到了访问下一个节点的key。

插入多余的分支路径图:

在程序中插叺多余的分支路径的第一步就是要判断插入位置这是在程序分析的基础上进行的。程序分析从最外层的结构开始一层一层的分析程序嵌套结构和并列结构,直至最简单的基本块结构

1)将最外层的结构视为一个结构块,分析其内部包含的判断或循环结构块无论判断或循环结构块内部是否包含嵌套结构,都将其视为结构块;

2)重复上一步骤对分析出的判断或循环结构块使用上一步的方法继续分析,直箌分析的结构块为基本块

说明:只选择结构嵌套层数为两层及以上的结构块进行控制流混淆。因为一层没有必要也没有意义做控制流混淆

因为不透明谓词是判断条件,所以在嵌套结构中的第一个判断条件或循环条件前插入使得添加插入的不透明谓词一定为真,保证控淛流只会执行实际需要执行的路径也可以插入一段不执行的嵌套结构,使得后续的压扁控制流后的结构看起来更复杂

在不透明谓词为假的边中插入不会执行的冗余代码,冗余的控制流在复制原基本块的基础上对数据进行改变具体方法:

1)增加多余控制流中循环执行的佽数以及将嵌套结构中的判断条件置反,并且将嵌套结构中执行的语句改为对变量的增减语句如果嵌套结构中循环条件有上限,则执行語句中的变量增反之,变量减若为判断条件,则统一改为对变量的增语句

2)然后插入不透明谓词为假的路径中,冗余的控制流最终指向下一个结构块冗余代码中数据大小的改变必须与原语句不同,且在数据量级上保持同一水平使得冗余代码看上去像原程序中实际執行的代码,能极大地保证混淆代码的隐蔽性

4、将原结构块与插入的不透明谓词以及冗余代码封装成一个结构块,以进行压扁控制流处悝

压扁前需要通过分析程序嵌套结构和条件基本块的类型确定压扁执行的次数以及调用基本块压扁控制流算法的类型。压扁控制流相关算法包括压扁控制流算法条件基本块压扁控制流算法

4.3.1、压扁控制流算法

功能:主要包括分析结构块嵌套深度(只分析原结构块),判斷条件基本块类型以调用相关基本块压扁控制流算法以及控制根据嵌套深度控制压扁次数。

4.3.2、条件基本块压扁控制流算法

压扁控制流实際上就是压扁程序中的嵌套结构使之扁平化,破坏其控制流结构增加分析程序的难度。

在进行压扁控制流处理时需将嵌套结构视为┅个条件基本块,逐层分析其嵌套类型之后逐层的将嵌套结构中部分实际和分支控制流结构进行压扁。

4.3.2.1、if语句基本块压扁控制流算法

功能:主要是对if语句基本块进行抽取部分实际和分支路径进行压扁

如果仅有一个if-else结构则直接退出,不进行压扁处理

如果有多个if-else结构,则抽取实际和分支路径的前半部分作为待压扁结构将其转换为switch结构,switch结构的输出作为余下实际路径的输入继续执行if-else流程,剩下的分支路徑将进行删除操作以控制混淆带来的文件大小增长。

构造switch结构前需要添加一个next变量和一个for循环,以支撑switch结构的运行

构造switch结构时,优先实际执行的路径每添加一条case语句,next增加1按照控制流图中从上至下,从左至右的顺序依次添加至多余路径语句的case语句但是最后一条case語句为嵌套结构中实际执行路径的最后一个子节点,插入的多余的分支路径按同样的步骤构造case语句插入到最后一条case语句之前

if语句基本块壓扁控制流算法图:

4.3.2.2、while语句基本块压扁控制流算法

功能:主要是对while语句基本块进行抽取部分实际和分支路径进行压扁。

对while语句基本块进行壓扁前需要将循环条件构造为if语句通过该if语句判断while语句基本块中的语句是否执行,以及执行的次数

通过if条件分析出循环次数n,若n为偶數保留前n/2次循环为原始结构,剩下后半部分n/2语句构造case语句若n为奇数,则原始结构保留前(n+1)/2次循环分支路径抽取的语句为循环次数比实際循环次数多的部分,构造case语句

例如:循环了10次,前5次循环保留后5次循环用来构造case语句。循环了9次前5次循环保留,后4次用来构造case语呴

构造switch结构前,需要添加一个next变量和一个for循环以支撑switch结构的运行。构造switch结构时优先实际执行的路径,每添加一条case语句next增加1,按照控制流图中从上至下从左至右的顺序依次添加至多余路径语句的case语句,但是最后一条case语句为嵌套结构中实际执行路径的最后一个子节点分支路径case语句插入最后一条case语句之前。

while语句基本块压扁控制流算法图:

4.3.2.3、for语句基本块压扁控制流算法

功能:主要是对for语句基本块进行抽取部分实际和分支路径进行压扁

对for语句基本块进行压扁的首要步骤是分析循环执行的次数n,类似while语句基本块压扁控制流算法抽取前半蔀分作为原始结构,仅对后半部分进行压扁控制流操作然后,将其循环判断条件和语句中对循环判断因子进行操作的语句提取出来分別对其构造case语句,使得压扁后的switch结构能实现for循环

for语句基本块压扁控制流算法图:

功能:主要是对switch语句基本块进行抽取部分实际和分支路徑进行压扁。

由于switch语句基本块的语句已经是case语句不需要再重新构造但是由于需要抽取部分实际路径和分支路径,需要对next变量进行操作

與其他条件基本块一样,对其抽取前半部分的实际和分支路径然后分别对抽取的和未抽取的路径进行switch结构重包装。与压扁其他基本块不哃未抽取的switch结构中的多余的分支路径语句并不进行删除操作。对switch语句基本块的压扁操作实际上并不能算是压扁仅仅是对其语句的结构進行重组。

switch语句基本块压扁控制流算法图:

功能:主要是对do-while语句基本块进行抽取部分实际和分支路径进行压扁

对do-while语句基本块的压扁控制鋶算法类似于while语句基本块压扁控制流算法,区别在于循环体的case语句要先执行即其next的值相较于循环条件较小。在构造case语句时应先对循环體中的语句进行case语句的构造,保证其next的值从0开始

do-while语句基本块压扁控制流算法图:

将程序中try-catch结构的基本块分别放到相应的case语句块中,再压扁成一个switch结构进行压扁操作时,将try、catch、finally基本块都看作一个整体对这个整体进行case语句的构造,按照程序中异常处理的方式添加next变量构慥成switch结构。

需要注意的是如果函数中有个循环会被频繁的执行,那么可以把这个循环归结为一个节点然后再进行压扁。这样循环中嘚各个基本块仍能集中在同一个case语句中,保持原有结构和执行效率不变而不会被打散到各个case语句块中,引发较大的性能开销

4.4、构建访問控制策略(强化不透明谓词)

将程序中各个封装好的结构块作为结点,结构块之间的执行顺序即结点之间的跳转作为一条边每个结点嘚访问都需要该结点的key以及通往下一个节点的边的password,通过整合key、password以及访问路径可以构建程序访问控制策略

每个结点的key为插入的不透明谓詞的判断条件,即不透明谓词的构建可以通过构造一个单点函数(该函数只有在某个特殊的点上才会为真其他情况全部为假),在计算判断结果的过程中只有当输入正确的信息后,布尔值才会为真如果判断条件有多个输入,可以把有限多个单点函数组合在一起构成哆点函数, 即只在一个给定的情况集合下为真其他情况下均为假的函数。

不透明谓词的判断条件可以利用hash来进行保护构建访问控制策畧时,可以将key值事先保存在程序中的其他位置在判断是否能访问节点时,将不透明谓词的条件的hash值与相应的key值进行匹配

4.5、控制流混淆礻例代码


强化不透明谓词之后的代码

未做混淆的代码执行分析:

while循环失败,退出循环程序执行结束。

做了混淆的代码执行分析:

for循环失敗退出循环,程序执行结束

本模块核心思想:隐藏代码中的常量字符串

字符串混淆方法首先提取出定义的常量字符串然后调用加密算法将字符串加密为字节数组,最后构造Java代码来存储得到的加密字节数组

博主之前也设计过一个密钥存储解决方案,不过被公司商用叻既然商用了那就不能公开了。整个方案还是非常复杂的!

大致原理是:先对待加密数据做对称加密处理同时将密钥打散成若干密钥爿段,将这些密钥片段运用拉格朗日插值多项式得出另外一串无关的字符串之后删除原密钥与原密钥片段,并将该无关字符串再打散保存在图片的各个像素点中解密时,从各个像素点中找回打散的无关字符串对其并进行拉格朗日逆运算,得出若干密钥片段并组合成密鑰再运用密钥解密得出原文。

也可以使用其他安全的存储方案

5.2、字符串混淆示例代码

我们继续使用布局混淆后的代码作为源代码使用

提取常量字符串并加密为字节数组(此处使用了AES加密,密钥为123456):
这里需要构造Java代码来存储得到的加密字节数组就不演示了。

本解决方案从三方面入手通过布局混淆、控制流混淆、字符串常量混淆三管齐下对Java代码进行混淆,混淆强度大破译难度高。

但性能也会受影响影响程度未做测试。

}

我要回帖

更多关于 软件系统分析与设计 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信