jother编码是我最开始想写的内容,原因有两点:1.原理比较简单,不需要太多关于算法的知识。2.比较有趣,是在对javascript有了很深的理解之后催生的产物。如果你只需要知道jother编码和解码的方法,那么你可以直接跳过文章正文看结论部分。如果你想知道其中的原理那么你可以带着这个疑问和我一起开始jother探索之旅。

在出发前,我们需要做一些准备工作,就如同去沙漠探险需要带上充足的水和干粮一样。有几样东西需要读者准备一下:1.javascript匿名函数相关知识。2.递归思想。3.javascript变量类型基本知识。4.javascript一些基本函数。5.一颗好奇的心。

那么我们现在就出发吧。首先给出一个非官方的jother编码定义:jother是一种运用于javascript语言中利用少量字符构造精简的匿名函数方法对于字符串进行的编码方式。其中少量字符包括:"!"、"+"、"("、")"、"["、"]"、"{"、"}"。只用这些字符就能完成对任意字符串的编码,我们可以得出两个结论:1.递归是不可或缺的。2.编码压缩率肯定是大于100%而且很高,也就是说编码之后的长度比原长度大很多。

我们先来看一个匿名函数的例子:

[function(){ alert(1) }()];

使用如果你把上面代码保存到之间,然后把保存的文件以html后缀结尾,并在浏览器中打开,你会看到一个弹框,弹框的内容为"1"。如果你习惯用console.log而不喜欢alert也是可以的。 紧接着我们稍微修改一下原代码:

alert([function(){ alert(1) }()]);

保存一下,再次刷新页面,我们可以看到先弹出了"1",后弹出了一个空白的框。

对于这个现象我们的解释是:第一次执行了alert(1),第二次执行了alert(函数)。而函数是一个匿名函数(有返回值),所以就是弹出的就是函数本身的返回值(如果无返回值的函数则是undefined)。如果你注意到了弹框的先后次序,那很好,说明你特别细心,这个原因是由于函数入栈和出栈导致的,在alert函数调用了匿名函数,当然要等待匿名函数先返回,然后自己才能返回。通过这里我们需要注意的是,javascript在alert函数中是可以执行新的函数的,而不仅仅是输出一个字符串。

下面我们再修改一下源代码:

alert([]); 保存执行一下,你看到了什么?依然弹了一个空白的框框,这个就说明[]也是一个匿名函数,而且是最简单的匿名函数,它也执行了。由于函数体都去掉了,所以导致仅仅留下了一个匿名函数的“空壳”。 我们再接着修改源码: alert(+[]);

你发现了什么?弹出了0,不是吗?因为我们的运算符“+”,对于无法显示出来的空(void)的函数返回值进行了强制类型转换,将其转为了整形的“0”。 道生一,一生二,二生三,三生万物。

我们只有“0”如何生“1”呢?不要急,看下面一个例子:

alert(![]);

运行以后,依然弹框了,弹出了一个false,false是什么?是bool(在javascript里通常是指"boolbean")运算符,为什么变成了false?是因为"!"对其进行了强制类型转换。但是这又有什么用呢?不要急,我们用两个"!"来试试:

alert(!![]);

这次屏幕上弹出了"true",虽然仍然是bool类型,但是已经更加接近"1"了,如何把“true”变为“1”呢?不要看后面的内容,请大家思考一分钟。 我想大部分人都已经有答案了,让我们来验证一下:

alert(+!![]);

对,就是这样!使用加号进行强制类型转换,将true转换为"1"。有了1就好办了,至少其他数字我们都可以表示了,下面来验证一下你的想法:

"+[]",//0 "+!![]", //1 "!![]+!![]", //2 "!![]+!![]+!![]",//3 "!![]+!![]+!![]+!![]", //4 "!![]+!![]+!![]+!![]+!![]",//5 "!![]+!![]+!![]+!![]+!![]+!![]", //6 "!![]+!![]+!![]+!![]+!![]+!![]+!![]",//7 "!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]", //8 "!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]" //9

它很酷,不是吗? 只有数字还不行,我们需要字符,字符串。那么数字如何变为字符串呢?这里就有点文章可做了,我一开始想到的是ascii码,但是如何将ascii码转换成字符呢?我们需要引入函数才行,但是能不能不引入新的函数?我们换一种思路来考虑这件事情:想办法生成一个数组,然后用数组中已有的字符直接指定下标显示。比如我们很容易就能产生的"true"、"false"。我们想要表示"a"的时候直接想办法输出一个"false",然后制定下标为"1"(注意这里"f"的下标为"0",所以"a"就是"1")不就可以了吗?

我们来证实一下:

alert((![])[+!![]]); 怎么样?看到了a吗?如果你回答:“看到了”,那么你肯定没有认真去动手做。这里输出的是“undefined”,这是为什么呢?因为![]表示的是false这个false是bool型的,当我们取一个bool型变量下标的时候javascript是不能允许的,所以这里给了一个undefined。那么我们如何想办法将bool型转为字符串呢?这里用到的是:"![]+[]"。 alert(typeof(![]+[]));

看到了吗?变成了string。这里就是说明了javascript在对bool类型和number类型做“+”运算的时候将其强制转换为了string类型。大家也可以自己动手用alert(typeof(xxx))试着判断一下之前提到的那些类型是否正确。

利用这个办法,我们就可以表示"a"、"e"、"f"、"l"、"r"、"s"、"t"、"u"。当然还有一个很容易得到的字符串——"undefined",又可以丰富一下我们的字典。这样,还是有很多字符无法表示,下面我们就来讨论一种扩展,Object:

alert({}); 在javascript中"{}"表示一个最简单的类,如果运行上面的代码,会显示"[object Object]",同样这个object也是不能直接按数组下标获取元素的,我们需要做一个转换:({}+[]) alert(({}+[])[+[]]); 这样就可以取到第0个元素:"["。 做这个扩展其实主要是为了得到一个重要的字符"o",因为我们后面要说的sort函数需要用到它。 0x01 函数

首先我们来补充一个前置概念——javascript匿名函数的原生形式

[]['sort']['constructor']('函数体')(2881064151);

这样的构造可以执行任意javascript代码。

为了吸引读者眼球,这里先埋下伏笔:

利用jother编码可以在不用字母和数字的情况执行任意js代码,这个在XSS攻击中是十分有用的,唯一的不足就是编码太长了,如何缩短编码,其实还是有些办法的,而且结合真实的攻击环境中可能允许输入一些字符,我们就可以指替换部分代码。比如代码中对“alert”过滤,是否可以利用jother重新编码函数,用匿名函数调用“alert”,在调用“alert”的时候仅替换alert中的r,这样就形成了“ale”+xxx(jother)+“t”的形式。

下面就开始正式介绍如何利用jother编码调用匿名函数,在第一篇内容中我们已经拥有了一些字符串,这些字符串中的每个字符我们都可以利用数组下标定位的方式取到,我们来看一下这些字符都有什么:“true”、“false”、“undefined”、“[object Object]”(注意这里有个很有用的字符空格)。我们来对比一下[]['sort']['constructor']1;我们还缺少什么?其实已经什么都不缺了。下面我们来构造这样的一个形式,为了直观我直接给出构造的结果: [][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!![]+!![]]+({}+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+(!![]+[])[+[]]+({}[[]]+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]])()

这个例子实际上等价于:

[]['sort']['constructor']('return location')() 注意这里是return后面的空格就是需要用前面我们提到的[object Object]来取到。

有了这个函数我们就可以获取很多有用的字符了,比如在线的话,就可以取到"http(s)://" 这样就有了新的字符“p”。

有了这个字符以后我们就可以利用escape和unescape函数组合出更多的字母以及特殊符合,例如利用escape(' ');得到“%20”,利用“%”和数字字母组合再unescape得到新的字符。

后面的事情就由你来自由发挥了。

当然构造一些字母的时候还有其他的技巧,比如构造出Infinity 其实是利用数字接近无穷大,原理就是想办法达到 e的100000次方,我们在这里就不一一列出了,具体的思路可以参照附件中的jother.js,这是jother发明者写的一段jother encode的demo。

bool型变量下标的时候javascript是不能允许的的更多相关文章

  1. 如果有三个Bool型变量,请写出一程序得知其中有2个以上变量的值是true

    下面这篇文章是从StackOverflow来的.LZ面试的时候遇到了一道面试题:“如果有三个Bool型变量,请写出一程序得知其中有2个以上变量的值是true”,于是LZ做了下面的这样的程序: bool ...

  2. STM32自带的bool型变量

    这些标着位会让你的程序使用起来更方便. First you need to include "STM32f10x_type.h" /*布尔型变量*/typedef enum{FAL ...

  3. c语言中有bool型变量吗?

    C语言里面是没有bool(布尔)类型的,C++里面才有,这就是说,在C++里面使用bool类型是没有问题的. bool类型有只有两个值:true =1 .false=0. 但是,C99标准里面,又定义 ...

  4. C逻辑型变量——时控灯例子

    在C99标准颁布之前,我们通常都是用1或者0来表示逻辑的真与假,因此,当我们需要在程序中传递这种逻辑数据时,我们都是用整型数据类型int来表示这种逻辑型数据.然而,使用整型数据类型int来表示逻辑型变 ...

  5. sqlmap Bool型&延时型 检测策略分析

    目录 sqlmap Bool型&延时型 检测策略分析 0x00 预备-queryPage() 0x01 bool型检测策略 判断依据 quick_ratio() 案例 0x02 延时型 判断依 ...

  6. 枚举型变量 ErrorStatus HSEStartUpStatus及使用

    ErrorStatus和C语言中的int .char一样,后面定义的HSEStartUpStatus是这个变量.举例,你的ErrorStatus 代表bool类型的0或者1. typedef enum ...

  7. seaborn 数据可视化(一)连续型变量可视化

    一.综述 Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易,图像也更加美观,本文基于seaborn官方API还有自己的一些理解.   1.1.样式控制: ...

  8. c语言字符串比较与bool型

    c++字符串string,定义的变量,能够通过比较符号,直接进行比较. 而c语言则不能通过char数组定义的变量,来直接比较.应用下面的方法: #include <string.h> in ...

  9. (转)C语言16进制输出字符型变量问题

    最近在做一个C的嵌入式项目,发现在C语言中用printf()函数打印字符型变量时,如果想采用"%x"的格式将字符型变量值以十六进制形式打印出来,会出现一个小问题,如下: char  ...

随机推荐

  1. 把包发布到npm官网

    一.包 包就是多模块的集合,CommonJS的包规范给程序员提供了组织模块的标准,减少沟通成本. 规范: 所有的模块放在demo文件夹下(包名)的lib文件夹里面 在lib文件夹的同级目录下新建ind ...

  2. MFC操作注册表

    1.创建和修改注册表 BOOL CTestToolCtr::GetHkey(CString strHkey, HKEY& hkey) { == strHkey.CompareNoCase(_T ...

  3. 缓存淘汰算法--LRU算法

    1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也 ...

  4. html常用标签介绍

    常用标签介绍 文本 最常用的标签可能是<font>了,它用于改变字体,字号,文字颜色. 点击查看效果 <font size="6">6</font&g ...

  5. 【Android进阶学习】shape和selector的结合使用(转)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://liangruijun.blog.51cto.com/3061169/732310 ...

  6. android中如何用代码来关闭打开的相机

    场景描述: 比如你再应用中打开了系统相机,然后需要在几分钟后自动关闭这个系统相机(不是手动关闭) 1.在activityA中利用startActivityForResult(intent,reques ...

  7. linux man的使用

    在Linux中无论是管理系统还是在Linux环境下编程,内嵌的手册man都是一个很好用的工具,“Linux下不懂得就找man”(man是manual的意思).本文将介绍我所知道的所有关于man的知识( ...

  8. redis——学习之路五(简单的C#使用redis)

    redis官方推荐使用的客户端程序 打星星表示推荐使用的客户端程序,一个笑脸表示最近6个月内有过正式活动的.http://redis.io/clients/#c 从这里我们可以判断官方推荐我们使用Se ...

  9. BZOJ 4066 简单题 ——KD-Tree套替罪羊树

    [题目分析] 直接x,y二维轮番划分,暴力即可. 套上替罪羊,打碎重构,对于时间复杂度有了保证. 写起来好麻烦,重构的技巧很棒! [代码] #include <cstdio> #inclu ...

  10. 十个免费的web应用安全检测工具

    Websites are getting more and more complex everyday and there are almost no static websites being bu ...