浅谈swf中的加密及对策
DelphiSwfSdk近一年没更新,作者消失无踪,留下bug一堆。最近在完善DelphiSwfSdk的过程中,对swf文件格式有了系统的了解,同时就自己比较感兴趣的as加密,也进行了一下研究。研究发现,as1,as2时代的加密,其实大部分都只能称之为“混淆”,利用混淆达到迷惑反编译器甚至卡死反编译器的目的。
就其原理,本质上只在于 反编译器 与 播放器 在处理swf文件时的细节上的差异。详述如下:
1. swf反编译器在反编译过程中,是按照swf的文件规范,将swf依次拆分为很多tag,然后如果tag中含有脚本,例如doaction或doinitaction等tag,则对这个tag中的bytecode,按照最紧凑原则进行依次读取解析,直至解析完整个swf文件。
2.swf播放器,在拆分swf为tag的过程中,和swf反编译器基本类似,差别不大,差别只在于,swf播放器解析tag中的脚本的时候,是变执行变解析,因此并不是按照最紧凑原则进行依次读取解析,而是执行到哪,就解析到哪。这点差别,也就成为了as1,as2时代很多swf加密工具保护swf文件中脚本的基本出发点。
下面,给出两种简单的加密示例的图示说明。
1、如下图所示:
将含有脚本的tag拆分,其中一部分bytecode,移到新加入swf的非官方说明中提到的tag,例如tag id为253等等,只要不和官方已有tag冲突即可,然后再原脚本tag的末尾跳到新tag中自行即可,这里主要利用了swf中的jump指令不但可以在本tag中跳转,同样可以跳转到其他tag,但是swf反编译器就不会这么办,swf反编译器只会将脚本tag当做一个整体去解析,这样当然就得不到正确的结果,swf encrpt中广泛使用了这中方法。
2、如下图所示:
将tag中的脚本中加入jmp,可以是有条件jmp,也可以是无条件jmp,有条件jmp利用好,可以实现多种变种。然后jmp到realcode。而jmp和realcode中插入fake code 或者error code,哪些压根就没有任何意义的bytecode或者错误的bytecode。这样,swf播放器在执行脚本的时候由于是边解析边执行,那么就会跳过fake code段,直接执行real code段。但是swf反编译器是采用 最紧凑法依次解析的,碰到fake code或error code,就挂了,后面的realcode就得到了保护。
在实际过程中,1、2两种方法可以整合使用,以实现更加复杂的方案。
这里也简单的谈谈对付这种加密方案的对策,一句话:模拟执行,模拟真实swf播放器的边解析边执行的过程,将所有可能执行分支全部取出,不可能执行分支全部跳过,之后再合并下得到的结果即可。剩下的仅仅是优化下代码以实现能解析bytecode为as脚本了。
文章很有见解,如果能附上一个实例那就更好了。