猿人学app2022-第一题

发布时间 2023-10-07 16:24:30作者: TimerZz

抓包需要hook sslpinning

// hook_ssl_pinning
function logger(message) {
  console.log(message);
  Java.perform(function () {
    var Log = Java.use("android.util.Log");
    Log.v("ssl_pinnig_bypass", message);
  });
}

Java.perform(function () {
  try {
    const x509TrustManager = Java.use("javax.net.ssl.X509TrustManager");
    const sSLContext = Java.use("javax.net.ssl.SSLContext");
    const TrustManager = Java.registerClass({
      implements: [x509TrustManager],
      methods: {
        checkClientTrusted(chain, authType) {
        },
        checkServerTrusted(chain, authType) {
        },
        getAcceptedIssuers() {
          return [];
        },
      },
      name: "cc.timer9527",
    });
    const TrustManagers = [TrustManager.$new()];
    const SSLContextInit = sSLContext.init.overload(
      "[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom");
    SSLContextInit.implementation = function (keyManager, trustManager, secureRandom) {
      SSLContextInit.call(this, keyManager, TrustManagers, secureRandom);
    };
    logger("[*][+] Hooked SSLContextInit")
  } catch (e) {
    logger("[*][-] Failed to hook SSLContextInit")
  }
})

请求app1路径可以获取数字的返回值,提交参数中的sign是需要计算的,需要拿到每次请求的sign值

jadx反编译,并搜索app1,找到相关路由的定义

右键“查找用例”,发现有两处调用了该函数

选择第一个,点进去,发现sign参数的生成函数,跟进去

 

sign方法需要一个byte数组作为参数

 

最后返回一个String类型字符串,hook这个返回值,然后拿这个返回值去请求就可以了

 frida rpc调用脚本如下。tips:由于js没有byte类型,传入sign方法的参数需要转化一下(stringToBytes函数)

//check1.js
function hookSign(str){
    let result
    let test = 0
    Java.perform(function (){
        let targetClassName = Java.use("com.yuanrenxue.match2022.security.Sign")
        let targetClassNameObj = targetClassName.$new()  
        result = targetClassNameObj.sign(stringToBytes(str))
    })
    return result
}

function stringToBytes(str) {
    var data = Java.use("java.lang.String").$new(str);
    return data.getBytes();
}

rpc.exports = {
    hooksign: hookSign
}
import frida, sys
import time
import requests


def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print('msg: ', message)
        print('test data2', data)


device = frida.get_usb_device()
# attach
session = device.attach("猿人学2022")

with open('check1.js', encoding='utf-8') as f:
    jscode = f.read()

script = session.create_script(jscode)
script.on('message', on_message)
script.load()

url = "https://appmatch.yuanrenxue.cn/app1"

headers = {
    "Accept-Language": "zh-CN,zh;q=0.8",
    "User-Agent": "Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; Nexus 6P Build/OPM1.171019.011) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
    "Cache-Control": "no-cache"
}

sum = 0
for i in range(1, 101):
    t = str(int(time.time() * 1000))
    payload = "page=" + str(i) + t
    result = script.exports_sync.hooksign(payload)
    print("sign>> ", result)
    data = {
        "page": str(i),
        "sign": result,
        "t": t,
        "token": "IKLostJxwdM%20ktruxVoZSAZsS6hiThDIkGizuHGvfScO2jmu4OaGArRxg6lZdAUl"
    }
    resp = requests.post(url=url, data=data, headers=headers)
    print(resp.json())
    for x in resp.json()["data"]:
        sum += int(x['value'].strip())
        print("tmp >>: ", sum)

print("sum is >>: ", sum)
sys.stdin.read()