本文教程针对的是2021年7月2日时国税查验平台的js分析,其中版本号为V2.0.06_009。主要分析内容为key9和flwq39以及fplx这3个参数的算法,其中key9分为获取验证码阶段和查验阶段,算法有所区别,flwq39同理。

教程开始:

一、官方网址

国家税务总局全国增值税发票查验平台

二、请求分析

国税查验平台请求共分为2个,第一个请求获取验证码,第二个请求为输入验证码后查验数据并返回发票详细信息。

第一步:安装证书

基础:谷歌浏览器

首先需要安装证书,建议选择自动安装,在某些教程中可能选择手动安装,以便于使用ast工具挂代理找内存数据,但是这里我们采用一种新的方法来解决js逆向问题,因此那种方便用那种。

第二步:抓包

基础:谷歌浏览器+开发者工具+js基础知识

我们使用开发者工具或按F12打开谷歌浏览器的开发者工具,请注意尽量在网页加载完成后打开开发者工具,界面如下:

官方很给力,直接debug了,至于如何去掉断点,可以参考百度上的其他教程,这里给出一个办法,上图中点击数据1所处位置,使其颜色为蓝色,点击2或者点击上方的debug恢复按钮。此时,我们成功绕过了debug,但是特别注意尽量关闭其他无用软件或者网页,因为在后面的操作中,会感到特别卡顿。

我们在发票代码输入框和发票号码中输入合法的数据,并在开发者工具模块,观察所发送的请求包:

https://fpcy.anhui.chinatax.gov.cn/NWebQuery/yzmQuery?callback=jQuery11020854931324645166_1625223145135&fpdm=034012000211&fphm=12345678&r=0.28901229909781767&v=V2.0.06_009&nowtime=1625223446708&publickey=1625223446708&key9=ec213f1e1aa579511f5d58f09a01a5a2&_=1625223145136&flwq39=LdjaQwXUtzKjxpXQ%2FmD7KCBtBMP7lqfc7uBJNuxAumYpT9mjp90BloLfM4V6KKuD4GWdYCxRLLjJX9a1YrNy7Bs95NmSWQmpc1VAibkeG3HydXc0r9xsRc%2BkIsPWeHrFk3PYAP6k8tAcTJzoIdlhctD8wOUVXOUwczcMJW6WiF0%3D

在这个请求中,分为url的网址前缀部分和尾部参数,其中尾部参数如下:

callback=固定值
fpdm=发票代码
fphm=发票号码
r=随机数
V=版本号
nowtime=当前时间减去1分钟
publickey=当前时间减去1分钟
key9=加密参数
_=可为固定值
flwq39=加密参数

如果你观察过会发现,不同地区的发票,请求的地址不同,如这里是anhui。该请求的前缀部分在一个js文件中,如图:

但是,很不幸,当你打开这个文件时,你会发现混淆了,不过很容易发现是sojson的样子,这并不影响我们逆向,我们使用http://tool.yuanrenxue.com/decode_obfuscator这个网站可以解密这些js代码,尽管解密的代码看着很头疼,但是已经比原始的好太多了。

解密后可以得到各个地区的ip和网址以及对应的地区代码:

0: {code: "1100", sfmc: "北京", Ip: "https://fpcy.beijing.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.beijing.chinatax.gov.cn:443"}
1: {code: "1200", sfmc: "天津", Ip: "https://fpcy.tjsat.gov.cn:443/NWebQuery", address: "https://fpcy.tjsat.gov.cn:443"}
2: {code: "1300", sfmc: "河北", Ip: "https://fpcy.hebei.chinatax.gov.cn/NWebQuery", address: "https://fpcy.hebei.chinatax.gov.cn"}
3: {code: "1400", sfmc: "山西", Ip: "https://fpcy.shanxi.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.shanxi.chinatax.gov.cn:443"}
4: {code: "1500", sfmc: "内蒙古", Ip: "https://fpcy.neimenggu.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.neimenggu.chinatax.gov.cn:443"}
5: {code: "2100", sfmc: "辽宁", Ip: "https://fpcy.liaoning.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.liaoning.chinatax.gov.cn:443"}
6: {code: "2102", sfmc: "大连", Ip: "https://sbf.dalian.chinatax.gov.cn:8402/NWebQuery", address: "https://sbf.dalian.chinatax.gov.cn:8402"}
7: {code: "2200", sfmc: "吉林", Ip: "https://fpcy.jilin.chinatax.gov.cn:4432/NWebQuery", address: "https://fpcy.jilin.chinatax.gov.cn:4432"}
8: {code: "2300", sfmc: "黑龙江", Ip: "https://fpcy.heilongjiang.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.heilongjiang.chinatax.gov.cn:443"}
9: {code: "3100", sfmc: "上海", Ip: "https://fpcy.shanghai.chinatax.gov.cn:1001/NWebQuery", address: "https://fpcy.shanghai.chinatax.gov.cn:1001"}
10: {code: "3200", sfmc: "江苏", Ip: "https://fpcy.jiangsu.chinatax.gov.cn:80/NWebQuery", address: "https://fpcy.jiangsu.chinatax.gov.cn:80"}
11: {code: "3300", sfmc: "浙江", Ip: "https://fpcy.zhejiang.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.zhejiang.chinatax.gov.cn:443"}
12: {code: "3302", sfmc: "宁波", Ip: "https://fpcy.ningbo.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.ningbo.chinatax.gov.cn:443"}
13: {code: "3400", sfmc: "安徽", Ip: "https://fpcy.anhui.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.anhui.chinatax.gov .cn:443"}
14: {code: "3500", sfmc: "福建", Ip: "https://fpcy.fujian.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.fujian.chinatax.gov.cn:443"}
15: {code: "3502", sfmc: "厦门", Ip: "https://fpcy.xiamen.chinatax.gov.cn/NWebQuery", address: "https://fpcy.xiamen.chinatax.gov.cn"}
16: {code: "3600", sfmc: "江西", Ip: "https://fpcy.jiangxi.chinatax.gov.cn:82/NWebQuery", address: "https://fpcy.jiangxi.chinatax.gov.cn:82"}
17: {code: "3700", sfmc: "山东", Ip: "https://fpcy.shandong.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.shandong.chinatax.gov.cn:443"}
18: {code: "3702", sfmc: "青岛", Ip: "https://fpcy.qingdao.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.qingdao.chinatax.gov.cn:443"}
19: {code: "4100", sfmc: "河南", Ip: "https://fpcy.henan.chinatax.gov.cn/NWebQuery", address: "https://fpcy.henan.chinatax.gov.cn"}
20: {code: "4200", sfmc: "湖北", Ip: "https://fpcy.hubei.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.hubei.chinatax.gov.cn:443"}
21: {code: "4300", sfmc: "湖南", Ip: "https://fpcy.hunan.chinatax.gov.cn:8083/NWebQuery", address: "https://fpcy.hunan.chinatax.gov.cn:8083"}
22: {code: "4400", sfmc: "广东", Ip: "https://fpcy.guangdong.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.guangdong.chinatax.gov.cn:443"}
23: {code: "4403", sfmc: "深圳", Ip: "https://fpcy.shenzhen.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.shenzhen.chinatax.gov.cn:443"}
24: {code: "4500", sfmc: "广西", Ip: "https://fpcy.guangxi.chinatax.gov.cn:8200/NWebQuery", address: "https://fpcy.guangxi.chinatax.gov.cn:8200"}
25: {code: "4600", sfmc: "海南", Ip: "https://fpcy.hainan.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.hainan.chinatax.gov.cn:443"}
26: {code: "5000", sfmc: "重庆", Ip: "https://fpcy.chongqing.chinatax.gov.cn:80/NWebQuery", address: "https://fpcy.chongqing.chinatax.gov.cn:80"}
27: {code: "5100", sfmc: "四川", Ip: "https://fpcy.sichuan.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.sichuan.chinatax.gov.cn:443"}
28: {code: "5200", sfmc: "贵州", Ip: "https://fpcy.guizhou.chinatax.gov.cn:80/NWebQuery", address: "https://fpcy.guizhou.chinatax.gov.cn:80"}
29: {code: "5300", sfmc: "云南", Ip: "https://fpcy.yunnan.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.yunnan.chinatax.gov.cn:443"}
30: {code: "5400", sfmc: "西藏", Ip: "https://fpcy.xztax.gov.cn:81/NWebQuery", address: "https://fpcy.xztax.gov.cn:81"}
31: {code: "6100", sfmc: "陕西", Ip: "https://fpcy.shaanxi.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.shaanxi.chinatax.gov.cn:443"}
32: {code: "6200", sfmc: "甘肃", Ip: "https://fpcy.gansu.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.gansu.chinatax.gov.cn:443"}
33: {code: "6300", sfmc: "青海", Ip: "https://fpcy.qinghai.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.qinghai.chinatax.gov.cn:443"}
34: {code: "6400", sfmc: "宁夏", Ip: "https://fpcy.ningxia.chinatax.gov.cn:443/NWebQuery", address: "https://fpcy.ningxia.chinatax.gov.cn:443"}
35: {code: "6500", sfmc: "新疆", Ip: "https://fpcy.xj-n-tax.gov.cn:443/NWebQuery", address: "https://fpcy.xj-n-tax.gov.cn:443"}

回到抓包中,我们观察到这时发送了一个获取验证码的请求:

注意到通过分析这个url,我们发现请求来自如下图,我们注意到getyzmxx这个函数,来自eab23.js这个文件里,我们提取这个文件使用ob解密。

ob解密后的数据如下:

var _0x14658c = function () {var _0x2253f1 = true;return function (_0x41c5d5, _0x508a27) {var _0x47fbda = _0x2253f1 ? function () {if (_0x508a27) {var _0x6b4e27 = _0x508a27["apply"](_0x41c5d5, arguments);_0x508a27 = null;return _0x6b4e27;}} : function () {};_0x2253f1 = false;return _0x47fbda;};
}();var _0x59e564 = _0x14658c(this, function () {var _0x595419 = function () {return "dev";},_0x4c5231 = function () {return "window";};var _0x1842a8 = function () {var _0x21d015 = new RegExp("\\w+ *\\(\\) *{\\w+ *['|\"].+['|\"];? *}");return !_0x21d015["test"](_0x595419["toString"]());};var _0x113bb3 = function () {var _0x326224 = new RegExp("(\\\\[x|u](\\w){2,4})+");return _0x326224["test"](_0x4c5231["toString"]());};var _0x185d70 = function (_0x4ac461) {var _0x557ade = 0;if (_0x4ac461["indexOf"](false)) {_0x3cbd92(_0x4ac461);}};var _0x3cbd92 = function (_0x2bb9d8) {var _0x5f4806 = 3;if (_0x2bb9d8["indexOf"]("true"[3]) !== _0x5f4806) {_0x185d70(_0x2bb9d8);}};if (!_0x1842a8()) {if (!_0x113bb3()) {_0x185d70("ind\u0435xOf");} else {_0x185d70("indexOf");}} else {_0x185d70("ind\u0435xOf");}
});_0x59e564();var yzmWait = 2;
var retrycount = 0;
$(document)["ready"](function () {$("#fpdm")["blur"](function () {retrycount = 0;});
});function yzmTime(_0x5c47fb) {if (yzmWait == 0) {$("#yzm_unuse_img")["hide"]();$("#yzm_img")["show"]();yzmWait = 60;} else {if (yzmWait == 2) {$("#yzm_unuse_img")["show"]();$("#yzm_img")["hide"]();}yzmWait--;setTimeout(function () {yzmTime(_0x5c47fb);}, 1000);}
}function getYzmXx() {$["pricode"]["clearA"]();show_yzm = "1";var _0x31767b = $("#fpdm")["val"]()["trim"]();var _0x4dfb9 = getSwjg(_0x31767b, 0);var _0x3297c1 = _0x4dfb9[1] + "/yzmQuery";var _0x41afd2 = showTime()["toString"]();var _0x1912a2 = $("#fpdm")["val"]()["trim"]();var _0x478041 = $("#fphm")["val"]()["trim"]();var _0x1a5014 = $("#kjje")["val"]()["trim"]();var _0x70138f = Math["random"]();var _0x1d5629 = _0x4dfb9[2];var _0x18c20a = {"fpdm": _0x1912a2,"fphm": _0x478041,"r": _0x70138f,"v": VVV,"nowtime": _0x41afd2,"area": _0x1d5629,"publickey": _0x41afd2,"key9": $["nnyd"]["yzm"](_0x1912a2, _0x478041, _0x41afd2)};$["ajaxSetup"]({"cache": false});yzmFlag = 1;$["ajax"]({"type": "post","url": _0x3297c1,"data": _0x18c20a,"dataType": "jsonp","jsonp": "callback","success": function (_0x135eb2) {if (_0x135eb2["hasOwnProperty"]("data")) {_0x135eb2 = _0x135eb2["data"];_0x135eb2 = replaceStr(_0x135eb2, _0x41afd2);_0x135eb2 = Base64["decode"](_0x135eb2);_0x135eb2 = eval("(" + _0x135eb2 + ")");}delayFlag = "1";var _0x2651d3 = _0x135eb2["key1"];var _0x1a96a9 = _0x135eb2["key2"];var _0x2b0c56 = _0x135eb2["key3"];var _0x1769c2 = _0x135eb2["key4"];var _0x483079 = _0x135eb2["key5"];var _0x2e8ee0 = _0x135eb2["key6"];if (_0x483079 == "2") {oldweb = 2;} else {if (_0x483079 == "1") {oldweb = 1;}}if (_0x2651d3 == "003") {jAlert("\u9A8C\u8BC1\u7801\u8BF7\u6C42\u6B21\u6570\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF71\u5206\u949F\u540E\u518D\u8BD5\uFF01", "\u8B66\u544A");$("#yzm_img")["hide"]();} else {if (_0x2651d3 == "005") {jAlert("\u975E\u6CD5\u8BF7\u6C42!", "\u8B66\u544A");} else {if (_0x2651d3 == "010") {jAlert("\u7F51\u7EDC\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5\uFF01(01)", "\u8B66\u544A");} else {if (_0x2651d3 == "fpdmerr") {jAlert("\u8BF7\u8F93\u5165\u5408\u6CD5\u53D1\u7968\u4EE3\u7801!", "\u8B66\u544A");} else {if (_0x2651d3 == "024") {jAlert("24\u5C0F\u65F6\u5185\u9A8C\u8BC1\u7801\u8BF7\u6C42\u592A\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\uFF01", "\u8B66\u544A");$("#yzm_img")["hide"]();} else {if (_0x2651d3 == "016") {jAlert("\u670D\u52A1\u5668\u63A5\u6536\u7684\u8BF7\u6C42\u592A\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\uFF01", "\u8B66\u544A");$("#yzm_img")["hide"]();} else {if (_0x2651d3 == "020") {jAlert("\u7531\u4E8E\u67E5\u9A8C\u884C\u4E3A\u5F02\u5E38\uFF0C\u6D89\u5ACC\u8FDD\u89C4\uFF0C\u5F53\u524D\u65E0\u6CD5\u4F7F\u7528\u67E5\u9A8C\u670D\u52A1\uFF01", "\u63D0\u793A");} else {if (_0x2651d3 == "errv") {jAlert("\u5F53\u524D\u9875\u9762\u7248\u672C\u8F83\u4F4E\uFF0C\u8BF7\u6309CTRL-F5\u5237\u65B0\u9875\u9762\uFF01", "\u63D0\u793A");} else {if (_0x2651d3 != "") {setTimeout(function () {$("#yzm_img")["attr"]("src", "data:image/png;base64," + _0x2651d3);$("#yzm_unuse_img")["attr"]("src", "data:image/png;base64," + _0x2651d3);if (_0x1769c2 == "00") {$("#yzminfo")["text"]("\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801\u6587\u5B57");} else {if (_0x1769c2 == "01") {$("#yzminfo")["html"]("\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801\u56FE\u7247\u4E2D<font color=\"red\" size=\"4\" style=\"background:#C0C0C0\">\u7EA2\u8272</font>\u6587\u5B57");} else {if (_0x1769c2 == "02") {$("#yzminfo")["html"]("\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801\u56FE\u7247\u4E2D<font color=\"yellow\" size=\"4\" style=\"background:#C0C0C0\">\u9EC4\u8272</font>\u6587\u5B57");} else {if (_0x1769c2 == "03") {$("#yzminfo")["html"]("\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801\u56FE\u7247\u4E2D<font color=\"blue\" size=\"4\" style=\"background:#C0C0C0\">\u84DD\u8272</font>\u6587\u5B57");}}}}yzmSj = _0x1a96a9;jmmy = _0x2b0c56;key6 = _0x2e8ee0;}, 500);}}}}}}}}}},"timeout": 5000,"error": function (_0x11ade1, _0x2c42b8, _0x3a7f30) {if (retrycount == 9) {jAlert("\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5!", "\u63D0\u793A");} else {retrycount = retrycount + 1;getYzmXx();}}});yzmWait = 2;yzmTime($("#yzm_img"));
}function showTime() {var _0x229b47 = new Date();var _0x2be691 = _0x229b47["getTime"]();return _0x2be691;
}

我们注意到key9值的位置,

$["nnyd"]["yzm"](_0x1912a2, _0x478041, _0x41afd2)

这里需要知道$["nnyd"]["yzm"]的具体函数,分析后如下:

_0x4abed0["prototype"]["yzm"] = function (_0x4a04f9, _0x1fcc0a, _0x4473d7) {var _0x3a01ad = new Array(3);_0x3a01ad[0] = _0x4a04f9 + _0x1fcc0a;_0x3a01ad[1] = _0x4a04f9 + _0x1fcc0a + _0x1fcc0a + _0x4a04f9;_0x3a01ad[2] = _0x4a04f9 + _0x4a04f9 + _0x1fcc0a + _0x4a04f9 + _0x1fcc0a + _0x4a04f9;var _0x155fec = _0x3a01ad[0]["substring"](0, 8);var _0x32d768 = _0x3a01ad[0]["substring"](8);var _0x559889 = _0x1e3a12(_0x155fec);var _0x5a173e = _0x559889["length"];for (var _0x2e3884 = 0; _0x2e3884 < _0x5a173e; _0x2e3884++) {for (var _0x39a07a = _0x2e3884 + 1; _0x39a07a < _0x5a173e; _0x39a07a++) {if (_0x559889[_0x2e3884] > _0x559889[_0x39a07a]) {_0x3f015b(_0x559889, _0x2e3884, _0x39a07a);}}}_0x155fec = _0x328421(_0x559889);var _0x3cf5d7 = _0x1e3a12(_0x32d768);var _0x5a173e = _0x3cf5d7["length"];var _0x38743f = 0;for (var _0x2e3884 = 0; _0x2e3884 < _0x5a173e; _0x2e3884++) {_0x38743f = _0x2e3884;for (var _0x39a07a = _0x2e3884 + 1; _0x39a07a < _0x5a173e; _0x39a07a++) {if (_0x3cf5d7[_0x38743f] > _0x3cf5d7[_0x39a07a]) {_0x38743f = _0x39a07a;}}_0x3f015b(_0x3cf5d7, _0x2e3884, _0x38743f);}_0x32d768 = _0x328421(_0x3cf5d7);var _0x8300db = _0x205ff1["encrypt"](_0x155fec) + _0x32d768;var _0x15339a = _0x3a01ad[1]["substring"](0, 9);var _0x3c7f1d = _0x3a01ad[1]["substring"](9, 17);var _0x1dd08a = _0x3a01ad[1]["substring"](17);var _0x591ade = _0x1e3a12(_0x15339a);var _0x5a173e = _0x591ade["length"];var _0x41c5e3 = 0;for (var _0x2e3884 = 0; _0x2e3884 < _0x5a173e; _0x2e3884++) {_0x41c5e3 = _0x2e3884;for (var _0x39a07a = _0x2e3884 + 1; _0x39a07a < _0x5a173e; _0x39a07a++) {if (_0x591ade[_0x41c5e3] > _0x591ade[_0x39a07a]) {_0x41c5e3 = _0x39a07a;}}_0x3f015b(_0x591ade, _0x2e3884, _0x41c5e3);}_0x15339a = _0x328421(_0x591ade);var _0x185cf9 = _0x1e3a12(_0x3c7f1d);var _0x2fa209 = _0x185cf9["length"];_0x3ad848["yzmdelay"](_0x4a04f9, _0x1fcc0a, _0x4473d7);console["log"]("\u9A8C\u8BC1\u7801\u9ED8\u8BA4\u5EF6\u65F6:312");for (var _0x2e3884 = 0; _0x2e3884 < _0x2fa209; _0x2e3884++) {for (var _0x39a07a = _0x2e3884 + 1; _0x39a07a < _0x2fa209; _0x39a07a++) {if (_0x185cf9[_0x2e3884] > _0x185cf9[_0x39a07a]) {_0x3f015b(_0x185cf9, _0x2e3884, _0x39a07a);}}}_0x3c7f1d = _0x328421(_0x185cf9);var _0x30d382 = _0x1e3a12(_0x1dd08a);var _0x3a8185 = _0x30d382["length"];for (var _0x2e3884 = 1; _0x2e3884 < _0x3a8185; _0x2e3884++) {for (var _0x39a07a = _0x2e3884; _0x39a07a > 0; _0x39a07a--) {if (_0x30d382[_0x39a07a] < _0x30d382[_0x39a07a - 1]) {_0x3f015b(_0x30d382, _0x39a07a, _0x39a07a - 1);} else {break;}}}_

这里只展示了部分数据,同时注意到一个参数,后面用得到:

0x5ecc18["setPublicKey"]("MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCjrcnzPya+QS6i5QND2EsIcrsP3/NRwgcYoaNyowpuIzQGDIySfhifm/+j41vJqwKd0D5Otjn6lF5mpUz0zvgMlVco5YytXIbBR8n7WfJ/1W4kTWYr9PM/sT3P23fS3xt13NHln7XgEjP7juv6z52OQOKxYKL/LFxoLkhQpUydWQIBEQ==");

如果有经验,你会知道可能和RSA加密相关,事实也是如此,上面已经对key9的算法位置分析清楚了,下面对flwq39进行分析,实际上,flwq39也是在这个文件中,我使用vscode对解密后的js代码进行了格式化,并查找了flwq39这个关键字,发现如图:

因此,我们继续分析会发现该参数是在请求前拼接完成的,并且关键字本身被替换了:

反向找到调用的函数就会发现最终是调用了RSA加密算法,其中PublicKey就是

MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCjrcnzPya+QS6i5QND2EsIcrsP3/NRwgcYoaNyowpuIzQGDIySfhifm/+j41vJqwKd0D5Otjn6lF5mpUz0zvgMlVco5YytXIbBR8n7WfJ/1W4kTWYr9PM/sT3P23fS3xt13NHln7XgEjP7juv6z52OQOKxYKL/LFxoLkhQpUydWQIBEQ==

在验证码获取后返回包如下:

jQuery11020854931324645166_1625223145135({"key1":"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","key2":"2021-07-02 18:34:48","key3":"43017c78ec891a4b9406501694f0b479","key4":"01","key5":"2","key6":"402887f17a53027c017a66d4d62d72d0"})

其中key1是经过base64编码的图片数据,key2是验证码的时间,另外注意到key3和key4及key6。

其中key4分为4种情况分别为输入全部、黄色、红色、蓝色,对应00,01,02,03。余下的参数在验证阶段用到。

同理,在查验阶段,请求如下:

https://fpcy.anhui.chinatax.gov.cn/NWebQuery/vatQuery?callback=jQuery11020854931324645166_1625223145135&key1=034012000211&key2=12345678&key3=20210702&key4=123456&fplx=10&yzm=MK&yzmSj=2021-07-02+18%3A34%3A48&index=43017c78ec891a4b9406501694f0b479&key6=402887f17a53027c017a66d4d62d72d0&publickey=2021-07-02+18%3A34%3A48&key9=ac558f9ae05a94c21dc504f5d8882b9d&_=1625223145137&flwq39=Ky8pYUqln7zaEZcxF9XZw3fAsiOM%2F92RmTxy%2BNAtDo4f1h3c1yHQJZNESl5Nz9Xq5Mu7bEeBkFlPgerOBnR1pnLviLn4WLkMTtzsLy%2BMe2wPu%2B%2FFaiszckIGS%2F1Z5YZ4zusosj68YLZ0hRk53UWbrWz9xg%2BC3XRGwEWyqbzg0XE%3D

这里注意到

key1=发票代码
key2=发票号码
key3=发票日期
key4=校验码或者不含税的金额
fplx=发票类型,一个函数
yzm=验证码
yzmsj=获取验证码请求的返回包里的key2
index=获取验证码请求的返回包里的Key3
key6=获取验证码请求的返回包里的Key6
publickey=验证码时间
key9=加密参数
flwq39=加密参数

这里的key9和flwq39在

$["nnyd"]["cy"]

这个对应的函数中,key9和flwq39算法和上面的类似。

此外注意到fplx这种参数,也在这几个js文件中,这里给出具体的函数名:

var code=["144031539110", "131001570151", "133011501118", "111001571071"];function alxd(a) {var b;var c = "99";if (a.length == 12) {b = a.substring(7, 8);for (var i = 0; i < code.length; i++) {if (a == code[i]) {c = "10";break}}if (c == "99") {if (a.charAt(0) == '0' && a.substring(10, 12) == '11') {c = "10"}if (a.charAt(0) == '0' && (a.substring(10, 12) == '04' || a.substring(10, 12) == '05')) {c = "04"}if (a.charAt(0) == '0' && (a.substring(10, 12) == '06' || a.substring(10, 12) == '07')) {c = "11"}if (a.charAt(0) == '0' && a.substring(10, 12) == '12') {c = "14"}}if (c == "99") {if (a.substring(10, 12) == '17' && a.charAt(0) == '0') {c = "15"}if (c == "99" && b == 2 && a.charAt(0) != '0') {c = "03"}}} else if (a.length == 10) {b = a.substring(7, 8);if (b == 1 || b == 5) {c = "01"} else if (b == 6 || b == 3) {c = "04"} else if (b == 7 || b == 2) {c = "02"}}return c
}

通过使用php的v8js拓展,我们可以实现接口编写:

二者结果一致。

至此,全部参数已经解密部分完毕。

第三步,算法的完全还原,脱离js环境,这里我使用C#实现算法还原和脱离

首先,我们需要知道的是在核心的算法中,源代码使用了ob进行了混淆,我们使用第三方软件进行初次还原时,也只能还原一部分,核心的内容基本会被还原,但是生成的代码还是无法完全被理解阅读,基于此,需要二次还原,这里注意到Ob混淆的核心思想,是一个大数组和若干个解密函数,后续的代码里不断的调用解密函数进行解密。

设计如下:通过分析可以注意到解密函数的前缀是_开头的,后续是)]或其他的组合,因此,我们需要使用提取函数名,在调用时,才能知道那些函数可以还原,同时在提取时也随同获取调用的参数,如果参数中包含变量,则直接忽略,并在调用成功后进行替换。

 string[] ret = getBValueT(djm, "_", "\\)");if (ret != null && ret.Count() > 0){foreach (string s in ret){if (s.IndexOf("=") == -1 && s.IndexOf(":") == -1 && s.IndexOf(",") != -1){listBox1.Items.Add("_" + s + ")");listBox1.Items.Add("_" + s + "))");File.AppendAllText("function.txt", "_0x" + s + ")" + ";\r\n");}}}//第二种情况ret = getBValueT(djm, "_", "\\]");if (ret != null && ret.Count() > 0){foreach (string s in ret){if (s.IndexOf(",") != -1){listBox1.Items.Add("_" + s + "]");listBox1.Items.Add("_" + s + "");File.AppendAllText("function.txt", "_" + s + ")" + ";\r\n");}}}//第三种情况ret = getBValueT(djm, "\\[_", "\\]");if (ret != null && ret.Count() > 0){foreach (string s in ret){if (s.IndexOf(",") != -1){listBox1.Items.Add("[_" + s + "]");listBox1.Items.Add("_" + s + "");File.AppendAllText("function.txt", "_" + s + ")" + ";\r\n");}}}//第四种情况ret = getBValueT(djm, "\\(_", "\\)");if (ret != null && ret.Count() > 0){foreach (string s in ret){if (s.IndexOf(",") != -1){listBox1.Items.Add("(_" + s + ")");listBox1.Items.Add("(_" + s + "))");File.AppendAllText("function.txt", "_" + s + ")" + ";\r\n");}}//  label3.Text = "匹配到" + listBox1.Items.Count + "个函数";}
 try{List<string> ret = new List<string>();Regex regex = new Regex("(?<=(" + sStr + "))0x[0-9a-z]{4,6}[\\[|\\(][.\\s\\S]*?(?=(" + eStr + "))", RegexOptions.Singleline|RegexOptions.Multiline);MatchCollection mc = regex.Matches(str);for (int i = 0; i < mc.Count; i++){ret.Add(mc[i].Value);}return ret.ToArray();}catch{return new string[] { };}

通过上述操作,我们就能最大程度还原出原始的代码段。

接着,彻底逆向还原使用其他语言改写,如果你看过本文,并对相关js有分析,你大概会知道,核心部分就是涉及几个加密算法,如md5和移位的一些操作。但其核心的算法如下:

第一个是Gen函数

第二个是key9

其他的类似。部分代码如下图:

国家税务总局全国增值税发票查验平台网站js逆向分析及全逆向算法还原相关推荐

  1. 国家税务总局全国增值税发票查验平台-1

    准备做个查验记录保存,方便数据归集.拿python练手. 1 安装控件 pip install pywebview pip install cefpython3 2 功能实现 2.1 main.py ...

  2. 国家税务总局全国增值税发票查验平台验证码刷不出来显示系统繁忙的解决方法

    虽然我们解决了访问https://inv-veri.chinatax.gov.cn/不行的问题,但是验证码的接口依然是不同的网址,需要解决验证码接口的访问问题. 找一下你要查验发票的地址,比如我的发票 ...

  3. 全国增值税发票查验平台 | 免验证码

    国家税务总局全国增值税发票查验平台 众所周知,发票查验有一个肉眼难以辨认的验证码,今天推荐给各位的是国税总局发票查验的免码接口,目前支持全发票种类,你们看到的没错,是全发票种类,市面上的API接口也不 ...

  4. MacBook Pro(苹果系统macOS)全国增值税发票查验平台无法获取验证码解决

    首先安装根证书,手动安装 下载证书得到 command+空格,进这个钥匙串访问app 将下载的文件拖进来安装好 我们返回验票网站,发现点击验证码还是不太行啊 https://fpcy.shanghai ...

  5. 国税总局增值税发票查验平台验证码识别深度学习实战

    国家税务总局全国增值税发票查验平台验证码 查验验证码图片如下面所示: 测试地址:http://47.99.174.98:8808/ 1.验证码识别Python版 import base64 impor ...

  6. 国家税务总局增值税发票查验平台不显示验证码的解决方法

    1.没有安装根证书,具体操作方法可参考平台操作说明,这里不再赘述: 2.已安装根证书却不显示验证码.以edge浏览器为例,其他浏览器同理. ■按F12键(笔记本电脑按Fn+F12),打开开发人员工具. ...

  7. JS逆向——国税总局发票查验平台

    国家税务总局全国增值税发票查验平台 https://inv-veri.chinatax.gov.cn/ 最近朋友有个新需求,就是做一个发票校验的爬虫,由于这个网站有一些不是很友好的反爬,导致对新手的非 ...

  8. 逆向工程Python爬虫——国税局发票查验平台

    前言 这是一篇含金量很高的干货文章,笔者将手把手带领各位一步一步地实现爬取国家税务总局全国增值税发票查验平台(以下简称"查验平台").这个想法诞生在19年初,当时在做一款通过扫描二 ...

  9. 发票查验平台 https://inv-veri.chinatax.gov.cn 您的连接不是私密连接,不能访问问题

    问题描述 国家税务总局全国增值税发票查验平台,https://inv-veri.chinatax.gov.cn 您的连接不是私密连接,不能直接访问问题 解决方案 直接在页面用键盘输入 thisisun ...

最新文章

  1. 区块链软件公司:创新的区块链技术如何改变法律行业的面貌
  2. Java虚拟机是什么
  3. Java使用Apache CXF开发Web Service
  4. linux nslookup 解析不到dns_涉及DNS的简单操作,只看这一篇就够了
  5. vue和小程序哪个好学一点_litemall,Spring Boot后端,微信小程序用户前端 + Vue用户移动端...
  6. 使用Qt设计师文件的3种方式
  7. 字符串和数组中split().toString(),join(),splice(),slice(),substr()和substring()
  8. VHDL常用操作符介绍
  9. 【全网最全的博客美化系列教程】08.自定义地址栏Logo
  10. 【软考】信息系统项目管理师,考试大纲与历年考点分析,学习方法(2021版)
  11. 鸿蒙app安卓版包,支付宝鸿蒙版本下载-支付宝鸿蒙app最新版 v10.2.8.7000-优盘手机站...
  12. 华为OLT快速配置指南
  13. 项目管理:系统需求分析模板
  14. 智力问答选择题_智力问答:智力题大全及答案
  15. f检验matlab计算,方差分析F检验的步骤和判定
  16. 微信小程序wx.setClipboardData复制文本
  17. UltraEdit文本编辑器-UE
  18. 电脑桌面图片变成白色的解决方案
  19. python h5游戏_记一次游戏H5开发经验
  20. 31、OPNET信道模型概述

热门文章

  1. Java SE核心API(2) —— 正则表达式、Object、包装类
  2. 神经网络中的梯度爆炸
  3. R语言数据科学:变量选择(一)逐步回归法
  4. open judge 1.5 18:鸡尾酒疗法
  5. 英语语法总结--名词
  6. 《孙子兵法战场机变之行军篇》
  7. 《ROS学习之路(1)》ROS Kinetic版本安装---ubuntu16.04(Xenial Xerus 好客的非洲地松鼠)
  8. pojFilp Game2965 翻转棋子
  9. 实验一:鸢尾花数据集分类
  10. 电工学复习【2】-- 电路的分析方法