看到北港武德宫动态产生 email 而来的 email 混淆字串产生器

偶然的机会,看到北港武德宫的网站,相当精美,一改过去对宫庙网站的印象。

照例,要打开原始码来学习一下,马上发现一串不太寻常的 JS

<script type="text/javascript">//<![CDATA[var l=new Array();l[0] = '>';l[1] = 'a';l[2] = '/';l[3] = '<';l[4] = '|119';l[5] = '|116';l[6] = '|46';l[7] = '|103';l[8] = '|114';l[9] = '|111';l[10] = '|46';l[11] = '|101';l[12] = '|100';l[13] = '|117';l[14] = '|119';l[15] = '|64';l[16] = '|110';l[17] = '|105';l[18] = '|109';l[19] = '|100';l[20] = '|97';l[21] = '>';l[22] = '"';l[23] = '|108';l[24] = '|105';l[25] = '|97';l[26] = '|109';l[27] = '|95';l[28] = '|101';l[29] = '|100';l[30] = '|117';l[31] = '|119';l[32] = ' class="';l[33] = '"';l[34] = '|119';l[35] = '|116';l[36] = '|46';l[37] = '|103';l[38] = '|114';l[39] = '|111';l[40] = '|46';l[41] = '|101';l[42] = '|100';l[43] = '|117';l[44] = '|119';l[45] = '|64';l[46] = '|110';l[47] = '|105';l[48] = '|109';l[49] = '|100';l[50] = '|97';l[51] = ':';l[52] = 'o';l[53] = 't';l[54] = 'l';l[55] = 'i';l[56] = 'a';l[57] = 'm';l[58] = '"';l[59] = '=';l[60] = 'f';l[61] = 'e';l[62] = 'r';l[63] = 'h';l[64] = ' ';l[65] = 'a';l[66] = '<';for (var i = l.length-1; i >= 0; i=i-1) {if (l[i].substring(0, 1) === '|') document.write("&#"+unescape(l[i].substring(1))+";");else document.write(unescape(l[i]));}//]]></script>

稍微研究之后,发现这是用来动态产生网站上的 email。之所以这么费事,因为有些爬虫会去抓网站上的 email,作为垃圾邮件的发送名单,某些网站安全扫描软体,也会把网站上有 email 列作缺点,因此这种作法是好的。

它的做法,是:

将 email 的字串转成 ascii 的10进位号码将号码转成带有|前缀的字串将包含有mailto 的 email 的 html 片段,转成阵列后再反转,增加混淆程度

看起来是简单易作的方法,只是看到那一长串的阵列宣告,就有点不舒服,总觉得在维护上应该会有点麻烦。

如果是我自己来做,要怎么改呢?在最低限的修改前提下,我会希望那段阵列是有办法自动产生,产生之后再放到网站上去,这样如果需要修改 email,或是相同的方法要套到别的网站上去,都会很快。

但如果是有产生器来产出,于其产生阵列,不如产出字串,在複製/贴上时,会更简单一点。

于是写了下面的产生器(https://jsfiddle.net/brecht/fsq6e7uo/2/):

<script>  //填入网站所使用的 email  var email = "service@example.com";  //填入该 email 所使用的 HTML 片段    var template = '<a href="mailto:{{email}}" class="email_style">{{email}}</a>';  var EmailMixer = {    mix: function(email, template) {      this.template = template.replace(/{{email}}/g, this.toCharNo(email));      var arr = this.revert(this.template);      return arr.join(";");    },    toCharNo: function(str) {      var code = "";      for (var i = 0; i < str.length; i++) {        code += ("|" + str[i].charCodeAt() + ";");      }      return code;    },    revert: function(str) {      var reverseArr = [];      var encodeStr = "";      var isEnCodeStr = false;      while (str) {        theChar = str[0];        if (isEnCodeStr === true) {          if (theChar !== ";") {            encodeStr += theChar;          } else {            isEnCodeStr = false;            reverseArr.unshift(encodeStr);            encodeStr = "";          }        } else {          if (theChar === "|") {            isEnCodeStr = true;            encodeStr += theChar;          } else {            reverseArr.unshift(theChar);          }        }        str = str.substr(1);      }      return reverseArr;    }  }  document.write(EmailMixer.mix(email, template));</script>

修改上面 email 的资讯,以及依自己的网站需要,修改 html 片段的组成,存成一个 html 档案,就会生出一个字串了。

不想用网页执行,也可以去掉头尾的标记,把最后一行 document.write(EmailMixer.mix(email, template)); 改成 console.log(EmailMixer.mix(email, template)) 之后,存成js档,就可以用 node xxx.js 执行,在命令列底下取得字串了。

有了字串之后,就要想办法还原,动态产生的方法如下(https://jsfiddle.net/brecht/kq38vw03/3/):

<script type="text/javascript">  //由 email 字串产生器产出的字串,因字串符中有使用双引号,因此产生的字串要用单引号来表示  var str = '>;a;/;<;|109;|111;|99;|46;|101;|108;|112;|109;|97;|120;|101;|64;|101;|99;|105;|118;|114;|101;|115;>;";e;l;y;t;s;_;l;i;a;m;e;";=;s;s;a;l;c; ;";|109;|111;|99;|46;|101;|108;|112;|109;|97;|120;|101;|64;|101;|99;|105;|118;|114;|101;|115;:;o;t;l;i;a;m;";=;f;e;r;h; ;a;<';  renderMail(str);  function renderMail(str) {    var arr = str.split(";");    arr.reverse();    for (var i = 0; i < arr.length; i++) {      document.write(unescape(arr[i].replace(/\|(.*)/, "&#$1;")));    }  }</script>

只要把 str 的字串换成上一步生成的字串,然后把上面这一段 script 片段,放到要产生 email 的地方即可。

ps. 这篇文章放到gist没多久,同事做了验证,这种方式防得了一般爬网页原始码的爬虫,但是防不了一些会将网页 DOM 生成后再爬的,例如 Google 搜寻引擎


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章