rogerxavier 发表于 2024-11-22 15:15:54

哥哥救命,这个sign加密是wasm的怎么破

先上代码

```
// ==UserScript==
// @name         solcat
// @namespace    http://tampermonkey.net/
// @version      0.1
// @descriptionSimulate a POST request to the Solcat API
// @author       Your Name
// @match      https://solcat.game/*
// @match      https://api.solcat.game/*
// @grant      GM_xmlhttpRequest
// @grant      unsafeWindow
// @run-at       document-start
// @connect      api.solcat.game
// ==/UserScript==

const payload = {
      event: "update",
      score: 204,
      coins: 80,
      gameSpeed: 1.112620234488441,
      usingResurrectionPowerUp: 0
    };
(function() {
    'use strict';

    // 保存原始的fetch函数
    let oldFetch = window.fetch;
   // 示例调用
   

    // 劫持fetch函数
    function hookFetch(...args) {
      return new Promise((resolve, reject) => {
            // 检查请求的URL是否匹配
            if (args.length > 0) {
                let url = args instanceof Request ? args.url : args;
                console.log("触发了fetch请求:", url);

               
                //检测是否是get score fetch
                if(url === 'https://api.solcat.game/v1/game/'+unsafeWindow.sessionId){
                  console.log('获取到get score,下面打印参数');
                  console.log(args);
                  console.log(args.headers);
                  debugger;
                  // 调用函数
                  sendGameUpdateRequest(payload,args.headers);
                  // 不调用oldFetch,直接resolve
                  resolve(new Response(null, { status: 200, statusText: 'OK', url })); // 或者根据需要构造一个假的响应

                }

                // 检查是否有onProgress回调
                if (args && args.onProgress) {
                  console.log("检测到onProgress回调");
                }
            }

            // 调用原始的fetch函数
            oldFetch.apply(window, args).then((response) => {
                // 打印响应的URL
                console.log("响应来自:", response.url);
               

                // 克隆响应对象以便可以多次读取
                let clonedResponse = response.clone();

                // 检查响应是否可读(状态码200-299)
                if (response.ok) {
                  clonedResponse.json().then((result) => {
                        console.log("返回数据:", result);
                        // 检查返回数据中是否有sessionId
                        if (result.data && result.data.sessionId) {
                            // 将sessionId记录到window对象下
                            unsafeWindow.sessionId = result.data.sessionId; // 记录sessionId
                            console.log("已记录sessionId:", unsafeWindow.sessionId);
                        }


                  }).catch((error) => {
                        console.log("解析JSON失败:", error);
                  });
                }
                // 将原始响应传递给resolve
                resolve(response);
               
            }).catch((error) => {
                // 将错误传递给reject
                console.log("fetch请求失败:", error);
                reject(error);
            });

      });
    }

    // 替换全局的fetch函数
    unsafeWindow.fetch = hookFetch; // 使用unsafeWindow确保在页面上下文中执行


    function sendGameUpdateRequest(payload,headers) {
      const url = "https://api.solcat.game/v1/game/"+unsafeWindow.sessionId;

      GM_xmlhttpRequest({
            method: "POST",
            url: url,
            headers: headers,
            data: JSON.stringify(payload),
            onload: function(response) {
                if (response.status === 200) {
                  const responseData = JSON.parse(response.responseText);
                  console.log("伪造getscore Response Data:", responseData);
                } else {
                  console.log("伪造getscore Request failed with status:", response.status);
                }
            },
            onerror: function(err) {
                console.log("Request error:", err);
            }
      });
    }

})();
```

















这是一个solcat的游戏(类似神庙逃亡)的hook代码,每隔一段时间拾取金币会向v1/game/+sessionid的地址发送一个更新分数和金币的请求,类似这样的payload=》
```
{
    "event": "update",
    "score": 38,
    "coins": 4,
    "gameSpeed": 1.112620234489441,
    "usingResurrectionPowerUp": 0
}
```
,通过上述代码hook发现每次update的时候请求头中的sign都会变,不更新sign就会403,追踪到



```
function _JS_WebRequest_SetRequestHeader(requestId, header, value) {
            var requestOptions = wr.requests;
            if (!requestOptions) {
                return
            }
            var _header = UTF8ToString(header);
            var _value = UTF8ToString(value);
            requestOptions.init.headers = _value
      }
```



这个函数似乎是修改header中的sign的,但是看调用栈sign的算法好像和wasm有关 ,            
```
"df": _JS_WebRequest_SetRequestHeader,   =》 framework.js中
```
```
df   call $a.df,   =》 wasm文件中
```

哥哥这个要怎么fetch这个wasm文件https://solcat.game/pc_v_4/Build/wasm来还原sign的算法呀

李恒道 发表于 2024-11-22 18:06:08

wasm的目前基本只是靠模拟
可以侵入网页的特定部分来获得计算函数
直接投数据得签名就好

rogerxavier 发表于 2024-11-22 18:50:39

可是哥哥这个算法好像是访问webassembly的内存视图HEAPU8,从里面获取的sign的信息,这个要怎么访问hook呀

李恒道 发表于 2024-11-23 01:32:21

rogerxavier 发表于 2024-11-22 18:50
可是哥哥这个算法好像是访问webassembly的内存视图HEAPU8,从里面获取的sign的信息,这个要怎么访问hook呀
...

明天我有空看一下
页: [1]
查看完整版本: 哥哥救命,这个sign加密是wasm的怎么破