从不同寻常的角度为JS代码加个密

1,314 阅读5分钟

众所周知,前端开发没有秘密。前端开发可能会遇到一些尴尬的事情,就是有些功能代码自己付出了很大心血,可是又不想被轻易抄袭,怎么办捏?

以往我们会选中诸如 eval加密、代码编码转换、debug断点、控制台及右键禁用等手段。可日子久了还是容易被发现。

于是乎,我在尝试一些稀奇古怪的想法,让想要抄袭代码的人懵逼下。虽然说只要有心,一样是可以破解的,但这也不乏是一种尝试吧!

一.利用canvas的imageData存代码

加密源代码

将代码的字符按编码转成数字,再通过自己设定的算法交叉每个编码的位置,将数字存入canvas中imageData里GRB的每一个通道。这样就完成了JS代码转成图片格式的转换。当你要运行代码的时候远程加载图片文件,再用解释脚本反向转码就好了!

QQ截图20230804002142.png

加密解析脚本

然而,问题来了?反向转码解释代码的时候不就暴露脚本了吗?这时候你问题变成了你如何对解释性脚本加密了。

最常见得是eval的加密方式,就是将js代码弄成字符串,然后打乱顺序,还原的时候用eval运行使其生效。如果这样,破解的人只要搜索eval就有突破口了。怎么办呢?

我的想法是利用Function构造器,让new Function()可以让字符串变成函数。可是Funtion目标还是明显了点。我想到了任何函数的constructor都是Funtion啊!那么我随便用一个常见的对象就可以了。 以下代码是在控制台打印出'Hello World'

let code = ')"dlroW olleH"(gol.elosnoc';
new Date.constructor(code.split('').reverse().join(''))();

隐藏解析脚本调用

直觉告诉我们,脚本是从上到下运行的,解析脚本的调用一定会在最后面运行。如果运行代码一般在最后面输出,一定是会被发现的。然而文件大小有限,又不可能加无用代码。

这时候我们可以利用一个JS的新特性getter, 重写一个对象的属性,将“解析脚本”的调用写在这个对象属性的getter里面。而只需要在代码的最后面,风轻云淡的return 这个属性值,就不经意间调用了“解析脚本”。而无论对方控制台怎么打印那个方法,都是正常的返回属性,并没有找到“解析脚本”。

限制脚本运行的域

如果仅仅是加密,对方直接复制走整套代码,不管看不看得懂,直接运行不就好了?我们该如何限制用户使用呢?可以在一开始图片加密的代码中,放入对当前可运行域名的检测,发现并非指定域名,直接跳转掉。这样既然用户破解不了图片代码,自然无法在自己的域名下再运行了。

图片加密JS演示 passer-by.com/imageCode/

二. 利用零宽度字符加密

隐藏源代码

在文本编码规范里面,存在着一些比较特别的控制字符,他们几乎看不见。是的,就是隐藏在某些字符当中,你甚至都察觉不出来的字符。他们和空格一样看不见,但是空格有宽度,它们没有。

我们可以利用这些特殊的字符进行编码。比如找到4个这样的字符,它们可以组成四进制了。我们只需要将我们的源代码,每个字符对应的码值用四进制表示就可以了!

隐藏代码调用

既然代码隐藏起来,我该如何运行它呢?首先,我们隐藏的是源代码,它明显的函数调用一下子就可以被觉察到。我们可以尝试重写一些常见的原生方法,这样在调用的时候也不会被别人起疑心。

前端最常见的方法莫过于console.log了,它在任何js代码中被调用,程序员只会觉得肯定是调试用的,不太会怀疑它存在的问题。那么我们只需要对console.log方法进行重写,待我们需要运行脚本的时候将偷偷运行就好了。

console.log("测试");

如果是这样的代码,你怎能想到这是一个隐藏的函数调用呢?

隐藏解析脚本

其实解析脚本隐藏不了,因为任何形式的加密方法,对方看到一堆乱码在那边一定会起疑心的。我认为最佳的加密方式就是大隐隐于市,大大方方的摆在明面上。因为解析方法很短,一共没有多少行代码,而相比于你要加密的代码的业务复杂度,往往是不对称的。 当信息熵存在严重不对称的时候,你是不太会怀疑某几行代码存在的问题。当你一眼看上去,那几行代码虽然你不知道它做什么用的,但它因为没几行一定不是你要的代码。

隐藏字符加密JS演示 passer-by.com/hiddenCode/

如果你对于隐藏性有疑虑,可以试试能否找到以上演示中“文字打印”特效的源代码在哪里?