前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【JS 逆向百例】元素ID定位加密位置,某麻将数据逆向

【JS 逆向百例】元素ID定位加密位置,某麻将数据逆向

原创
作者头像
K哥爬虫
修改于 2021-08-26 09:34:00
修改于 2021-08-26 09:34:00
3.2K0
举报
文章被收录于专栏:Python 爬虫Python 爬虫

声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

  • 目标:某在线麻将游戏的网页数据
  • 主页:aHR0cHM6Ly90ZW5ob3UubmV0LzIvP3E9MzM2bTIzN3AyNDc5czE2N3ozcw==

逆向过程

抓包分析

本次要逆向的对象于以往不同,不是某个接口的参数,而是网页中的数据,一般网页中的数据都可以在源码中看到,或者通过某个接口传过来,而本次的目标数据是通过 JS 加密得到的,先来抓包看看基本情况:

01.png
01.png

F12 检查,可以看到我们要的数据在 textarea 标签里面,看起来没什么毛病,那么直接使用 Xpath 提取试试看:

代码语言:txt
AI代码解释
复制
import requests
from lxml import etree


url = '脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler'
headers = {
    'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

response = requests.get(url=url, headers=headers)
tree = etree.HTML(response.text)
data = tree.xpath('//textarea/text()')
print(data)
02.png
02.png

可以看到实际上提取到的数据是为空的,我们查看网页源代码,直接搜索 textarea,同样也是没有的,试试直接搜索数据也是没有的:

03.png
03.png
04.png
04.png

加密逆向

既然这种数据不存在于网页源码中,也不是通过其他接口返回的,那么最有可能就是通过 JS 加密后直接插入到网页源码中的,那么这里应该如何定位加密的位置呢?对比一下插入数据后的网页源码和未插入数据的网页源码,可以看到蓝色框里的代码都是通过 JS 插入的,而且这个 1008.js 多半就是加密的 JS 文件:

05.png
05.png

这里我们想到一个 JavaScript 语法,如需从 JavaScript 访问某个 HTML 元素,可以使用 document.getElementById(id) 方法,这个 id 就是某个 HTML 元素的属性,然后使用 innerHTML 来获取或插入元素内容,可以看菜鸟教程的一个例子:

06.png
06.png

通过这种语法,结合前面源码中的几个标签,我们就可以猜测,某个 JS 里面可能会存在这样的语句:document.getElementById("tehai").innerHTMLdocument.getElementById("tips").innerHTMLdocument.getElementById("m2").innerHTML,直接全局搜索其中任意一个语句,就可以在 1008.js 里面找到对应的结果,当然直接搜索这个标签的 id 也是可以找到结果的,埋下断点进行调试:

07.png
07.png

可以发现第 913 行 document.getElementById("m2").innerHTML = d + "<br>" 是向 m2 标签里面插入值 d 和换行符,一步一步往上看,可以发现 d 包含了很多 html 的东西,而上面的 g 只有文本,刚好是目标数据,那么我们最终返回直接 return 这个 g 就好了。

继续往上跟踪 g 的值的来源,会发现步骤比较复杂,那么我们直接将这部分函数(fa 函数)整个复制下来运行调试(大约第 794 行至第 914 行), 本地进行调试会提示 gaO 未定义,我们在其定义的语句的下一行埋下断点进行调试,可以看到 ga 的值其实是固定的 qO 就是 URL 后面 q 的值,如:336m237p2479s167z3s

08.png
08.png

将这两个变量进行定义后,接着本地调试,又会提示 aaca 等函数未定义,依赖的函数比较多,那么这种情况下就没必要去挨个扣,直接将 fa 以前的所有函数都 copy 下来进行调试即可,这样就直接解决了所有依赖。

完整代码

GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/

以下只演示部分关键代码,完整代码仓库地址:https://github.com/kgepachong/crawler/

关键 JS 加密代码架构

代码语言:txt
AI代码解释
复制
// Copyrights C-EGG inc.

var u = function () {}();

function w() {}

w.prototype = {};

function x(b, a, g, d) {}

// 此处省略 N 个函数

function M(b) {}

function N(b, a) {}

function ea(b) {}

function fa(O) {
    function b(a, b) {
        var c, d = 0;
        for (c = 0; c < a.length; ++c) d += 4 - b[a[c]];
        return d
    }

    // var a = ga, g = O, d;
    var a = 'q', g = O, d;
    d = "<hr size=1 color=#CCCCCC >";
    switch (a.substr(0, 1)) {
        case "q":
            d += '標準形(七対国士を含む)の計算結果 / <a href="?p' + a.substr(1) + "=" + g + '">一般形</a><br>';
            break;
        case "p":
            d += '一般形(七対国士を含まない)の計算結果 / <a href="?q' + a.substr(1) + "=" + g + '">標準形</a><br>'
    }
    for (var c = "d" == a.substr(1, 1), a = a.substr(0, 1), g = g.replace(/(\d)(\d{0,8})(\d{0,8})(\d{0,8})(\d{0,8})(\d{0,8})(\d{0,8})(\d{8})(m|p|s|z)/g, "$1$9$2$9$3$9$4$9$5$9$6$9$7$9$8$9").replace(/(\d?)(\d?)(\d?)(\d?)(\d?)(\d?)(\d)(\d)(m|p|s|z)/g, "$1$9$2$9$3$9$4$9$5$9$6$9$7$9$8$9").replace(/(m|p|s|z)(m|p|s|z)+/g, "$1").replace(/^[^\d]/, ""), g = g.substr(0, 28), f = aa(g), r = -1; r = Math.floor(136 * Math.random()), f[r];) ;
    var m = Math.floor(g.length / 2) % 3;
    2 == m || c || (f[r] = 1, g += H(r));
    var f = ca(f),
        n = "",
        e = G(f, 34),
        n = n + N(e, 28 == g.length),
        n = n + ("(" + Math.floor(g.length / 2) + "枚)");
    -1 == e[0] && (n += ' / <a href="?" >新しい手牌を作成</a>');
    var n = n + "<br/>",
        q = "q" == a ? e[0] : e[1],
        k,
        p,
        l = Array(35);
    if (0 == q && 1 == m && c) k = 34,
        l[k] = K(f),
    l[k].length && (l[k] = {
        i: k,
        n: b(l[k], f),
        c: l[k]
    });
    else if (0 >= q) for (k = 0; 34 > k; ++k) f[k] && (f[k]--, l[k] = K(f), f[k]++, l[k].length && (l[k] = {
        i: k,
        n: b(l[k], f),
        c: l[k]
    }));
    else if (2 == m || 1 == m && !c) for (k = 0; 34 > k; ++k) {
        if (f[k]) {
            f[k]--;
            l[k] = [];
            for (p = 0; 34 > p; ++p) k == p || 4 <= f[p] || (f[p]++, F(f, "p" == a) == q - 1 && l[k].push(p), f[p]--);
            f[k]++;
            l[k].length && (l[k] = {
                i: k,
                n: b(l[k], f),
                c: l[k]
            })
        }
    } else {
        k = 34;
        l[k] = [];
        for (p = 0; 34 > p; ++p) 4 <= f[p] || (f[p]++, F(f, "p" == a) == q - 1 && l[k].push(p), f[p]--);
        l[k].length && (l[k] = {
            i: k,
            n: b(l[k], f),
            c: l[k]
        })
    }
    var t = [];
    for (k = 0; k < g.length; k += 2) {
        p = g.substr(k, 2);
        var v = ba(p),
            h = J(g.replace(p, "").replace(/(\d)(m|p|s|z)/g, "$2$1$1,").replace(/00/g, "50").split(",").sort().join("").replace(/(m|p|s|z)\d(\d)/g, "$2$1")),
            R = q + 1,
            I = l[v];
        I && I.n && (R = -1 == q ? 0 : q, void 0 == I.q && t.push(I), I.q = h);
        2 == m && (h += H(r));
        n += (2 == m || 2 != m && !c ? da : L)(p, 2 == k % 3 && k == g.length - 2 ? " hspace=3 " : "", a, h, v, R)
    }
    l[34] && l[34].n && (l[34].q = J(g), t.push(l[34]), n += '<br><br><a href="?' + a + "=" + l[34].q + '">次のツモをランダムに追加</a>');
    t.sort(function (a, b) {
        return b.n - a.n
    });
    // g = "" + (document.f.q.value + "\n");
    g = "" + (O + "\n");
    d += "<table cellpadding=2 cellspacing=0 >";
    q = 0 >= q ? "待ち" : "摸";
    for (k = 0; k < t.length; ++k) {
        v = t[k].i;
        d += "<tr id=mda" + v + " ><td>";
        34 > v && (d += "打</td><td>" + ('<img src="https://cdn.tenhou.net/2/a/' + H(4 * v + 1) + '.gif" class=D />') + "</td><td>", g += "打" + H(4 * v + 1) + " ");
        d += q + "[</td><td>";
        g += q + "[";
        l = t[k].c;
        c = t[k].q;
        for (p = 0; p < l.length; ++p) r = H(4 * l[p] + 1),
            d += '<a href="?' + a + "=" + (c + r) + '" class=D onmouseover="daFocus(this,' + v + ');" onmouseout="daUnfocus();"><img src="https://cdn.tenhou.net/2/a/' + r + '.gif" border=0 /></a>',
            g += H(4 * l[p] + 1);
        d += "</td><td>" + t[k].n + "枚</td><td>]</td></tr>";
        g += " " + t[k].n + "枚]\n"
    }
    d = d + "</table><br><hr><br>" + ('<textarea rows=10 style="width:100%;font-size:75%;">' + g + "</textarea>");
    -1 == e[0] && (d = d + "<hr size=1 color=#CCCCCC >" + ea(f));
    // document.getElementById("tehai").innerHTML = n;
    // document.getElementById("tips").innerHTML = "";
    // document.getElementById("m2").innerHTML = d + "<br>"
    return g
}

// 测试样例
// console.log(fa('336m237p2479s167z3s'))

Python 代码

代码语言:txt
AI代码解释
复制
#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import execjs


url = '脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler'


def main():
    q = url.split('=')[1]
    with open('decrypt.js', 'r', encoding='utf-8') as f:
        decrypt_js = f.read()
    data = execjs.compile(decrypt_js).call('fa', q)
    print(data)


if __name__ == '__main__':
    main()

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【JS 逆向百例】PEDATA 加密资讯以及 zlib.gunzipSync() 的应用
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2022/01/06
7970
【JS 逆向百例】PEDATA 加密资讯以及 zlib.gunzipSync() 的应用
C#结合JS实现HtmlTable动态添加行并保存到数据库
在 Web 应用项目中,实现一对多录入的数据管理功能是一项常见的应用。因此可以实现一个相对轻量化的设计实现表格的录入,为保证功能的可用性、界面友好性,总体的需求如下:
初九之潜龙勿用
2024/06/20
2720
【JS 逆向百例】无限debugger绕过,某政民互动数据逆向
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/08/30
1.6K0
【JS 逆向百例】无限debugger绕过,某政民互动数据逆向
【JS 逆向百例】Ether Rock 空投接口
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/11/24
7170
【JS 逆向百例】Ether Rock 空投接口
(html,css,js)动漫网页完整源码+演示
演示网址:日语学习 视频演示: riyu 如下是所有代码,没有隐藏,各位可以自己测试。 index.html DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="style/main.css"> <title>川川学长带你学日语50音图 | 平假名title> head> <body> <div id="wrap"> <c
川川菜鸟
2021/10/18
3.8K0
【JS 逆向百例】百度翻译接口参数逆向
JS逆向百例_快代理logo.png 逆向目标 目标:百度翻译接口参数 主页:https://fanyi.youdao.com/ 接口:https://fanyi.baidu.com/v2transapi 逆向参数: Form Data: sign: 706553.926920 token: d838e2bd3d5a3bb67100a7b789463022 逆向过程 抓包分析 我们在百度翻译页面随便输入文字,可以看到没有刷新页面,翻译结果就出来了,由此可以推断是 Ajax 加载的,打开开发者工具,选择 X
K哥爬虫
2021/08/05
1.4K0
【JS 逆向百例】百度翻译接口参数逆向
【JS 逆向百例】DOM事件断点调试,某商盟登录逆向
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/09/06
1.1K0
【JS 逆向百例】DOM事件断点调试,某商盟登录逆向
【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2023/01/12
1.6K0
【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解
CTF论剑场 Web14-21 WriteUp
根据hint信息可以猜测为 /.git/敏感文件泄露,该目录下包含了所有 git 正常工作所需要的信息。 使用 GitHack工具(项目地址:https://github.com/lijiejie/GitHack)进行探测:
安恒网络空间安全讲武堂
2019/09/29
2K0
CTF论剑场 Web14-21 WriteUp
JS代码格式化和语法着色
有时为了研究学习一些格式不规范的JS代码段,需要将代码段格式化一下,这样思路就会清晰多了,网上找到此款格式化的工具,将以下代码保存为html格式文件即可使用 <html> <head> <title>JSer </title> <meta http-equiv="content-type" content="text/html; charset=gb2312" /> <style> /* Global CSS */ * { padding:0px; margin:0px; font-size:13px; f
欢醉
2018/01/22
5.6K0
JS代码格式化和语法着色
JavaScript学习笔记+常用js用法、范例(二)
javascript 加入如下语句,出错时会提示 注意: chrome、opera 和 safari 等浏览器不支持 window.onerror 事件(w3c标准没有此事件),需另外捕获出错信息
用户6808043
2022/02/24
2.3K0
【JS 逆向百例】XHR 断点调试,Steam 登录逆向
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/09/09
1.9K0
【JS 逆向百例】XHR 断点调试,Steam 登录逆向
【JS 逆向百例】37网游登录接口参数逆向
本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/08/17
8000
【JS 逆向百例】37网游登录接口参数逆向
【JS 逆向百例】复杂的登录过程,最新WB逆向
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/08/30
2K0
【JS 逆向百例】复杂的登录过程,最新WB逆向
Typecho 无插件实现即时搜索
在functions.php最后面添加以下,通过每次访问判断文件间隔时间来达到更新缓存的目的。上方js里的search_a路径需要填写完整路径+/caches/cache.json
泽泽社长
2023/04/17
8040
【JS 逆向百例】网洛者反爬练习平台第六题:JS 加密,环境模拟检测
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/12/28
8440
【JS 逆向百例】网洛者反爬练习平台第六题:JS 加密,环境模拟检测
《优化》Typecho-handsome主题下实现评论一键打卡、赞、踩功能并集成图片上传功能
在后台 --> 设置外观 --> 开发者设置 --> 自定义JavaScript 加入以下代码:
听闻所见
2023/07/29
3140
《优化》Typecho-handsome主题下实现评论一键打卡、赞、踩功能并集成图片上传功能
qrCode生成二维码图片
QRCode.js 是一个用于生成二维码图片的插件。 1.文件脚本 var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,th
用户1055830
2018/01/18
2.6K0
qrCode生成二维码图片
【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向
本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!
K哥爬虫
2021/10/12
2.1K0
【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向
js如何判断手机横屏还是竖屏的方法
七辰
2023/09/28
1.2K0
推荐阅读
相关推荐
【JS 逆向百例】PEDATA 加密资讯以及 zlib.gunzipSync() 的应用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档