這是個非常非常簡單的js加密鏈接。
這是一個導航網站,實際鏈接到的網站的url被加密了,並沒有直接顯示在頁面上,首先開發者模式選中鏈接元素:
發現這個鏈接有一個onclick事件,是調用了visit方法傳入了一個很長的看上去像是base64的字符串,猜測實際的url應該就是根據這個字符串生成的,但是怎么跟進去visit方法呢,這個方法能夠在html中直接訪問到,說明其作用域是全局的,那么切換到console面板,輸入剛才那個函數的名稱visit回車將其打印:
單擊輸出,跳轉到函數所在的代碼:
可以看到這部分關鍵的代碼在strdecode函數中,如法炮制,跳轉到strdecode所在的代碼:
單擊跳轉:
這部分用到了兩個全局變量,Gword和hn,通過搜索請求找到這兩個變量都在頁面doc里聲明的:
hn就是域名的主機名部分轉為小寫,即“ac.scmor.com”,然后就是Gword貌似是作者的郵箱,這樣寫在頁面代碼中還不得被各種爬蟲發的小廣告給煩死啊。。。
搞清楚了這兩個變量,再回到之前的js:
默認情況下每個鏈接都會有一串看上去像是base64的字符串,這里strdecode傳入的參數就是那個字符串,傳進來的字符串首先進行base64解碼,然后基於Gword和hn轉換為一個新的base64編碼的字符串,然后繼續對其base64解碼,就得到了最終的url。
根據上面的邏輯編寫出代碼:
package cc11001100.misc.crawler.js.acscmorcom; import cc11001100.misc.crawler.utils.HttpUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jsoup.Connection; import java.util.ArrayList; import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * http://ac.scmor.com/ * * @author CC11001100 */ @Slf4j public class AcscmorcomCrawler { public static List<String> getMirrorSiteLink() { String responseBody = HttpUtil.request("http://ac.scmor.com/", null, Connection.Response::body); if (StringUtils.isBlank(responseBody)) { log.error("response empty"); return Collections.emptyList(); } Matcher matcher = Pattern.compile("autourl\\[\\d+] = \"(.+?)\"").matcher(responseBody); List<String> result = new ArrayList<>(); while (matcher.find()) { result.add(decodeToLink(matcher.group(1))); } return result; } /** * <pre> * function strdecode(string) { * string = base64decode(string); * key = Gword + hn; * len = key.length; * code = ''; * for (i = 0; i < string.length; i++) { * var k = i % len; * code += String.fromCharCode(string.charCodeAt(i) ^ key.charCodeAt(k)); * } * return base64decode(code); * } * </pre> * * @param likeBase64 * @return */ private static String decodeToLink(String likeBase64) { String hn = "ac.scmor.com"; String gword = "author: link@scmor.com."; String s1 = base64DecodeToString(likeBase64); String key = gword + hn; StringBuilder result = new StringBuilder(); for (int i = 0; i < s1.length(); i++) { char c = (char) (s1.charAt(i) ^ key.charAt(i % key.length())); result.append(c); } return base64DecodeToString(result.toString()); } private static String base64DecodeToString(String raw) { return new String(Base64.getDecoder().decode(raw)); } public static void main(String[] args) { // System.out.println(decodeToLink("AD0mWAw2VVYgWiAdDB4LHQwqaxY2XxcVL0M9FiEYTxM=")); List<String> list = getMirrorSiteLink(); System.out.println("count: " + list.size()); list.forEach(System.out::println); // count: 16 // http://so.hiqq.com.cn/ // https://sci-hub.org.cn/ // https://xueshu.soogle.top // http://www.ndtsg.com/ // https://www.80xueshu.com/ // https://xs.glgoo.top/scholar // https://scholar.123admin.com/ // https://g3.luciaz.me/scholar // http://nav.hiqq.com.cn/twy/ // https://a.g456.top // https://g.sudo.gq/ // https://q.g456.top // https://ice.g456.top // http://206.189.135.241/ // https://www.kuaimen.bid/ // https://gg.chn.moe/ } }
輸出:
.