如何混淆(保护)JavaScript?

我想制作一个非开源的JavaScript应用程序,因此我想学习如何混淆我的JS代码?这可能吗?

469925 次浏览

混淆:

尝试YUI压缩机。这是一个非常受欢迎的工具,由Yahoo UI团队构建、增强和维护。

您也可以使用:

UPDATE: This question was originally asked on 2008, and The mentioned technologies are deprecated. you can use:

私有字符串数据:

将字符串值保持私有是另一个问题,混淆不会真正有多大好处。当然,通过将源代码打包成混乱、缩小的混乱,你就有了安全默默无闻的精简版本。大多数时候,是你的用户在查看源代码,客户端上的字符串值是供他们使用的,所以这种私有字符串值通常不是必要的。

如果你真的有一个你永远不想让用户看到的值,你会有几个选择。首先,你可以做某种加密,在页面加载时解密。这可能是最安全的选择之一,但也有很多工作可能是不必要的。你可能可以bas64编码一些字符串值,这会更容易…但是真正想要这些字符串值的人可以轻松解码它们。加密是真正防止任何人访问你数据的唯一方法,大多数人发现这比他们需要的更安全。

附注:

众所周知,Javascript中的混淆会导致一些错误。混淆器在这方面做得越来越好了,但是许多机构认为他们从缩小gziping中看到了足够的好处,以及混淆并不总是值得麻烦的额外节省。如果你想保护你的源代码,也许你会认为这是值得的,只是为了让你的代码更难阅读。J SM in是一个不错的选择。

解释型语言的问题在于,您发送源代码以使它们工作(除非您有字节码编译器,但话又说回来,反编译非常简单)。

所以,如果你不想牺牲性能,你只能对变量和函数名采取行动,例如用a、b…aa、ab…或a101、a102等替换它们,当然,尽可能多地删除空格/换行符(这就是所谓的JS压缩器所做的)。
如果您必须实时加密和解密它们,混淆字符串会影响性能。加上JS调试器可以显示最终值…

有许多JavaScript混淆工具可以免费使用;然而,我认为重要的是要注意,很难将JavaScript混淆到无法逆向工程的程度。

为此,我在某种程度上加班时使用了几个选项:

  • YUI CompressorYahoo!的JavaScript压缩器在压缩代码方面做得很好,这将改善其加载时间。有一个小程度的混淆效果相对较好。本质上,Compressor会更改函数名称、删除空格和修改局部变量。这是我最经常使用的。这是一个基于Java的开源工具。

  • JSMin是Douglas Crockford编写的一个工具,旨在缩小您的JavaScript源代码。用Crockford自己的话说,“JSMin不会混淆,但会丑化。”它的主要目标是缩小源代码的大小,以便在浏览器中更快地加载。

  • 免费JavaScript混淆器。这是一个基于Web的工具,它试图通过实际编码来混淆您的代码。我认为它的编码形式(或混淆)的权衡可能会以文件大小为代价;然而,这是个人偏好的问题。

我可以推荐Patrick J. O'Neil的JavaScript实用程序。它可以混淆/压缩和压缩,并且似乎非常擅长这些。也就是说,我从未尝试将其集成到任何类型的构建脚本中。

至于混淆与缩小——我不太喜欢前者。它让调试变得不可能(第1行出错……“等等,只有一行”),而且它们总是需要时间来解压缩。但如果你需要……好吧。

你可以随意混淆javascript源代码,但它总是可以逆向工程的,因为它要求所有源代码都在客户端机器上实际运行……我能想到的最好的选择是用服务器端代码完成所有处理,而javascript所做的所有客户端代码就是将处理请求发送到服务器本身。否则,任何人都将始终能够跟踪代码正在做的所有操作。

有人提到bas64来保证字符串的安全。这是一个可怕的想法。Base64可以立即被那些想要对您的代码进行逆向工程的人识别出来。他们要做的第一件事就是取消编码并查看它是什么。

一个非开源的基于Javascript的应用程序是相当愚蠢的。Javascript是一种客户端解释语言…混淆并没有多大的保护…

JS混淆通常是为了减小脚本的大小,而不是“保护”它。如果您不希望代码公开,Javascript不是合适的语言。

周围有很多工具,但大多数工具的名称中都有“压缩机”(或“微型”)一词,这是有原因的。

混淆永远不会真正起作用。对于任何真正想了解你的代码的人来说,这只是一个减速带。更糟糕的是,它让你的用户无法修复错误(并将修复程序发回给你),并使你更难诊断现场的问题。这是浪费你的时间和金钱。

与律师讨论知识产权法以及您的法律选择。“开源”并不意味着“人们可以阅读源代码”。相反,开源是一种特定的许可模式,授予自由使用和修改您的代码的权限。如果您不授予这样的许可,那么人们复制您的代码就是违法的,(在世界上大多数地方)您有法律选择来阻止他们。

真正保护代码的唯一方法是不发布它。移动重要的代码服务器端并让您的公共Javascript代码对其进行Ajax调用。

在这里查看我关于模糊器的完整答案。

我的印象是,一些企业(例如:JackBe)将加密的JavaScript代码放在*. gif文件中,而不是JS文件中,作为混淆的额外措施。

作为JavaScript/超文本标记语言/CSS混淆器/压缩器,您还可以尝试Patu Digua

我很惊讶没有人提到谷歌的闭包编译器。它不仅缩小/压缩,它还分析以查找和删除未使用的代码,并重写以最大限度地缩小。它还可以进行类型检查并警告语法错误。

JQuery最近从YUI Compresser切换到闭包编译器,并看到了“扎实改进

试试JSCrambler。我最近试了一下,印象深刻。 它提供了一组用于混淆的模板,为那些不太关心细节并且只想快速完成的人提供了预定义的设置。您还可以通过选择您想要的任何转换/技术来创建自定义混淆。

与我建议反对YUI Compressor的大多数其他答案相反;你应该使用谷歌关闭

不是因为它压缩更多,而是因为它会捕获JavaScript错误,例如a = [1,2,3,];,这会使IE变得混乱。

我建议首先使用YUI Compressor之类的东西缩小,然后使用http://www.javascriptobfuscator.com/之类的东西将所有字符串和数字转换为HEX值

这样,代码将变得几乎无法理解,我认为在这个阶段,黑客重新制定你的代码需要比从头开始重写更多的时间。重写和克隆是你无法阻止的。毕竟我们是自由人!

Dean Edward的Packer是一个出色的混淆器,尽管它主要混淆代码,而不是混淆代码中可能包含的任何字符串元素。

请参阅:在线Javascript压缩工具并从下拉列表中选择Packer(Dean Edwards)

我过去用过这个,效果不错。它不是免费的,但你绝对应该看看。
JavaScript混淆器和编码器

我正在使用闭包编译器实用程序进行Java脚本混淆。它缩小了代码并有更多混淆选项。 此实用程序可在以下URL的Google代码中获得:
关闭工具

但是现在有一天我听到了很多UglifyJS。你可以找到闭包编译器和UglifyJS之间的各种比较,其中Uglify似乎是赢家。
UglifyJS:一个快速的新JavaScript压缩器,用于Node.js,与闭包相提并论

很快我就会给丑陋的JS机会。

试试这个工具Javascript混淆器

我在我的HTML5游戏中使用它,它不仅将它的大小从950KB减少到150,而且使源代码不可读闭包编译器和迷你器是可逆转的,我个人不知道如何扭转这种混淆。

我已经使用Jasob多年了,它无疑是最好的混淆器。
它有一个先进的用户界面,但仍然直观,易于使用。 它还将处理超文本标记语言和CSS文件。

使用它的最佳方法是在所有私人变量前加上下划线之类的前缀,然后使用sort功能将它们组合在一起,并检查将它们作为混淆的目标。

用户仍然可以查看您的源代码,但当您的私有变量从_sUserPreferredNickName转换为a时,破译起来要困难得多。

引擎将自动统计目标变量的数量并对它们进行优先级排序以获得最大压缩。

我不为Jasob工作,我没有从推广他们中得到任何东西,只是提供一些友好的建议。
缺点是它不是免费的,而且有点贵,但与替代品相比仍然值得-“免费”选项甚至没有接近。

你绝对应该考虑看看混淆器

我超越了我们从其他工具(例如YUI压缩机谷歌关闭)中看到的典型Javascript缩小技巧。

模糊的代码看起来更像是加密的。不像我以前见过的任何东西。

你试过Bananascript吗?它产生高度压缩和完全不可读的代码。

我会怎么做:

A.巨魔黑客!

这将是我的假/混淆的秘密javascript代码LAUNCHER的第二部分。 你在源代码中看到的那个。

这个代码是什么?

  1. 加载真实代码
  2. 设置自定义标头
  3. 发布自定义变量

var ajax=function(a,b,d,c,e,f){
e=new FormData();
for(f in d){e.append(f,d[f]);};
c=new XMLHttpRequest();
c.open('POST',a);
c.setRequestHeader("Troll1","lol");
c.onload=b;
c.send(e);
};
window.onload=function(){
ajax('Troll.php',function(){
(new Function(atob(this.response)))()
},{'Troll2':'lol'});
}

B.稍微混淆代码

那是什么?

  1. 这与上面在Base64中的代码相同
  2. 这不是SECRET JavaScript代码

(new Function(atob('dmFyIGFqYXg9ZnVuY3Rpb24oYSxiLGQsYyxlLGYpe2U9bmV3IEZvcm1EYXRhKCk7Zm9yKGYgaW4gZCl7ZS5hcHBlbmQoZixkW2ZdKTt9O2M9bmV3IFhNTEh0dHBSZXF1ZXN0KCk7Yy5vcGVuKCdQT1NUJyxhKTtjLnNldFJlcXVlc3RIZWFkZXIoIlRyb2xsMSIsImxvbCIpO2Mub25sb2FkPWI7Yy5zZW5kKGUpO307d2luZG93Lm9ubG9hZD1mdW5jdGlvbigpe2FqYXgoJ1Ryb2xsLnBocCcsZnVuY3Rpb24oKXsgKG5ldyBGdW5jdGlvbihhdG9iKHRoaXMucmVzcG9uc2UpKSkoKX0seydUcm9sbDInOidsb2wnfSk7fQ==')))()

C创建一个难以显示的php文件,其中包含真实代码

这个php代码是什么?

  1. 检查正确的引用者(启动器的域/目录/代码)
  2. 检查自定义HEADER
  3. 检查自定义POST变量

如果一切正常,它会向您显示正确的代码,否则是假代码或禁止IP,关闭页面…无论什么。

<?php
$t1=apache_request_headers();
if(base64_encode($_SERVER['HTTP_REFERER'])=='aHR0cDovL2hlcmUuaXMvbXkvbGF1bmNoZXIuaHRtbA=='&&$_POST['Troll2']=='lol'&&$t1['Troll1']='lol'){
echo 'ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuaW5uZXJUZXh0PSdBd2Vzb21lJzsNCg==';//here is the SECRET javascript code
}else{
echo 'd2luZG93Lm9wZW4oJycsICdfc2VsZicsICcnKTt3aW5kb3cuY2xvc2UoKTs=';
};
?>

Base64引用者=http://here.is/my/launcher.html

SECRET javascript=document.body.appendChild(document.createElement('div')).innerText='Awesome';

FAKE=window.open('', '_self', '');window.close();

现在…如果你在SECRET javascript中定义事件处理程序,它可能是可访问的…你需要在外面用启动代码定义它们并指向嵌套的SECRET函数。

那么……有没有简单的方法来获取代码? document.body.appendChild(document.createElement('div')).innerText='Awesome';

我不确定这是否有效,但我正在使用chrome并检查元素,资源,网络,来源,时间轴,配置文件,审计,但我没有找到上面的行。

注1:如果你打开Troll.phpurl从检查元素->网络在Chrome你得到假代码。

注意2:整个代码是为现代浏览器编写的。Poly填充需要更多代码。

编辑

launcher.html

<!doctype html><html><head><meta charset="utf-8"><title></title><script src="data:application/javascript;base64,KG5ldyBGdW5jdGlvbihhdG9iKCdkbUZ5SUdGcVlYZzlablZ1WTNScGIyNG9ZU3hpTEdRc1l5eGxMR1lwZTJVOWJtVjNJRVp2Y20xRVlYUmhLQ2s3Wm05eUtHWWdhVzRnWkNsN1pTNWhjSEJsYm1Rb1ppeGtXMlpkS1R0OU8yTTlibVYzSUZoTlRFaDBkSEJTWlhGMVpYTjBLQ2s3WXk1dmNHVnVLQ2RRVDFOVUp5eGhLVHRqTG5ObGRGSmxjWFZsYzNSSVpXRmtaWElvSWxSeWIyeHNNU0lzSW14dmJDSXBPMk11YjI1c2IyRmtQV0k3WXk1elpXNWtLR1VwTzMwN2QybHVaRzkzTG05dWJHOWhaRDFtZFc1amRHbHZiaWdwZTJGcVlYZ29KMVJ5YjJ4c0xuQm9jQ2NzWm5WdVkzUnBiMjRvS1hzZ0tHNWxkeUJHZFc1amRHbHZiaWhoZEc5aUtIUm9hWE11Y21WemNHOXVjMlVwS1Nrb0tYMHNleWRVY205c2JESW5PaWRzYjJ3bmZTazdmUT09JykpKSgp"></script></head><body></body></html>

Troll.php

<?php $t1=apache_request_headers();if(/*base64_encode($_SERVER['HTTP_REFERER'])=='PUT THE LAUNCHER REFERER HERE'&&*/$_POST['Troll2']=='lol'&&$t1['Troll1']='lol'){echo 'ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSkuaW5uZXJUZXh0PSdBd2Vzb21lJzsNCg==';}else{echo 'd2luZG93Lm9wZW4oJycsICdfc2VsZicsICcnKTt3aW5kb3cuY2xvc2UoKTs=';}; ?>

您无法保护客户端代码:只需在GoogleChrome上按F12,暂停javascript执行,您将获得所有字符串,甚至是加密的字符串。

如果您正在编写服务器端javascript(即NodeJS),害怕有人入侵您的服务器,并希望让黑客的工作更加困难,让您有更多时间恢复访问权限,请使用javacript编译器

你需要在高级编译上使用闭包编译器,因为它是唯一一个重命名所有变量的工具,即使这些变量在多个文件/模块中使用。但它有一个问题:只有当你写入它的编码风格时它才有效。