llvm代码混淆学习(五)
写在前面
随便学学 llvm 代码混淆,顺便做个毕设,水几篇文章就当做做笔记
控制流平坦化原理分析概述控制流平坦化指的是将正常控制流中基本块之间的跳转关系删除,用一个集中的分发块来调度基本块的执行顺序。
结构
入口块:进入函数第一个执行的基本块。
主分发块与子分发块:负责跳转到下一个要执行的原基本块。
原基本块:混淆之前的基本块,真正完成程序工作的基本块。
返回块:返回到主分发块。
所有完成原程序功能的原基本块平行排列在返回块上方,ida反汇编出来看起来就是一排,也就是平坦化的由来。
混淆效果分析正常的控制流时,能很容易的分析出程序的执行顺序,以及每一段代码完成的工作(一段代码可能由多个相互关联的基本块组成),进而掌握整个程序的逻辑。
分析平坦化后的控制流时,在不知道基本块执行顺序的情况下,分别对每一个基本块进行分析是很难的,而如果要得知每一个基本块的执行顺序,必须分析分发块的调度逻辑。
实际上当函数比较复杂时,通过手动分析分发块还原原基本块的执行顺序是非常复杂的。
控制流平坦化混淆后的伪代码,while + switch 结构对应平坦化后的控制流结构。
控制流平坦化代码实 ...
llvm代码混淆学习(四)
写在前面
随便学学 llvm 代码混淆,顺便做个毕设,水几篇文章就当做做笔记
代码混淆基本原理术语介绍代码混淆代码混淆是将计算机程序的代码,转换成一种功能上等价,但是难以阅读和理解的形式的行为。
函数函数是代码混淆的基本单位,一个函数由若干个基本块组成,有且仅有一个入口块,可能有多个出口块。
一个函数可以用一个控制流图(Control Flow Graph,CFG)来表示。
基本块基本块由一组线性指令组成,每一个基本块都有一个入口点(第一条执行的命令)和一个出口点(最后一条执行的指令,也即终结指令)。
终结指令要么跳转到另一个基本块(br,switch),要么从函数返回(ret)。
控制流控制流代表了一个程序在执行过程中可能遍历到的所有路径。
通常情况下,程序的控制流很清晰的反映了程序的逻辑,但经过混淆的控制流会使得人们难以分辨正常逻辑。
不透明谓词不透明谓词指的是其值为混淆者明确知晓,但是反混淆者却难以推断的变量。
例如混淆者在程序中使用一个恒为 0 的全局变量,反混淆者难以推断这个变量恒为 0。
常见的混淆思路符号混淆将函数的符号,如函数名、全局变量名去除或者混淆。对于 ...
llvm代码混淆学习(三)
写在前面
随便学学 llvm 代码混淆,顺便做个毕设,水几篇文章就当做做笔记
基本块分割基本块分割即将一个基本块分割为等价的若干个基本块,在分割后的基本块之间加上无条件跳转。
基本块分割不能算是混淆,但是可以提高某些代码混淆的混淆效果。
为什么要分割在许多基于基本块的代码混淆中,基本块数量越多,代码混淆后的复杂度越大。
通过增加基本块的数量,可以到达提高混淆效果的目的。
实现思路遍历每个函数中的每个基本块,对每个基本块进行分割即可。
有 PHI 指令的基本块选择跳过
因为 PHI 值根据前驱块指定,分割带有 PHI 指令的基本块可能会改变其前驱块,导致带有 PHI 指令的基本块的前驱块是分割前的同一个基本块
使用到的 API
额外参数指定
可以通过 cl::opt 模板类获取指令中的参数,这里的 opt 是选项 option 的缩写,不是优化器的意思:
1234567#include "llvm/Support/CommandLine.h"// 可选的参数,指定一个基本块会被分裂成几个基本块,默认值为 2static cl::opt<int> ...
llvm代码混淆学习(二)
写在前面
随便学学 llvm 代码混淆,顺便做个毕设,水几篇文章就当做做笔记
LLVM Pass 常用 APILLVM Pass 框架中,三个最核心的类是 Function、BasicBlock和Instruction,分别对应 LLVM IR 中的函数、基本块和指令,还有一个基本类Value,所有可以被当作指令操作数的类型都是 Value 的子类
Function 类与 Function 有关的操作主要是获取函数的一些属性,比如名称等等,以及对函数中基本块的遍历:
获取函数名称:F.getName()
获取入口快:F.getEntryBlock()
函数中基本块的遍历
可以通过 foreach 循环对函数 Function 中的每个基本块 BasicBlock 进行遍历
12345bool runOnFunction(Function &F){ // 使用引用是为了能修改传入参数Function类 for(BasicBlock &BB : F){ // 遍历F中的基本块,同样使用引用 // to do } ...
llvm代码混淆学习(一)
写在前面
随便学学 llvm 代码混淆,顺便做个毕设,水几篇文章就当做做笔记
LLVM IR 概述
低级编程语言,类似汇编
任何高级编程语言都可以用 LLVM IR 表示
基于 LLVM IR 可以进行代码优化
两种表示方法
人类可以阅读的文本形式,文件后缀为.ll
易于机器处理的二进制格式,文件后缀为.bc
用llvm-dis和llvm-as可以相互转化
结构源代码被编译为 LLVM IR 后,具有模块 Module,函数 Function和基本块 BasicBlock
模块
一个源代码文件对应一个模块
头部信息包含程序的目标平台,如 x86、arm 等,和一些其他信息
全局符号包含全局变量、函数的定义与声明
函数
函数指的是源代码中的某个函数
参数即函数的参数
一个函数由若干基本块组成,其中函数最先执行的基本块为入口块
基本块
一个基本块由若干指令和标签组成
正常情况下,基本块的最后一条指令为跳转指令(br 或 switch),或返回指令(retn),也叫作终结指令(Terminator Instruction)
PHI 指令是一种特殊的指令
代码混淆基于 L ...
《Brotato》游戏测评
写在前面
非常上头的一款小游戏,46 小时全成就通关,总结记录一下
背景看宫本狗雨在直播间玩了,非常有意思,立马 22 块买了开始玩。果不其然非常上头,十分杀时间。
游戏性轻肉鸽莱克游戏,主角是个b土豆(我一开始是真没看出来),打的是外星人。难度比较适中,也比较吃运气,算得上是一个休闲小游戏。
玩法可以选择不同的主角,每一个主角有特定的技能效果,普遍可以拿 6 个武器。
每一局一共 20 关,每一关杀怪会掉落钱,捡钱可以加经验值,升级可以加属性,没捡到的钱会在当前关卡结束时自动收集,每过一关可以进入商店买武器和道具。
核心玩法就是道具、武器和角色技能之间的配合,因为大部分道具不是单纯的增益属性,而是增加某属性的同时削弱另一个属性,比如增加 6% 伤害,减少 8 范围,玩家需要有取舍的获取自己需要的属性和武器。
难度分为危险 0 - 5,六个难度,每过一个难度等级会解锁一个新角色,在对局中达到某些特定属性,也会解锁新角色。
每个角色的技能都不同,所以都非常有特点,导致玩法和流派也千奇百怪,再加上刷新的道具武器不同,运气好坏,使得这个游戏很难玩腻,每一局都很有新鲜感。
美术和音乐美术 ...