Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save KairuiLiu/ccbec3a4660e37acb6d79ef3a3467466 to your computer and use it in GitHub Desktop.

Select an option

Save KairuiLiu/ccbec3a4660e37acb6d79ef3a3467466 to your computer and use it in GitHub Desktop.
北京人才引进落户进度查询
// ==UserScript==
// @name 北京人才引进落户进度查询
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 北京人才引进落户进度查询
// @author WhoCare?
// @match https://fw.bjrcgz.gov.cn/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const TARGET_URL =
'https://fw.bjrcgz.gov.cn/person/platform-person/personOverviewInfo/getProcessingBusinessInfo';
function decryptProcessingBusinessInfo(Pt) {
const p = [
214, 144, 233, 254, 204, 225, 61, 183, 22, 182, 20, 194, 40, 251, 44, 5,
43, 103, 154, 118, 42, 190, 4, 195, 170, 68, 19, 38, 73, 134, 6, 153,
156, 66, 80, 244, 145, 239, 152, 122, 51, 84, 11, 67, 237, 207, 172, 98,
228, 179, 28, 169, 201, 8, 232, 149, 128, 223, 148, 250, 117, 143, 63,
166, 71, 7, 167, 252, 243, 115, 23, 186, 131, 89, 60, 25, 230, 133, 79,
168, 104, 107, 129, 178, 113, 100, 218, 139, 248, 235, 15, 75, 112, 86,
157, 53, 30, 36, 14, 94, 99, 88, 209, 162, 37, 34, 124, 59, 1, 33, 120,
135, 212, 0, 70, 87, 159, 211, 39, 82, 76, 54, 2, 231, 160, 196, 200,
158, 234, 191, 138, 210, 64, 199, 56, 181, 163, 247, 242, 206, 249, 97,
21, 161, 224, 174, 93, 164, 155, 52, 26, 85, 173, 147, 50, 48, 245, 140,
177, 227, 29, 246, 226, 46, 130, 102, 202, 96, 192, 41, 35, 171, 13, 83,
78, 111, 213, 219, 55, 69, 222, 253, 142, 47, 3, 255, 106, 114, 109,
108, 91, 81, 141, 27, 175, 146, 187, 221, 188, 127, 17, 217, 92, 65, 31,
16, 90, 216, 10, 193, 49, 136, 165, 205, 123, 189, 45, 116, 208, 18,
184, 229, 180, 176, 137, 105, 151, 74, 12, 150, 119, 126, 101, 185, 241,
9, 197, 110, 198, 132, 24, 240, 125, 236, 58, 220, 77, 32, 121, 238, 95,
62, 215, 203, 57, 72,
],
D = [
462357, 472066609, 943670861, 1415275113, 1886879365, 2358483617,
2830087869, 3301692121, 3773296373, 4228057617, 404694573, 876298825,
1347903077, 1819507329, 2291111581, 2762715833, 3234320085, 3705924337,
4177462797, 337322537, 808926789, 1280531041, 1752135293, 2223739545,
2695343797, 3166948049, 3638552301, 4110090761, 269950501, 741554753,
1213159005, 1684763257,
];
function I(ce) {
const me = [];
for (let le = 0, Se = ce.length; le < Se; le += 2)
me.push(parseInt(ce.substr(le, 2), 16));
return me;
}
function S(ce, me) {
const le = 31 & me;
return (ce << le) | (ce >>> (32 - le));
}
function F(ce) {
return (
((255 & p[(ce >>> 24) & 255]) << 24) |
((255 & p[(ce >>> 16) & 255]) << 16) |
((255 & p[(ce >>> 8) & 255]) << 8) |
(255 & p[255 & ce])
);
}
function T(ce) {
return ce ^ S(ce, 2) ^ S(ce, 10) ^ S(ce, 18) ^ S(ce, 24);
}
function z(ce) {
return ce ^ S(ce, 13) ^ S(ce, 23);
}
function N(ce, me, le) {
const Se = new Array(4),
Oe = new Array(4);
for (let we = 0; we < 4; we++)
(Oe[0] = 255 & ce[4 * we]),
(Oe[1] = 255 & ce[4 * we + 1]),
(Oe[2] = 255 & ce[4 * we + 2]),
(Oe[3] = 255 & ce[4 * we + 3]),
(Se[we] = (Oe[0] << 24) | (Oe[1] << 16) | (Oe[2] << 8) | Oe[3]);
for (let Ae, we = 0; we < 32; we += 4)
(Ae = Se[1] ^ Se[2] ^ Se[3] ^ le[we + 0]),
(Se[0] ^= T(F(Ae))),
(Ae = Se[2] ^ Se[3] ^ Se[0] ^ le[we + 1]),
(Se[1] ^= T(F(Ae))),
(Ae = Se[3] ^ Se[0] ^ Se[1] ^ le[we + 2]),
(Se[2] ^= T(F(Ae))),
(Ae = Se[0] ^ Se[1] ^ Se[2] ^ le[we + 3]),
(Se[3] ^= T(F(Ae)));
for (let we = 0; we < 16; we += 4)
(me[we] = (Se[3 - we / 4] >>> 24) & 255),
(me[we + 1] = (Se[3 - we / 4] >>> 16) & 255),
(me[we + 2] = (Se[3 - we / 4] >>> 8) & 255),
(me[we + 3] = 255 & Se[3 - we / 4]);
}
function Te(
ce,
me,
le,
{
padding: Se = 'pkcs#7',
mode: Oe,
iv: we = [],
output: Ae = 'string',
} = {}
) {
if (
'cbc' === Oe &&
('string' == typeof we && (we = I(we)), 16 !== we.length)
)
throw new Error('iv is invalid');
if (('string' == typeof me && (me = I(me)), 16 !== me.length))
throw new Error('key is invalid');
if (
((ce =
'string' == typeof ce
? 0 !== le
? (function R(ce) {
const me = [];
for (let le = 0, Se = ce.length; le < Se; le++) {
const Oe = ce.codePointAt(le);
if (Oe <= 127) me.push(Oe);
else if (Oe <= 2047)
me.push(192 | (Oe >>> 6)), me.push(128 | (63 & Oe));
else if (Oe <= 55295 || (Oe >= 57344 && Oe <= 65535))
me.push(224 | (Oe >>> 12)),
me.push(128 | ((Oe >>> 6) & 63)),
me.push(128 | (63 & Oe));
else {
if (!(Oe >= 65536 && Oe <= 1114111))
throw (
(me.push(Oe), new Error('input is not supported'))
);
le++,
me.push(240 | ((Oe >>> 18) & 28)),
me.push(128 | ((Oe >>> 12) & 63)),
me.push(128 | ((Oe >>> 6) & 63)),
me.push(128 | (63 & Oe));
}
}
return me;
})(ce)
: I(ce)
: [...ce]),
('pkcs#5' === Se || 'pkcs#7' === Se) && 0 !== le)
) {
const Ye = 16 - (ce.length % 16);
for (let Ce = 0; Ce < Ye; Ce++) ce.push(Ye);
}
const ve = new Array(32);
!(function ie(ce, me, le) {
const Se = new Array(4),
Oe = new Array(4);
for (let we = 0; we < 4; we++)
(Oe[0] = 255 & ce[0 + 4 * we]),
(Oe[1] = 255 & ce[1 + 4 * we]),
(Oe[2] = 255 & ce[2 + 4 * we]),
(Oe[3] = 255 & ce[3 + 4 * we]),
(Se[we] = (Oe[0] << 24) | (Oe[1] << 16) | (Oe[2] << 8) | Oe[3]);
(Se[0] ^= 2746333894),
(Se[1] ^= 1453994832),
(Se[2] ^= 1736282519),
(Se[3] ^= 2993693404);
for (let Ae, we = 0; we < 32; we += 4)
(Ae = Se[1] ^ Se[2] ^ Se[3] ^ D[we + 0]),
(me[we + 0] = Se[0] ^= z(F(Ae))),
(Ae = Se[2] ^ Se[3] ^ Se[0] ^ D[we + 1]),
(me[we + 1] = Se[1] ^= z(F(Ae))),
(Ae = Se[3] ^ Se[0] ^ Se[1] ^ D[we + 2]),
(me[we + 2] = Se[2] ^= z(F(Ae))),
(Ae = Se[0] ^ Se[1] ^ Se[2] ^ D[we + 3]),
(me[we + 3] = Se[3] ^= z(F(Ae)));
if (0 === le)
for (let Ae, we = 0; we < 16; we++)
(Ae = me[we]), (me[we] = me[31 - we]), (me[31 - we] = Ae);
})(me, ve, le);
const Ne = [];
let Ke = we,
et = ce.length,
Ge = 0;
for (; et >= 16; ) {
const Ye = ce.slice(Ge, Ge + 16),
Ce = new Array(16);
if ('cbc' === Oe)
for (let ue = 0; ue < 16; ue++) 0 !== le && (Ye[ue] ^= Ke[ue]);
N(Ye, Ce, ve);
for (let ue = 0; ue < 16; ue++)
'cbc' === Oe && 0 === le && (Ce[ue] ^= Ke[ue]),
(Ne[Ge + ue] = Ce[ue]);
'cbc' === Oe && (Ke = 0 !== le ? Ce : Ye), (et -= 16), (Ge += 16);
}
if (('pkcs#5' === Se || 'pkcs#7' === Se) && 0 === le) {
const Ye = Ne.length,
Ce = Ne[Ye - 1];
for (let ue = 1; ue <= Ce; ue++)
if (Ne[Ye - ue] !== Ce) throw new Error('padding is invalid');
Ne.splice(Ye - Ce, Ce);
}
return 'array' !== Ae
? 0 !== le
? (function Q(ce) {
return ce
.map((me) =>
1 === (me = me.toString(16)).length ? '0' + me : me
)
.join('');
})(Ne)
: (function Y(ce) {
const me = [];
for (let le = 0, Se = ce.length; le < Se; le++)
ce[le] >= 240 && ce[le] <= 247
? (me.push(
String.fromCodePoint(
((7 & ce[le]) << 18) +
((63 & ce[le + 1]) << 12) +
((63 & ce[le + 2]) << 6) +
(63 & ce[le + 3])
)
),
(le += 3))
: ce[le] >= 224 && ce[le] <= 239
? (me.push(
String.fromCodePoint(
((15 & ce[le]) << 12) +
((63 & ce[le + 1]) << 6) +
(63 & ce[le + 2])
)
),
(le += 2))
: ce[le] >= 192 && ce[le] <= 223
? (me.push(
String.fromCodePoint(
((31 & ce[le]) << 6) + (63 & ce[le + 1])
)
),
le++)
: me.push(String.fromCodePoint(ce[le]));
return me.join('');
})(Ne)
: Ne;
}
const decrypt = (ce, me, le) => Te(ce, me, 0, le);
return (function Ae(ae) {
const De = (function we(ae) {
if ('' === ae.trim()) return Array.from(new Uint16Array(0));
let Ve = new Uint16Array(ae.length);
for (let De = 0; De < ae.length; De++) Ve[De] = ae.charCodeAt(De);
return Array.from(Ve);
})('KW%_q&j[)1{xHM:R'),
fe = decrypt(ae, De);
return JSON.parse(fe);
})(Pt);
}
// 保存原始的 fetch 函数
const originalFetch = window.fetch;
// 重写 fetch 函数
window.fetch = function (...args) {
const [resource, config] = args;
// 检查是否是目标URL
if (resource && resource.toString().includes(TARGET_URL)) {
// 执行原始请求
return originalFetch
.apply(this, args)
.then((response) => {
// 克隆响应以便我们可以读取它
const responseClone = response.clone();
// 读取响应JSON
responseClone
.json()
.then((data) => {
// 检查status
if (data.status === 200) {
// 执行解密函数
try {
const decryptedResult = decryptProcessingBusinessInfo(
data.result
);
console.log(
'🔓 解密结果:',
JSON.stringify(decryptedResult, null, 2)
);
} catch (error) {
console.error('❌ 解密过程中发生错误:', error);
}
} else {
console.log('❌ 响应错误,状态码:', data.status);
console.log('错误信息:', data.msg || '未知错误');
}
})
.catch((error) => {
console.error('❌ 解析响应JSON时发生错误:', error);
});
// 返回原始响应,不影响正常的页面功能
return response;
})
.catch((error) => {
console.error('❌ 网络请求失败:', error);
throw error;
});
}
// 对于其他请求,直接调用原始fetch
return originalFetch.apply(this, args);
};
// 也监听 XMLHttpRequest,以防页面使用的是 XHR
const originalXhrOpen = XMLHttpRequest.prototype.open;
const originalXhrSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function (method, url, ...args) {
this._url = url;
return originalXhrOpen.call(this, method, url, ...args);
};
XMLHttpRequest.prototype.send = function (...args) {
if (this._url && this._url.includes(TARGET_URL)) {
// 监听响应
this.addEventListener('load', function () {
try {
const data = JSON.parse(this.responseText);
// 检查status
if (data.status === 200) {
// 执行解密函数
try {
const decryptedResult = decryptProcessingBusinessInfo(
data.result
);
console.log(
'🔓 解密结果:',
JSON.stringify(decryptedResult, null, 2)
);
} catch (error) {
console.error('❌ 解密过程中发生错误:', error);
}
} else {
console.log('❌ 响应错误,状态码:', data.status);
console.log('错误信息:', data.msg || '未知错误');
}
} catch (error) {
console.error('❌ 解析XHR响应JSON时发生错误:', error);
}
});
}
return originalXhrSend.apply(this, args);
};
console.clear();
console.log('🚀 网络请求监听脚本已启动');
})();
@KairuiLiu
Copy link
Author

KairuiLiu commented Sep 11, 2025

安装 油猴 扩展, 点击上方 Raw 按钮, 浏览器会自动跳转到脚本安装页面, 选择安装脚本. 打开人才引进页面, F12 即可看到解密结果

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment