What is _BSK?

Anyone who is familiar with using python to make posts in Baidu Tieba should know about the data form below.

If you have any questions about how to get those parameters other than _BSK, please visit my previous posts.

用python写一个百度贴吧客户端

如何用Javascript在百度贴吧上发帖

PostData.jpg

why is _BSK so important?

Surprisingly, Baidu recently added one more security check for making a post. Any Post without _BSK parameter will be regarded as a SPAM, and even worse, system will automatically ban your account at once and it is very hard to get it back.

This _BSK was added around July 2017 and because of that, my own custom Python Tieba program couldn't make any posts or comments. It causes two of my tieba accounts banned forever, even though I didn't use it as a spammer.

Anyway, can we crack this annoying _BSK out?

How to solve_BSK value ?

I will provide my solution first and then explain a little bit about it.

In your browser, press F12 and paste the following javascript.

The code can be found in 如何用Javascript在百度贴吧上发帖

Here is what the result should look like.

Console Result.jpg

Every time you execute this piece of code, you will get a different result of _bsk. However, all of them are valid . If you want to make a test, just set breakpoints before making Post and manually change _BSK value in the data form to the value from my function. It works fine in my computer, so I expect you will get the same result.

where to find this Javascript?

The whole idea is to make breakpoints and steps through all the function calls when you click submit button.

Before submitting your comments, type _BSK in console, it should say that _BSK is not defined. That's because the javascript which defines _BSK object hasn't been downloaded yet. Check your Network tab, you will find out there is one more step before add, which load two js files to your browser under  fex.bdstatic.com/bsk![bsk_js]

bsk_js.jpg

bsk_source.jpg

All the secrete is hidden inside this file.

After loading it, type _BSK again in your console, you can see what the _BSK object looks like.

bsk_console.jpg

It includes three functions a,b,l.

I am not sure what the function c and l are about, but it is function a that does calculation after my findings. You will see it shortly.

After setting breakpoints, l find out program stops here to prepare _BSK value.

_.Module.define({
    path: "common/widget/BskService",
    requires: [],
    sub: {
        initial: function() {
            this.loader = window._BSK ? {
                done: function(n) {   // we already have BSK object
                    n()
                },
                fail: function() {}
            } : $.ajax({  // first time, no BSK available, we need to download the js that defines bsk
                url: "https://fex.bdstatic.com/bsk/??dknsaZmLdyKfEeIVbKxn_dcc70f7.js,omzVouOACqkNljzDbdOB_af501e9.js",
                cache: !0,
                dataType: "script"
            })
        },
        slientEncrypt: function(n, e) {
            return this.encrypt(n, e)["catch"](function() {
                return e
            })
        },
        encrypt: function(n, e) {  // this part tells us how to use _BSK function to get what we want
            var t = this;
            return new Promise(function(i, o) {
                t.loader.done(function() {
                    window._BSK || o(new Error("BSK load failed"));
                    var t = {}; // t is an empty object that will carry _BSK value after encryption later
                  
                  // _BSK.a function is used to encrypt and t.data is the final value
                  
                    window._BSK.a("omzVouOACqkNljzDbdOB", {  //"omzVouOACqkNljzDbdOB" is a constant string
                        IN: n,  // our input parameter,   i.e n ={tbs: "ea8e71a7b73bbc181503433430"}   
                        OUT: t // our output  t={}
                    }),
                    $.extend(e, {
                        _BSK: t.data  // t.data is _BSK value we want .
                    }),
                    i(e)
                }).fail(function() {
                    o(new Error("BSK load failed"))
                })
            }
            )
        }
    }
});

I made some comments above to make it easier to understand.

As you can see, this piece of code demonstrate which _BSK function we need to use and which parameter we are gonna pass. When debugging, you will find out input is actually tbs value and __BSK.a encrypt it . After submitting your Post request, on the server side, baidu decrypt this _BSK value and compare it with tbs, if they agree then the whole process will succeed.

Now, let's see how _BSK object is constructed.

It is shown in the js code below. I called it a black box because I don't know how it works.

(function() {  // create a closure to make all the functions and variables private
    (function(global) {  // pass window object as local variable to make it faster
        function f(b, a) {
            for (var c = 0; c < a.length; c++)
                b.push(a[c]);
            return b
        }
        function g(b, a) {
            for (var c = 0; c < b.length; c++)
                a(b[c], c)
        }
        function l(b, a, c) {
            void 0 === c && (c = null);
            for (var d = [], e = 0; e < b.length; e++)
                d.push(a.apply(c, [b[e], e]));
            return d
        }
        function m(b) {
            return "[object Array]" === Object.prototype.toString.call(b)
        }
        var n = function() {
            function b() {}
            b.B = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/<$+-%>{:* \\,}[^=_~&](")';
            return b
        }()
          , r = function() {
            function b(a) {
                this.m = [];
                this.w = 0;
                this.D = [];
                var c = this;
                this.g = a;
                this.g.i._A = function(a) {
                    c.w = a
                }
                ;
                this.m.push(this.g)
            }
            b.prototype.va = function() {
                return function c(d, e) {
                    return e ? c(d ^ e, (d & e) << 1) : d
                }(8, 2)
            }
            ;
            b.prototype.K = function(a, c) {
                void 0 === c && (c = -1);
                this.m.push(a);
                this.g = this.m[this.m.length - 1];
                -1 !== c && (this.w = c);
                this.D.push(this.w)
            }
            ;
            b.prototype.oa = function(a) {
                var c = this;
                g(a[1], function(a) {
                    return c.b(a)
                })
            }
            ;
            b.prototype.pa = function(a) {
                a[2] ? this.b(a[2]) : this.f(void 0);
                this.g.i[l(function d(a) {
                    return m(a) ? [].concat.apply([], l(a, d)) : a
                }(a[1]), this.o, this).join("")] = this.h()
            }
            ;
            b.prototype.W = function(a) {
                this.b(a[1]);
                this.h() ? this.b(a[2]) : this.b(a[3])
            }
            ;
            b.prototype.aa = function(a) {
                var c = this;
                this.g.i[l(function e(a) {
                    return m(a) ? [].concat.apply([], l(a, e)) : a
                }(a[1]), this.o, this).join("")] = new p(this,this.g,l(a[2], function(a) {
                    return c.C(a[1])
                }),a[3],a[4])
            }
            ;
            b.prototype.ea = function(a) {
                -2 === a[1] ? this.f(new RegExp(this.C(a[2]),this.C(a[3]))) : -1 === a[1] ? this.f(a[2]) : this.f(a[1])
            }
            ;
            b.prototype.ca = function(a, c) {
                var d = this.g.G(l(function k(a) {
                    return m(a) ? [].concat.apply([], l(a, k)) : a
                }(a[1]), this.o, this).join(""));
                if (void 0 !== d)
                    c ? this.f(d) : this.f(d.j[d.s]);
                else
                    throw Error();
            }
            ;
            b.prototype.T = function(a) {
                var c = this;
                this.b(a[1]);
                this.b(a[2]);
                var d = this.h()
                  , e = this.h();
                [function() {
                    c.f(d + e)
                }
                , function() {
                    c.f(d - e)
                }
                , function() {
                    c.f(d / e)
                }
                , function() {
                    c.f(d < e)
                }
                , function() {
                    c.f(d > e)
                }
                , function() {
                    c.f(d <= e)
                }
                , function() {
                    c.f(d >= e)
                }
                , function() {
                    c.f(d == e)
                }
                , function() {
                    c.f(d % e)
                }
                , function() {
                    c.f(d ^ e)
                }
                , function() {
                    c.f(d * e)
                }
                , function() {
                    c.f(d === e)
                }
                , function() {
                    c.f(d !== e)
                }
                , function() {
                    c.f(d << e)
                }
                , function() {
                    c.f(d | e)
                }
                , function() {
                    c.f(d >> e)
                }
                , function() {
                    c.f(d & e)
                }
                ][a[3]]()
            }
            ;
            b.prototype.f = function(a) {
                this.g.xa(a)
            }
            ;
            b.prototype.P = function(a) {
                var c = this;
                try {
                    g(a, function(a) {
                        return c.b(a)
                    }),
                    this.status = 0
                } catch (d) {
                    this.status = 1
                } finally {
                    this.g = null,
                    this.m = []
                }
            }
            ;
            b.prototype.ba = function(a) {
                var c = this;
                this.f(new p(this,this.g,l(a[1], function(a) {
                    return c.C(a[1])
                }),a[2],a[3]))
            }
            ;
            b.prototype.J = function(a) {
                var c = this;
                g(a[2], function(a) {
                    return c.b(a)
                });
                this.b(a[1], !0);
                var d = this.h()
                  , e = d.j
                  , d = d.j[d.s]
                  , b = [];
                for (a = a[2].length; a--; )
                    b.unshift(this.h());
                if (d.apply)
                    e = d.apply(e, b),
                    this.f(e);
                else
                    throw Error();
            }
            ;
            b.prototype.C = function(a) {
                return l(function d(a) {
                    return m(a) ? [].concat.apply([], l(a, d)) : a
                }(a), this.o, this).join("")
            }
            ;
            b.prototype.S = function(a) {
                this.b(a[2]);
                this.b(a[3], !0);
                this.b(a[3]);
                var c = this.h()
                  , d = this.h()
                  , b = this.h();
                [function() {}
                , function() {
                    b = c + b
                }
                , function() {
                    b = c - b
                }
                ][a[1]]();
                d.j ? d.j[d.s] = b : this.g.i[d] = b
            }
            ;
            b.prototype.o = function(a) {
                a ^= this.w;
                return n.B[0 <= a && 26 >= a || 64 < a ? a : 32 <= a && 58 >= a ? 26 + a - 32 : -17 <= a && -8 >= a ? 52 + a + 17 : 0]
            }
            ;
            b.prototype.M = function() {
                this.m.pop();
                this.D.pop();
                this.g = this.m[this.m.length - 1];
                this.w = this.D[this.D.length - 1]
            }
            ;
            b.prototype.h = function() {
                return this.g.O()
            }
            ;
            b.prototype.fa = function(a) {
                this.b(a[2]);
                var c = this.h()
                  , d = this;
                [function() {
                    c ? d.f(c) : d.b(a[3])
                }
                , function() {
                    d.b(a[3]);
                    d.f(c && d.h())
                }
                ][a[1]]()
            }
            ;
            b.prototype.qa = function() {
                return [this.oa, this.pa, this.aa, this.ea, this.ca, this.T, this.ba]
            }
            ;
            b.prototype.R = function(a) {
                var c = this;
                g(a[1], function(a) {
                    return c.b(a)
                });
                var d = [];
                for (a = a[1].length; a--; )
                    d.unshift(this.h());
                this.f(d)
            }
            ;
            b.prototype.ha = function(a) {
                var c = this
                  , d = {};
                g(a[1], function(a) {
                    c.b(a[1]);
                    d[l(function h(a) {
                        return m(a) ? [].concat.apply([], l(a, h)) : a
                    }(a[0]), c.o, c).join("")] = c.h()
                });
                this.f(d)
            }
            ;
            b.prototype.ja = function() {
                this.f(this.g.i["this"] || this.g.i)
            }
            ;
            b.prototype.ga = function(a, c) {
                var d;
                if (1 === a[1])
                    if (d = this.g.G(l(function h(a) {
                        return m(a) ? [].concat.apply([], l(a, h)) : a
                    }(a[4][1]), this.o, this).join("")))
                        d = d.j[d.s];
                    else
                        throw Error();
                else
                    this.b(a[4], !1),
                    d = this.h();
                if (void 0 !== d) {
                    0 === a[3] && 1 === a[2] ? this.f(l(function h(a) {
                        return m(a) ? [].concat.apply([], l(a, h)) : a
                    }(a[5][1]), this.o, this).join("")) : this.b(a[5]);
                    var b = this.h();
                    c ? this.f(this.g.ta(d, b)) : this.f(d[b])
                } else
                    throw Error();
            }
            ;
            b.prototype.na = function(a) {
                this.b(a[1], !0);
                var c = this.h()
                  , d = c.j[c.s];
                [function() {
                    d++
                }
                , function() {
                    d--
                }
                ][a[2]]();
                c.j[c.s] = d
            }
            ;
            b.prototype.sa = function() {
                return [this.$, this.da, this.V, this.X, this.ka, this.la, this.Y]
            }
            ;
            b.prototype.b = function(a, c) {
                void 0 === c && (c = !1);
                if (!this.g.L && !this.g.u && !this.g.v) {
                    var d = f(this.qa(), f(this.ra(), f(this.sa(), [this.ia, this.fa, this.ma, this.W, this.U, this.Z])))
                      , b = a[0] - 3 * this.va() ^ this.w;
                    if (d[b])
                        d[b].apply(this, [a, c]);
                    else
                        throw Error();
                }
            }
            ;
            b.prototype.Z = function(a) {
                var c = this;
                this.b(a[1], !0);
                var d = this.h();
                this.b(a[2]);
                for (var b in this.h()) {
                    d.j[d.s] = b;
                    g(a[3], function(a) {
                        return c.b(a)
                    });
                    if (this.g.u) {
                        this.g.u = !1;
                        break
                    }
                    this.g.v && (this.g.v = !1)
                }
            }
            ;
            b.prototype.$ = function(a) {
                var c = this;
                this.b(a[1]);
                do {
                    g(a[2], function(a) {
                        return c.b(a)
                    });
                    if (this.g.u) {
                        this.g.u = !1;
                        break
                    }
                    this.g.v && (this.g.v = !1);
                    this.b(a[3]);
                    this.b(a[4]);
                    if (!this.h())
                        break
                } while (1)
            }
            ;
            b.prototype.U = function(a) {
                var c = this;
                g(a[1], function(a) {
                    return c.b(a)
                })
            }
            ;
            b.prototype.da = function(a) {
                this.b(a[1]);
                this.h() ? a[2] && this.b(a[2]) : a[3] && this.b(a[3])
            }
            ;
            b.prototype.V = function() {
                this.g.u = !0
            }
            ;
            b.prototype.X = function() {
                this.g.v = !0
            }
            ;
            b.prototype.ma = function(a) {
                var c = this;
                this.b(a[2], !1);
                var d = this.h();
                [function() {
                    c.f(!d)
                }
                , function() {
                    c.f(-d)
                }
                ][a[1]]()
            }
            ;
            b.prototype.ra = function() {
                return [this.J, this.J, this.S, this.R, this.ha, this.ja, this.ga, this.na]
            }
            ;
            b.prototype.ka = function(a) {
                this.b(a[1]);
                throw this.h();
            }
            ;
            b.prototype.la = function(a) {
                var c = this;
                try {
                    g(a[1], function(a) {
                        return c.b(a)
                    })
                } catch (e) {
                    var d = new q;
                    d.A = this.g;
                    this.K(d);
                    a[2] && (this.g.i[l(function h(a) {
                        return m(a) ? [].concat.apply([], l(a, h)) : a
                    }(a[2][1]), this.o, this).join("")] = e);
                    g(a[3], function(a) {
                        return c.b(a)
                    });
                    this.M()
                } finally {
                    a[4] && g(a[4], function(a) {
                        return c.b(a)
                    })
                }
            }
            ;
            b.prototype.Y = function(a) {
                this.b(a[1])
            }
            ;
            b.prototype.ia = function(a) {
                a[1] && this.b(a[1]);
                this.g.L = !0
            }
            ;
            return b
        }()
          , q = function() {
            function b(a) {
                this.F = function() {
                    return function(a, d) {
                        this.j = a;
                        this.s = d
                    }
                }();
                this.v = this.u = this.L = !1;
                this.H = [];
                this.i = a || {
                    btoa: function(a, d, b, k, h) {
                        void 0 === d && (d = n.B.slice(0, 64));
                        for (k = h = ""; a[k | 0] || (d = "=",
                        k % 1); h += d[63 & b >> 8 - k % 1 * 8])
                            b = b << 8 | a.charCodeAt(k -= -.75);
                        return h
                    }
                }
            }
            b.prototype.O = function() {
                return this.H.pop()
            }
            ;
            b.prototype.xa = function(a) {
                this.H.push(a)
            }
            ;
            b.prototype.ta = function(a, c) {
                return new this.F(a,c)
            }
            ;
            b.prototype.G = function(a) {
                if (this.i.hasOwnProperty(a))
                    return new this.F(this.i,a);
                if (this.A)
                    return this.A.G(a);
                if (global[a])
                    return new this.F(global,a)
            }
            ;
            return b
        }()
          , p = function() {
            function b(a, c, d, b, k) {
                this.I = a;
                this.ua = b;
                this.A = c;
                this.N = d;
                this.wa = k
            }
            b.prototype.apply = function(a, c) {
                var b = this
                  , e = new q;
                e.A = this.A;
                this.N && g(this.N, function(a, b) {
                    e.i[a] = c[b]
                });
                e.i["this"] = a;
                this.I.K(e, this.wa);
                try {
                    g(this.ua, function(a) {
                        return b.I.b(a, !1)
                    })
                } finally {
                    this.I.M()
                }
                if (0 !== e.H.length)
                    return e.O()
            }
            ;
            return b
        }()
          , t = {};
        global._BSK = {  // how _BSKis defined
            a: function(b, a) {
                a.MAP = n.B;
                (new r(new q(a))).P(t[b])  // t[b] is that giant array you saw in my solution which copied from the first step.![](D:\Python27\Learning\browser_tieba\bsk\Solver_JS\bsk_skeleton.jpg)
            },
            c: function(b, a) {
                b.MAP = n.B;
                (new r(new q(b))).P(a)
            },
            l: function(b, a) {
                t[b] = a
            }
        };
    })(window)
}
)

bsk_skeleton.jpg

To get more sense on its structure, please see the snippet above.

Note :

n.B ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/<$+-%>{:* \\,}[^=_~&](")';

which provides the mapping.

Function r,q,P are three big function object with many prototype functions. It is very difficult to guess the meaning of those random variable names or the use of each functions. I gave up trying to replicate them in Python and choose to run this bulk of javascript in browser with inputs (tbs).

Running is much easier than replicating, I create a wrapper function called solver_bsk(tbs) which will call the black box above and returns _bsk, which showed in my solution at the beginning.

though, I still don't quite understand what kind of algorithm behind it, at least we can get what we want so far.

Now, how to run this javascript in Python?

To be honest, i still couldn't figure out how to run it in python instead of browser's console. Though there are lots of library in python like selenium and js2py that could help translation, but every time I try it, python throws me Noneinstead of a string. I guess the real problem is that those library can't handle such a big block of nested functions. I probably need to break it piece by piece and then translate each individual functions in a language of python rather than throw it as a whole.

Anyway, as soon as we know how to compute _BSK , bridge this js code into Python would be much easier.

If you have any suggestions about how to run this js in Python, please comment below.

Much appreciated,

By Brad Xing

--- 8/25/2017 Updated:

I found a work around to use Selenium webdriver to run local HTML with BSK js function and then scrape the BSK value from the browser. More details, please visit my thread

用python写一个百度贴吧客户端

作者:bigtrace
链接:https://www.jianshu.com/p/c04b1e9b929c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。