网站: https://australia51.com/citywide/
在各个城市分类下,可以看到商家链接
而部分商家介绍中,含有邮箱
我们通过 f12 检查元素,发现邮箱字段在 html 里面。
但是抓包发现,该字段是
<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="86ede5e7f3f2e9eee9f3f5e3c6eee9f2ebe7efeaa8e5e9eb">[email protected]</a>
这个字段是需要 js 解密后,把新的 html 元素节点添加到文本中。 基本可以确定 data-cfemail 与邮箱有关系。我们可以通过 data-cfemail 属性来定位解密邮箱的 js 。
这里穿插一个小知识:标签中,以 data 开头的字段是自定义的字段
。js 获取该字段可以通过 dataset.cfemail
和 getAttribute("data-cefmail")
来获取。
因此,我们在 network 中 ctrl+f 粘贴 cfemail
。
data-cfemail 被赋值给了 f
查找 f ,发现 f 被 o.getAttribute 给了 i 。i = "86ede5e7f3f2e9eee9f3f5e3c6eee9f2ebe7efeaa8e5e9eb"
。接着,如果 i 为 true,l = n(i, 0);
,然后 createTextNode(l) 创造节点,把 d 节点替到 a 中。因此,邮箱节点是在 n 函数中创建的。一眼丁真,解密也是通过 n 函数实现的。
查找 function n 或者 n = function,调用了 r 函数。重复上述步骤得到如下代码
function r(e, t) {
var r = e.substr(t, 2);
return parseInt(r, 16)
}
function n(n, c) {
for (var o = "", a = r(n, c), i = c + 2; i < n.length; i += 2) {
var l = r(n, i) ^ a;
o += String.fromCharCode(l)
}
}
function n :
- 参数 n : 是 data-cfemail 的值
- 参数 c : 传递进来的时候是个固定值 0
function r :
- 参数 e : 从 n 中调用发现,e = n = data-cfemail
- 参数 t : 每次增加 2
r 函数把每次把 n 中以 t 开头的两个字符截取,这两个字符表示 16 进制的数。通过 parseInt 转为 10 进制,返回给 l 。用前两个字符的 10 进制值和后面的字符 10进制值 求异或,得到一个数字。再通过 n 中 String.fromCharCode 获取该数字表示的 ascii 字符,添加到 o 中。循环结束后,得到 邮箱地址
把这段代码改写为 java。以 “86ede5e7f3f2e9eee9f3f5e3c6eee9f2ebe7efeaa8e5e9eb
” 为例
public class Cfemail {
public static void main(String[] args) {
String cfemail = "dbb0b8baaeafb4b3b4aea8be9bb3b4afb6bab2b7f5b8b4b6";
String email = n(cfemail);
System.out.println("邮件地址:" + email);
}
public static String n(String cfemail) {
StringBuilder email = new StringBuilder();
int start = 0,
a = r(cfemail, start);
start += 2;
for (; start < cfemail.length(); start += 2) {
email.append((char) (r(cfemail, start) ^ a));
}
return email.toString();
}
public static int r(String cfemail, int index) {
return Integer.parseInt(cfemail.substring(index, index+2), 16);
}
}