[JS reverse hundred examples] the second question of the anti climbing practice platform for netizens: jjencode encryption

Time:2022-5-4

Follow wechat official account: brother K crawler, and continue to share advanced crawler, js/ Android reverse and other technical dry goods!

statement

All contents in this article are only for learning and communication. The packet capturing content, sensitive website and data interface have been desensitized. It is strictly prohibited to use them for commercial and illegal purposes, otherwise all the consequences have nothing to do with the author. If there is infringement, please contact me and delete them immediately!

Reverse target

  • Goal: webmaster anti crawler practice platform question 2: jjencode encryption
  • Link:http://spider.wangluozhe.com/challenge/2
  • Introduction: this question is similar to the first question, which requires to collect all the numbers on 100 pages and calculate the sum of all data. The algorithm used in the second question is SHA1 magic revision, and there is also a jjencode encryption

01.png

Introduction to jjencode

Jjencode was originally a web program developed by Japanese author Yosuke Hasegawa in 2009. It can encode any JavaScript into a confused form using only 18 symbols[]()!+,\"$.:;_{}~=, online experience address:https://utf-8.jp/public/jjencode.html, if you want to explore its principle in depth, you can reply to [jjencode] on the K brother crawler official account to obtain the PDF of its detailed principle introduction.

The author has a hint: jjencode is easy to decode. It’s not a practical confusion. It’s just an encoder. Jjencode is too characteristic and easy to be detected. It also depends on the browser. The code can’t run on a certain browser. Its disadvantage is that the stack pressure is very serious. If JS is large, encryption may overflow memory, so it is only suitable for core function encryption. In fact, jjencode is still very few commercial, but there is no harm in understanding it.

A normal JS code:

alert("Hello, JavaScript" )

Code after jjencode confusion (custom variable name $):

$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"(\\\"\\"+$.__$+$.__$+$.___+$.$$$_+(![]+"")[$._$_]+(![]+"")[$._$_]+$._$+",\\"+$.$__+$.___+"\\"+$.__$+$.__$+$._$_+$.$_$_+"\\"+$.__$+$.$$_+$.$$_+$.$_$_+"\\"+$.__$+$._$_+$._$$+$.$$__+"\\"+$.__$+$.$$_+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$_+$.___+$.__+"\\\"\\"+$.$__+$.___+")"+"\"")())();

Jjencode is a simple way to solve confusion. Here are some common methods:

  1. Use online tools to decrypt directly, such as:http://www.hiencode.com/jjencode.html
  2. The code of jjencode is usually a self executing method (Iife), removing the last part of the code()After that, put it into the browser and directly execute it, you can see the source code
  3. Online debugging, break points in the first line of jjencode code code, and then execute step by step. Finally, you will see the source code in the virtual machine (VM)

Reverse parameter

The main goal of reverse is the page turning interface_signatureParameter, the encryption method called is stillwindow.get_sign(), it is the same as the first question. This article will not repeat it. If you are not clear, you can see brother K’s article in the last issue.

02.png

Follow up 2 JS, you will find that it is a jjencode confusion:

03.png

Let’s get rid of the last part of the confusion()Put it on the browser console and run it (it is recommended to open a traceless window, which may sometimes have an impact). You can see the source code. Click the source code to the virtual machine (VM), and the whole source code will be displayed in front of us:

04.png

05.png

Except directly remove()In addition to running, we can also set breakpoints in the first line of confused code, then follow up step by step, and finally get the source code, as shown in the figure below:

06.png

07.png

It’s easy to look at the source code. It’s a magic modified SHA1 anonymous function. You can copy its code and rewrite it, which can be carried with Python code_ Signature calculates the data of each page one by one, and finally submits it successfully:

08.png

Complete code

GitHub pays attention to brother K crawler and continues to share crawler related codes! Welcome, star!https://github.com/kgepachong/

The following only demonstrates some key codes, which cannot be run directly!Full code warehouse address:https://github.com/kgepachong/crawler/

JavaScript encryption code

/* ==================================
# @Time    : 2021-12-10
#@author: wechat official account: brother K crawler
# @FileName: challenge_2.js
# @Software: PyCharm
# ================================== */


var hexcase = 0;
var chrsz = 8;

function hex_sha1(s) {
    return binb2hex(core_sha1(AlignSHA1(s)));
}

function sha1_vm_test() {
    return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}

function core_sha1(blockArray) {
    var x = blockArray;
    var w = Array(80);
    var a = 1732584173;
    var b = -271733877;
    var c = -1752584194;
    var d = 271733878;
    var e = -1009589776;
    for (var i = 0; i < x.length; i += 16) {
        var olda = a;
        var oldb = b;
        var oldc = c;
        var oldd = d;
        var olde = e;
        for (var j = 0; j < 80; j++) {
            if (j < 16)
                w[j] = x[i + j];
            else
                w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
            var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));
            e = d;
            d = c;
            c = rol(b, 30);
            b = a;
            a = t;
        }
        a = safe_add(a, olda);
        b = safe_add(b, oldb);
        c = safe_add(c, oldc);
        d = safe_add(d, oldd);
        e = safe_add(e, olde);
    }
    return new Array(a, b, c, d, e);
}

function sha1_ft(t, b, c, d) {
    if (t < 20) {
        return (b & c) | ((~b) & d);
    }
    if (t < 40) {
        return b ^ c ^ d;
    }
    if (t < 60) {
        return (b & c) | (b & d) | (c & d);
    }
    return b ^ c ^ d;
}

function sha1_kt(t) {
    return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
}

function safe_add(x, y) {
    var lsw = (x & 0xFFFF) + (y & 0xFFFF);
    var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
    return (msw << 16) | (lsw & 0xFFFF);
}

function rol(num, cnt) {
    return (num << cnt) | (num >>> (32 - cnt));
}

function AlignSHA1(str) {
    var nblk = ((str.length + 8) >> 6) + 1;
    var blks = new Array(nblk * 16);
    for (var i = 0; i < nblk * 16; i++) {
        blks[i] = 0;
    }
    for (i = 0; i < str.length; i++) {
        blks[i >> 2] |= str.charCodeAt(i) << (24 - (i & 3) * 8);
    }
    blks[i >> 2] |= 0x80 << (24 - (i & 3) * 8);
    blks[nblk * 16 - 1] = str.length * 8;
    return blks;
}

function binb2hex(binarray) {
    var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
    var str = "";
    for (var i = 0; i < binarray.length * 4; i++) {
        str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF);
    }
    return str;
}

function getSign() {
    return hex_sha1(Date.parse(new Date).toString());
}

//Test output
// console.log(getSign())

Python computing key code

# ==================================
# --*-- coding: utf-8 --*--
# @Time    : 2021-12-10
#@author: wechat official account: brother K crawler
# @FileName: challenge_2.py
# @Software: PyCharm
# ==================================


import execjs
import requests


challenge_api = "http://spider.wangluozhe.com/challenge/api/2"
headers = {
    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    "Cookie": "change the cookie value to your own!",
    "Host": "spider.wangluozhe.com",
    "Origin": "http://spider.wangluozhe.com",
    "Referer": "http://spider.wangluozhe.com/challenge/2",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36",
    "X-Requested-With": "XMLHttpRequest"
}


def get_signature():
    with open('challenge_2.js', 'r', encoding='utf-8') as f:
        ppdai_js = execjs.compile(f.read())
    signature = ppdai_js.call("getSign")
    print("signature: ", signature)
    return signature


def main():
    result = 0
    for page in range(1, 101):
        data = {
            "page": page,
            "count": 10,
            "_signature": get_signature()
        }
        response = requests.post(url=challenge_api, headers=headers, data=data).json()
        for d in response["data"]:
            result += d["value"]
    Print ("the result is:", result)


if __name__ == '__main__':
    main()