【原创】 猿人学第一题解析

查看 78|回复 11
作者:cainfish   
本文适合像我一样得小白,大牛请略过,主要是记录,哈哈哈。一、 发现一个练手的好地方
              昨日在浏览论坛的时候,发现大牛 发了一个帖子 猿人学第二题 手把手补环境
链接地址:猿人学第2题手把手补环境 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn


image.png (76.3 KB, 下载次数: 2)
下载附件
2022-12-13 16:57 上传

依照Anekys 大牛提供的地址,进入之后返现者的是个练手的好地方,哈哈哈,js解密过程中,能遇到的问题,几乎在这边全部遇到了。并且还有解题排名,膜拜各种大牛的机会。
二、 正式开始
      2.1 过掉debugger 分析页面
           首先看第一题


image.png (32.73 KB, 下载次数: 1)
下载附件
2022-12-13 19:40 上传

要求是获取机票的平均价格,填入答案。
依照国际管理,F12,开发者工具,ctrl+shift+r 重新加载页面,不出意外的界面停止在debugger


image.png (11.37 KB, 下载次数: 2)
下载附件
2022-12-13 19:45 上传

直接在第二行除邮件编辑断点  值填写false,过掉debugger。
       2.2  依次点击每一页的值查看,请求值变化
第一页  /api/match/1?m=5c70fb1948228fdf84f74568b037fa11|81671008953
第二页 /api/match/1?page=2&m=922c0993d9df7bc038a09470c17d5901|81671009628
第三页 api/match/1?page=3&m=e9526008c0fde5ba4e4499ec78289239|81671032379
                不难看出请求不能的页面出了添加了page的参数外,m的值发生了变化,如果在全局搜索里面搜索m的话,这个值太多了直接去启动器中查看堆栈调用


forum.png (37.66 KB, 下载次数: 1)
下载附件
2022-12-13 19:59 上传

排除掉ajax 后,第一个就是request函数了,点击函数进入源代码区查看。


image.png (102.36 KB, 下载次数: 1)
下载附件
2022-12-13 20:02 上传

2.3   解密混淆和加密得js代码
js代码被加密混淆了,在线搜索js解密工具,其实不解密也能看,但是阅读的难度就比较高了。
解码后得到
[JavaScript] 纯文本查看 复制代码window['url'] = '/api/' + 'match' + '/1',
    request = function() {
        var _0x2268f9 = Date['parse'](new Date()) + (16798545 + -72936737 + 156138192),
            _0x57feae = oo0O0(_0x2268f9['toStr' + 'ing']()) + window['f'];
        const _0x5d83a3 = {};
        _0x5d83a3['page'] = window['page'],
            _0x5d83a3['m'] = _0x57feae + '丨' + _0x2268f9 / (-1 * 3483 + -9059 + 13542);             //  看到m出现了
        var _0xb89747 = _0x5d83a3;
        $['ajax']({
            'url': window['url'],
            'dataType': 'json',
            'async': ![],
            'data': _0xb89747,
            'type': 'GET',
            'beforeSend': function(_0x4c488e) {},
            'success': function(_0x131e59) {
                _0x131e59 = _0x131e59['data'];
                let _0x354583 = '',
                    _0x1b89ba = '' + '中国联合航' + '空' + 'KN591' + '1波' + '音737(' + '中)' + '' + '' + '13:50' + '' + '大兴' + '国际机场' + '' + '3' + '小时40分' + '钟' + '' + '17:' + '30' + '宝安机场
' + '' + '&' + 'yen;' + 'p' + 'rice_' + 'sole' + '
' + '' + '' + '收起' + '
' + ''),
                    _0x548377 = ['中国南方航' + '空', '吉祥航空', '奥凯航空', '九元航空', '长龙航空', '东方航空', '中国国际航' + '空', '深圳航空', '海南航空', '春秋航空', '上海航空', '西部航空', '重庆航空', '西藏航空', '中国联合航' + '空', '云南祥鹏航' + '空', '云南英安航' + '空', '厦门航空', '天津航空', '山东航空', '四川航空', '华夏航空', '长城航空', '成都航空有', '北京首都航' + '空', '中华航空', '意大利国家' + '航空公司', '印度百捷航' + '空', '越南航空', '远东航空', '印度航空公' + '司', '印度捷特航' + '空有限公司', '以色列航空' + '公司', '意大利航空', '伊朗航空公' + '司', '印度尼西亚' + '鹰航空公司', '英国航空公' + '司', '西方天空航' + '空', '西捷航空', '西班牙欧洲' + '航空公司', '西班牙航空' + '公司', '中国南方航' + '空', '吉祥航空', '奥凯航空', '九元航空', '长龙航空', '东方航空', '中国国际航' + '空', '深圳航空', '海南航空', '春秋航空', '上海航空', '西部航空', '重庆航空', '西藏航空', '中国联合航' + '空', '云南祥鹏航' + '空', '云南英安航' + '空', '厦门航空', '天津航空', '山东航空', '四川航空', '华夏航空', '长城航空', '成都航空有', '北京首都航' + '空', '中华航空', '意大利国家' + '航空公司', '印度百捷航' + '空', '越南航空', '远东航空', '印度航空公' + '司', '印度捷特航' + '空有限公司', '以色列航空' + '公司', '意大利航空', '伊朗航空公' + '司', '印度尼西亚' + '鹰航空公司', '英国航空公' + '司', '西方天空航' + '空', '西捷航空', '西班牙欧洲' + '航空公司', '西班牙航空' + '公司'],
                    _0x5286d2 = 22 * 251 + -1721 + -3800,
                    _0xa24ff9 = ['北京首都国' + '际机场', '上海虹桥国' + '际机场', '上海浦东国' + '际机场', '天津滨海国' + '际机场', '太原武宿机' + '场', '呼和浩特白' + '塔机场', '沈阳桃仙国' + '际机场', '大连周水子' + '国际机场', '长春大房身' + '机场', '哈尔滨阎家' + '岗国际机场', '齐齐哈尔三' + '家子机场', '佳木斯东郊' + '机场', '厦门高崎国' + '际机场', '福州长乐国' + '际机场', '杭州萧山国' + '际机场', '合肥骆岗机' + '场', '宁波栎社机' + '场', '南京禄口国' + '际机场', '广州白云国' + '际机场', '深圳宝安国' + '际机场', '长沙黄花机' + '场', '海口美亚机' + '场', '武汉天河机' + '场', '济南遥墙机' + '场', '青岛流亭机' + '场', '南宁吴墟机' + '场', '三亚凤凰国' + '际机场', '重庆江北国' + '际机场', '成都双流国' + '际机场', '昆明巫家坝' + '国际机场', '昆明长水国' + '际机场', '桂林两江国' + '际机场', '西安咸阳国' + '际机场', '兰州中川机' + '场', '贵阳龙洞堡' + '机场', '拉萨贡嘎机' + '场', '乌鲁木齐地' + '窝堡机场', '南昌向塘机' + '场', '郑州新郑机' + '场', '北京首都国' + '际机场', '上海虹桥国' + '际机场', '上海浦东国' + '际机场', '天津滨海国' + '际机场', '太原武宿机' + '场', '呼和浩特白' + '塔机场', '沈阳桃仙国' + '际机场', '大连周水子' + '国际机场', '长春大房身' + '机场', '哈尔滨阎家' + '岗国际机场', '齐齐哈尔三' + '家子机场', '佳木斯东郊' + '机场', '厦门高崎国' + '际机场', '福州长乐国' + '际机场', '杭州萧山国' + '际机场', '合肥骆岗机' + '场', '宁波栎社机' + '场', '南京禄口国' + '际机场', '广州白云国' + '际机场', '深圳宝安国' + '际机场', '长沙黄花机' + '场', '海口美亚机' + '场', '武汉天河机' + '场', '济南遥墙机' + '场', '青岛流亭机' + '场', '南宁吴墟机' + '场', '三亚凤凰国' + '际机场', '重庆江北国' + '际机场', '成都双流国' + '际机场', '昆明巫家坝' + '国际机场', '昆明长水国' + '际机场', '桂林两江国' + '际机场', '西安咸阳国' + '际机场', '兰州中川机' + '场', '贵阳龙洞堡' + '机场', '拉萨贡嘎机' + '场', '乌鲁木齐地' + '窝堡机场', '南昌向塘机' + '场', '郑州新郑机' + '场'];
                if (window['page']) {} else
                    window['page'] = 2333 * 3 + 458 * -5 + -4708;
                $['each'](_0x131e59, function(_0x282f1d, _0x4e0853) {
                        _0x354583 += _0x1b89ba['repla' + 'ce']('price' + '_sole', _0x4e0853['value'])['repla' + 'ce']('中国联合航' + '空', _0x548377[_0x5286d2 * window['page']])['repla' + 'ce']('大兴国际', _0xa24ff9[parseInt(_0x5286d2 * window['page'] / (659 + 785 * -7 + 4838)) + (5666 * 1 + 2 * -4161 + 2657)])['repla' + 'ce']('宝安机场', _0xa24ff9[_0xa24ff9['lengt' + 'h'] - parseInt(_0x5286d2 * window['page'] / (8357 + -323 * 1 + -8032)) - (350 + -9 * 295 + 2306)]),
                            _0x5286d2 += -156 * -53 + -78 * -111 + -16925;
                    }),
                    $('.m-ai' + 'rfly-' + 'lst')['text']('')['appen' + 'd'](_0x354583);
            },
            'complete': function() {},
            'error': function() {
                alert('数据拉取失' + '败。可能是' + '触发了风控' + '系统,若您' + '是正常访问' + ',请使用谷' + '歌浏览器无' + '痕模式,并' + '且校准电脑' + '的系统时间' + '重新尝试'),
                    alert('生而为虫,' + '我很抱歉,' + '请刷新页面' + ',查看问题' + '是否存在'),
                    $('.page' + '-mess' + 'age')['eq'](17 * -94 + 1014 + -4 * -146)['addCl' + 'ass']('activ' + 'e'),
                    $('.page' + '-mess' + 'age')['remov' + 'eClas' + 's']('activ' + 'e');
            }
        });
    },
    request();
虽然还是有加密的内容,但是我们看到了需要的关键数据 page 和 m的出现  并且后面又是ajax,推断加密代码就在前面几行,对照加密数据设置断点。


image.png (46.6 KB, 下载次数: 0)
下载附件
2022-12-13 20:10 上传

果然断在了断点处,步进查看变化。
小技巧:如果数值看不懂得,可以直接在控制台输入之后;


image.png (4.09 KB, 下载次数: 3)
下载附件
2022-12-13 20:24 上传

继续往下走,跳转到了第一页 页面自身得 javascript  ,因为页面是一行超级长,复制出来,格式化以便理解。


image.png (86.39 KB, 下载次数: 2)
下载附件
2022-12-13 20:33 上传

继续安利,哈哈哈,我举得我更像一个分享up主。
删除掉不要得之后,发现了管家加密函数---------         
[color=] oo0O0  是的就是这个狗东西。


image.png (36.14 KB, 下载次数: 1)
下载附件
2022-12-13 20:40 上传

请注意后面那个孤零零得箭头,就是她使我走向了一条没有尽头得路。
三、 解密关键函数
上文说到,window['\x66']  \x66 就是f啦,解密后的函数有表明,在跟进 关键解密函数
[color=]oo0O0  
后,函数内容如下:
[JavaScript] 纯文本查看 复制代码
function oo0O0(mw) {
    window.b = '';
    for (var i = 0, len = window.a.length; i > (-0x2 * C & 0x6)) : 0x0) {
                    W = m['indexOf'](W)
                }
                return A
            };
            var t = function (w, m) {
                var T = [],
                A = 0x0,
                C,
                b = '',
                W = '';
                w = Y(w);
                for (var R = 0x0, v = w['length']; R
看到函数定义后  马上定义了一个,window.b , window.b得值 是通过windows.a.length(长度)for 循环后计算得出,那么window.a的值是从哪里得来得呢,全局搜索后 window.a ,发现在自身页面得js中有定义。
嘿嘿,正道得光………………


image.png (34.35 KB, 下载次数: 0)
下载附件
2022-12-13 20:54 上传

第一个就在第一行,但是这一行也是超级长得,浏览器自带得格式化不管用,怎么操作不用我说了吧,嘿嘿,刚安利得工具。


image.png (18.22 KB, 下载次数: 1)
下载附件
2022-12-13 21:00 上传

看到了windows.a  但是貌似是乱码,控制台一下,window.a


image.png (73.34 KB, 下载次数: 1)
下载附件
2022-12-13 21:06 上传

也是存在各种各样得符号,监控一次此时得windows.b,


image.png (13.47 KB, 下载次数: 1)
下载附件
2022-12-13 21:26 上传

值越来越多了,哈哈哈,正道得光又要来了……
不仅仅在第一页找到了,window.a 连window.c 等等参与运算的,全部都找到了。


image.png (15.1 KB, 下载次数: 1)
下载附件
2022-12-13 21:29 上传

感觉自己离真相越来越近了。


image.png (12.84 KB, 下载次数: 2)
下载附件
2022-12-13 21:35 上传



image.png (21.58 KB, 下载次数: 2)
下载附件
2022-12-13 21:36 上传

在关键函数的下一行下断点,放开跑到断点之前,我们需要的m的值已经找到了。


image.png (42.17 KB, 下载次数: 1)
下载附件
2022-12-13 21:38 上传

此时我们也已经获得了window.b的全部值。
在我们解密后的关键函数中,看到window.b 有个atob ,百度一下
  • atob() //ASCII to Base64
  • btoa() //Base64 to ASCII
    atob() 函数能够解码通过base-64编码的字符串数据。相反地,btoa() 函数能够从二进制数据“字符串”创建一个base-64编码的ASCII字符串。
    反正不懂就找百度,控制到运行 atob(windows['b'])


    image.png (108.83 KB, 下载次数: 1)
    下载附件
    2022-12-13 21:51 上传

    得到了另外一串js代码,观察发现貌似是md5加密的,放进wt里面跑一下(WT是个js调试工具,貌似也是吾爱大神弄出来的,在这里致敬一下,我等匹夫只能用下别人的工具了,做个工具小子吧)。
    还记得那个孤独的箭头吗 ,对的,window['f']哪里。


    image.png (16.65 KB, 下载次数: 1)
    下载附件
    2022-12-13 21:57 上传

    至此我们终于找到了,真正的加密代码。
    [JavaScript] 纯文本查看 复制代码var hexcase = 0;
    var b64pad = "";
    var chrsz = 16;
    function hex_md5(a) {
        return binl2hex(core_md5(str2binl(a), a.length * chrsz))
    }
    function b64_md5(a) {
        return binl2b64(core_md5(str2binl(a), a.length * chrsz))
    }
    function str_md5(a) {
        return binl2str(core_md5(str2binl(a), a.length * chrsz))
    }
    function hex_hmac_md5(a, b) {
        return binl2hex(core_hmac_md5(a, b))
    }
    function b64_hmac_md5(a, b) {
        return binl2b64(core_hmac_md5(a, b))
    }
    function str_hmac_md5(a, b) {
        return binl2str(core_hmac_md5(a, b))
    }
    function md5_vm_test() {
        return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"
    }
    function core_md5(p, k) {
        p[k >> 5] |= 128 >> 9)  16) {
            e = core_md5(e, c.length * chrsz)
        }
        var a = Array(16),
            d = Array(16);
        for (var b = 0; b > 16) + (d >> 16) + (c >> 16);
        return (b >> (32 - b))
    }
    function str2binl(d) {
        var c = Array();
        var a = (1 > 5] |= (d.charCodeAt(b / chrsz) & a) > 5] >>> (b % 32)) & a)
        }
        return d
    }
    function binl2hex(c) {
        var b = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
        var d = "";
        for (var a = 0; a > 2] >> ((a % 4) * 8 + 4)) & 15) + b.charAt((c[a >> 2] >> ((a % 4) * 8)) & 15)
        }
        return d
    }
    function binl2b64(d) {
        var c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var f = "";
        for (var b = 0; b > 2] >> 8 * (b % 4)) & 255) > 2] >> 8 * ((b + 1) % 4)) & 255) > 2] >> 8 * ((b + 2) % 4)) & 255);
            for (var a = 0; a  d.length * 32) {
                    f += b64pad
                } else {
                    f += c.charAt((e >> 6 * (3 - a)) & 63)
                }
            }
        }
        return f
    };
    验证一下是否正确


    image.png (15.27 KB, 下载次数: 1)
    下载附件
    2022-12-13 22:04 上传



    image.png (20.48 KB, 下载次数: 1)
    下载附件
    2022-12-13 22:06 上传

    哦吼,是一致的,那么说明,我们找的的加密函数是正确的,挖哈哈哈哈哈!!
    四、关于算法
                算法也是挺简单的,
                1.  首先生成一个时间戳
                2.  用hex_md5()函数加密时间戳,
                3.  用时间戳除以1000 得到后面的值,
    别问我为什么指导的,下一句就是,哈哈哈。


    image.png (40.61 KB, 下载次数: 2)
    下载附件
    2022-12-13 22:14 上传

    具体的就不写了哈,后续有时间在写python的实现。发现写文章还挺浪费时间,但是还是想把这些分享出来,给像我一样的小白避坑!!!

    航空, 机场

  • jgjackson   

    我才是真的小白,抄作业都抄得磕磕绊绊。交上作业[Python] 纯文本查看 复制代码
    import time
    import execjs
    import requests
    js_code = 'var hexcase=0;var b64pad="";var chrsz=16;function hex_md5(a){return binl2hex(core_md5(str2binl(a),a.length*chrsz))}function b64_md5(a){return binl2b64(core_md5(str2binl(a),a.length*chrsz))}function str_md5(a){return binl2str(core_md5(str2binl(a),a.length*chrsz))}function hex_hmac_md5(a,b){return binl2hex(core_hmac_md5(a,b))}function b64_hmac_md5(a,b){return binl2b64(core_hmac_md5(a,b))}function str_hmac_md5(a,b){return binl2str(core_hmac_md5(a,b))}function md5_vm_test(){return hex_md5("abc")=="900150983cd24fb0d6963f7d28e17f72"}function core_md5(p,k){p[k>>5]|=128>>9)16){e=core_md5(e,c.length*chrsz)}var a=Array(16),d=Array(16);for(var b=0;b>16)+(d>>16)+(c>>16);return(b>(32-b))}function str2binl(d){var c=Array();var a=(1>5]|=(d.charCodeAt(b/chrsz)&a)>5]>>>(b%32))&a)}return d}function binl2hex(c){var b=hexcase?"0123456789ABCDEF":"0123456789abcdef";var d="";for(var a=0;a>2]>>((a%4)*8+4))&15)+b.charAt((c[a>>2]>>((a%4)*8))&15)}return d}function binl2b64(d){var c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var f="";for(var b=0;b>2]>>8*(b%4))&255)>2]>>8*((b+1)%4))&255)>2]>>8*((b+2)%4))&255);for(var a=0;ad.length*32){f+=b64pad}else{f+=c.charAt((e>>6*(3-a))&63)}}}return f};'
    if __name__ == '__main__':
        total = 0
        count = 0
        for i in range(1, 6):
            timestamp = int(time.time()) * 1000 + 100000000
            # 通过compile命令转成一个js对象
            js = execjs.compile(js_code)
            # 调用function ==> 调用的方法名, 参数1  参数2 ...
            window_f = js.call('hex_md5', str(timestamp))
            m = window_f + "丨" + str(int(timestamp / 1000))
            data = {"m": m, "page": i}
            url = f"https://match.yuanrenxue.cn/api/match/1"
            print(url)
            response_json = requests.get(url=url, params=data).json()
            print(response_json)
            content = response_json['data']
            for a in content:
                total = a['value'] + total
                count = 1 + count
        average = total / count
        print(average)
    cainfish
    OP
      


    看床走不动路 发表于 2022-12-17 15:00
    感谢分享!
    直接在这一步“直接在第二行除邮件编辑断点  值填写false,过掉debugger”卡住不动如山{:301_1 ...

    我刚才特地测试了一下,不会卡啊,你看下你的浏览器,最好ctrl+shift+N,创建一个无痕模式的浏览器,这样浏览器不加载其他插件,可能就不会卡了。
    tongyan   

    感谢楼主分享
    ghx230011   

    厉害,厉害,真棒~我就是学不会
    cainfish
    OP
      

    其实这里有个误区,那个关键解密函数return 的是个空值,真正有用的是atob(window.b),并且window。b 页面加载完之后,就能atob了
    qq11xx   

    感谢分享
    cainfish
    OP
      

    是不是大神太多了,没人看。嘎嘎,看来要练习技术了,写点牛逼的!
    0755sz   

    谢谢楼主分享
    tpl633   

    牛逼,看得头大,哈哈
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部