前端知识库(lizh)
  • README
  • Bugs
    • 前端调试随笔
    • 浏览器常见问题概览
    • 浏览器兼容问题概览
    • HTML常见问题概览
    • CSS常见问题概览
    • JS常见问题概览
    • 移动端兼容性问题概览
    • 微信小程序开发
    • NodeJs常见问题概览
    • Mac常见问题概览
    • 微信开发遇坑指南
    • Npm包常见问题概览
    • 其他问题汇总
  • Css探索系列
    • CSS基础知识
    • CSS常见问答
    • CSS常见问答02
    • CSS应用示例
    • CSS应用示例02
    • 由Z Index引发的层叠上下文思考
    • 由浮动塌陷引发的块级格式上下文思考
    • CSS探索系列 Flex布局
    • CSS探索系列 Margin
    • CSS探索系列 Auto关键字
    • CSS探索系列 Gradient
    • CSS探索系列 Line Height
    • CSS探索系列 元素居中
    • CSS探索系列 动画
    • 为什么使用PostCSS处理CSS?
    • 重新认识伪类与伪元素
    • 自定义表单伪元素样式
    • 如何理解Css中的Display属性
    • 视口和软键盘对视口的影响
    • 关于Css
  • Frontend
    • 00 关于Web前端
    • 01 前端知识概览
    • 02 常用前端库概览
    • 基础 00 前端常见问题01
    • 基础 01 浏览器缓存
    • 基础 02 浏览器工作原理
    • 基础 03 谈谈前端跨源问题及解决方法
    • 进阶 01 Web性能优化
    • 进阶 02 搜索引擎优化(SEO)
    • 进阶 03 前端模块化编程
    • 进阶 04 规范代码:Linter、Prettier、EditorConfig
    • 进阶 11 前端自动化测试
    • 高级 01 前端安全
    • Vue2.X原理篇
    • Vue3初步了解及迁移指南
    • 重读Vue教程
    • React17.X原理篇
    • 你必须知道的React问题
    • 重读React教程
    • 聊一聊Cookie的一些问题
    • 如何理解HTTP响应的状态码
    • HTTP的历史演变及概述
    • Webpack4.X原理篇
    • Webpack基础入门篇
    • Webpack构建优化篇
    • TypeScript使用指南
    • 代码规范
      • 前端规范
      • HTML
      • CSS
      • JS
  • Html探索系列
    • HTML基础知识
    • HTML基础知识02
    • HTML常见问答
    • HTML经典实践用例
    • HTML元素的宽高及位置详解
    • Video元素的使用和常见问题总结
    • Html探索系列 Meta标签
    • DOCTYPE:文档类型与浏览器模式
    • DHTML(动态网页)简介
    • HTML标签详解
    • HTML布局的几种方式
    • HTML全局属性
    • 关于Html
  • Js探索系列
    • 基础知识
    • 常见问答
    • 应用示例
    • 趣味示例
    • 基础篇 05 AJAX
    • 基础篇 06 Window对象
    • 基础篇 07 Error、JSON、Math、Console对象
    • 基础篇 08 History、URL、Screen、Navigator、Location对象
    • 基础篇 09 文档对象模型(DOM)
    • 基础篇 10 Document对象
    • 基础篇 11 Element对象
    • 基础篇 12 Event对象
    • 基础篇 13 键盘、鼠标、触摸事件
    • 基础篇 15 CSS对象模型(CSSOM)
    • 进阶篇 01 Prototype对象和继承
    • 进阶篇 02 Promise对象
    • 进阶篇 07 迭代器(Iterator)
    • 进阶篇 08 Generator和Async函数
    • 进阶篇 09 JavaScript异步编程
    • Date对象和日期时间字符串格式
    • Canvas基础入门篇
    • Canvas进阶篇
    • SVG基础入门篇
    • 四种判断数据类型方法的优缺点
    • 深入理解JavaScript的浅拷贝和深拷贝
    • 谈谈JavaScript的作用域和上下文
    • 复制内容到剪贴板
    • 关于Javascript
  • NodeJs
    • 关于Node.Js
    • Node.Js:三种调试方法
    • Npm包管理器简介及一些机制
    • NPM:Package.Json详解(中文)
    • NPM:从零开始,开发一个软件包
    • NPM:常用命令
    • Node.Js:Fs(文件系统)
    • Node.Js:Global(全局变量)
    • Node.Js:HTTP
    • Node.Js:Module(模块)
    • Node.Js:Path(路径)
    • Node.Js:Readline(逐行读取)
  • Research
    • 极细边框(1px边框)实现方式
    • 如何监控前端异常?
    • H5页面跳转和刷新
    • Web主题切换和个性化定制方法总结
    • Vue SSR(服务端渲染)的简单实现
    • 基于Create React App打造代码规范化的React+Ts项目
    • H5可视化编辑
    • Web常用功能
    • Javascript加密混淆
    • Vue如何导入TypeScript
    • 移动端PDF预览
    • 纯CSS绘制箭头
    • 网站性能测量和优化方法
  • Tech
    • GOOGLE浏览器的搜索技巧
    • Curl的用法指南
    • Sublime3插件篇
    • Charles安装及使用
    • Nginx基础使用
    • 排序算法(Javascript)
    • 代码整洁之道(摘录笔记)
    • Java的24种设计模式与7大原则
    • 观察者和发布订阅模式
  • Tools
    • Git
      • Git基础教程
      • Git常见问题
    • Gitbook
      • Gitbook入门篇
      • Gitbook插件篇
      • Gitbook进阶篇
由 GitBook 提供支持
在本页
  • 为什么要对JS代码进行保护?
  • 如何对Javascript代码进行保护?
  • 怎么实现代码的不可读不可分析?
  • JavaScript加密
  • JavaScript混淆
  • eval混淆
  • hash混淆
  • 压缩混淆
  • js混淆器大致有两种
  • 混淆插件
  • 反调试
  • 把js代码转化为二进制字节码
  • 代码可以放置其他位置(非js文件)
  • 代码块预处理工具
  • 在线加密混淆工具

这有帮助吗?

  1. Research

Javascript加密混淆

为什么要对JS代码进行保护?

  • JS代码运行于客户端。

  • JS代码是公开透明的。

由于这两个原因,至使JS代码是不安全的,任何人都可以读、分析、复制、盗用,甚至篡改。因此出现了很多安全事件,典型的如:自己的原创程序代码被盗用、网站数据被篡改等等。

如果你不想让自己的代码被它人看到、不想它人了解你的代码功能,或者想降低被不怀好意的人甚至是黑客攻击。那么你应该尝试使用JS保护。

如何对Javascript代码进行保护?

  • 使JS代码不可读

    让攻击者无法理解代码功能,也无法篡改任何功能。

  • 使JS代码不可分析

    让攻击者不能进行动态跟踪调试。

    代码不可读之后,攻击者往往会进行动态跟踪调试,以期逆向还原出原始代码,或分析出程序功能。

怎么实现代码的不可读不可分析?

  • 代码加密:加密后的代码看似乎杂乱,但代码在执行前需要进行解密才能执行,只要找到解密函数即可还原出原始代码,所以此方式安全系数较低;

  • 虚拟机技术:可以屏蔽JS原始关键字,但兼容性较差,无法保证在多端,多浏览器下运行;

  • 代码混淆:使用字符串阵列化、平展控制流、多态变异、僵尸函数等手段,使代码变的不可读不可分析,达到最终保护的目的。且不影响代码原有功能。是理想、实用的JS保护方案。

JavaScript加密

密码学有一句话: 当你采用的加密模式,使得攻击者为了破解所付出的代价 远远超过其所获得的利益之时,你的加密方案就是安全的。

  • 代码无法做到完全不可读,只能做到很难读。

  • 只能增加逆向难度,从而提高山寨逆向成本。

造成这两点的原因是,你无法绕过浏览器的web inspector(下文简称WI)。有人会说在JS做黑盒,但其最终调用的还是浏览器提供的API。你是无法防止他人在你调用API时候拦截的。除非你的代码拥有比WI更高的API权限。否则都是没有用。

JavaScript混淆

脱离混淆的Javascript加密是伪命题,无论怎么加密,如果不加以混淆手段保护,都没有意义。

如同传统软件的加壳保护,js混淆给底层的加密算法加了最基本的保障,在js层面来说,混淆和加密一定是相辅相成的。

由于js是动态指令码语言,在http中传输的就是原始码,逆向起来要比打包编译后的软体简单很多。暴露在外的程式码没有绝对的安全,但是在对抗中,精心设计的混淆程式码能够给破坏者带来不小的麻烦,也能够为防守者争取更多的时间,相对于破解来说,混淆器规则的更替成本要小得多,在高强度的攻防中,可以大大增加破解者的工作量,起到防御作用。从这个角度来讲,关键程式码进行混淆是必不可少的步骤。

JS混淆归结为三类: eval类型,hash类型,压缩类型

也是最早JS出现的混淆加密,据说第一天就被破解,修改一下代码,alert一下就可以破解了。

hash混淆

  • miniui 使用的[JSA加密](https://sourceforge.net/projects/jsintegration/files/tools/_ JSA-20071021/)

JSA加密 和 javascript-obfuscator 的区别:

压缩混淆

js混淆器大致有两种

  • 通过正则替换实现的混淆器

  • 通过语法树替换实现的混淆器

第一种实现成本低,但是效果也一般,适合对混淆要求不高的场景。

第二种实现成本较高,但是更灵活,而且更安全,更适合对抗场景。基于语法层面的混淆器其实类似于编译器,基本原理和编译器类似,我们先对编译器做一些基本的介绍。

编译器工作流程

简单的说,当我们读入一段字串文字(source code),词法分析器会把它拆成一个一个小的单位(token),比如数字1 是一个token, 字串'abc'是一个token等等。接下来语法分析器会把这些单位组成一颗树状结构(AST),这个树状结构就代表了token们的组成关系。比如1 + 2 就会展示成一棵加法树,左右子节点分别是token - 1 和token - 2 ,中间token表示加法。编译器根据生成的AST转换到中间程式码,最终转换成机器程式码。

混淆器工作流程

编译器需要把原始码编译成中间程式码或者机器码,而我们的混淆器输出其实还是js。所以我们从语法分析之后往下的步骤并不需要。想想我们的目标是什么,是修改原有的js程式码结构,在这里面这个结构对应的是什么呢?就是AST。任何一段正确的js程式码一定可以组成一颗AST,同样,因为AST表示了各个token的逻辑关系,我们也可以通过AST反过来生成一段js程式码。所以,你只需要构造出一颗AST,就能生成任何js程式码!

规则设计

知道了大致的混淆流程,最重要的环节就是设计规则。我们上面说了,我们需要生成新的AST结构意味着会生成和原始码不一样的js程式码,但是我们的混淆是不能破坏原有程式码的执行结果的,所以混淆规则必须保证是在不破坏程式码执行结果的情况下,让程式码变得更难以阅读。

具体的混淆规则各位可以自行根据需求设计,比如拆分字串、拆分阵列,增加废程式码等等。

混淆插件

一个免费和高效的JavaScript混淆器(包括ES2017)。让你的代码更难复制,防止别人窃取你的成果。这个工具是一个优秀的Web UI(并且是开源的)

这个库很像在线JavaScript代码压缩网站,实际上也可以做一个在线压缩代码的网站。不过他吸引我的是他的cli工具。

❗ 作者在Github上说了没有很多时间来维护这个项目了,使用请慎重考虑。

//源码
function aa () {
	console.log('aaa')
}
aa()

//混淆后
var _cs=['\x61\x61\x61']; function _f0() { console.log(_cs[0]) } _f0()

是一款JS代码处理工具,提供了压缩,混淆和代码规范化等功能。通过以下传参数,可以对js做些混淆:

mangle: {
	toplevel: true, // — 混淆在最高作用域中声明的变量名(默认false)
	eval: true,	// - 混淆在eval 或 with作用域出现的变量名(默认false)
	properties: {} //**警告:**这能会搞崩你的代码。混淆属性名跟混淆变量名不一样,是相互独立的。会混淆对象所有可见的属性名,除了DOM属性名和JS内置的类名。
}

uglify-js可以对变量名、属性、方法名进行混淆,无法对字符串进行混淆。

与uglify-js类似。有对应webpack 4\webpack 3的插件。

jscrambler是一个商业级工具,看了很多社区的评论,这个目前是最好的,需要付费。

jsfuck 是一个开源的js 混淆工具,原理比较简单,其实就是通过特定的字符串加上下标定位字符,再由这些字符替换源代码,从而实现混淆。而且文件体积会受很大影响。

//源码
alert('a')

//转换后
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+........

反调试

由于JavaScript自带debugger语法,我们可以利用死循环性的debugger,当页面打开调试面板的时候,无限进入调试状态。

代码可以放置其他位置(非js文件)

放到png文件中:利用HTML Canvas 2D Context获取二进制数据的特性,可以用图片存储脚本资源。

放在css文件中:利用content样式能存放字符串的特性,同样可以用来存储脚本资源。

在线加密混淆工具

https://www.jsjiami.com/ (在线)

https://www.sojson.com/jsjiemi.html (在线)

参考链接:

上一页Web常用功能下一页Vue如何导入TypeScript

最后更新于3年前

这有帮助吗?

fundebug使用的

通过[JSA加密](https://sourceforge.net/projects/jsintegration/files/tools/_ JSA-20071021/)混淆后生成的代码,一下,可以发现,其实没有做什么什么修改,只是做了一些变量替换。想还原也比较简单的。这里就不拿它来做代表,也没有什么人用。

通过混淆后生成的代码,一下,分析一下可以发现,其实多了一个字典,所有方法变量,都有可能存在字典中,调用时先调用字典还原方法名变量再执行。其实入口都是变量的规则。

是目前前端性能优化的常用工具,以为代表。

对编译器更多细节感兴趣的同学可以移步龙书:

参考:提供商业混淆服务的的混淆规则

利用HTML 获取二进制数据的特性,可以用图片存储脚本资源。

国内最知名的JS加密当属JShaman
Node.js加密算法库Crypto
eval混淆
javascript-obfuscator
beautifier
javascript-obfuscator
beautifier
uglify
编译原理
混淆器设计?
jscramble
javascript-obfuscator
uglify-js
closure-webpack-plugin
jscrambler
jsfuck(开源)
把js代码转化为二进制字节码
Canvas 2D Context
代码块预处理工具
加密基础知识四 前端JS加密传输 crypto-js
js混淆加密,通过混淆Js程式码让别人(很难)无法还原
移动时代的前端加密