百度贴吧:如何找出BSK参数

2020/12/05 日更新,我做了一个在线的解析bsk或者转bsk成明文的工具:http://www.baidubsk.site
仅供个人学习使用。

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 None instead 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写一个百度贴吧客户端

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容