求论坛大佬指导小程序云函数逆向思路
已尝试步骤和思路
- fiddler抓包,发现有些包抓不到
- github搜索到相关工具对小程序反编译,发现代码中有
wx.cloud.callFunction wx.request 相关调用
- github搜索到相关工具对特定版本小程序开启控制台后,调试js发现数据是通过
wx.request调用得来
目前碰到几个问题
- 小程序自动升级,开启控制台调试后关闭再打开就不能开启了。只能重新安装特定版本
- 尝试使用frida进行hook,没有使用frida经验,使用ai写的frida脚本测试发现脚本正常运行,但是获取不到
wx.cloud.callFunction wx.request 相关信息
# frida_loader.py
import frida
import sys
import json
# ----- 配置 -----
TARGET_PROCESS_NAME_OR_PID = "WeChatAppEx.exe"
HOOK_SCRIPT_FILE = "hook_wx_cloud.js"
# ----- 配置结束 -----
def on_message(message, data):
"""
处理从 Frida JavaScript 脚本发送回来的消息
"""
if message['type'] == 'send':
payload = message['payload']
print(f" Message from JS: {payload.get('type', 'unknown')}")
if payload.get('type') == 'status':
print(f" Status: {payload.get('message')}")
elif payload.get('type') == 'request':
print(f" Function Name: {payload.get('functionName')}")
print(f" Timestamp: {payload.get('timestamp')}")
print(f" Request Data:\n{json.dumps(payload.get('requestData'), indent=4, ensure_ascii=False)}")
print("-" * 50)
elif payload.get('type') == 'response':
print(f" Function Name: {payload.get('functionName')}")
print(f" Timestamp: {payload.get('timestamp')}")
if payload.get('isError'):
print(f" Error Response Data:\n{json.dumps(payload.get('responseData'), indent=4, ensure_ascii=False)}")
else:
print(f" Success Response Data:\n{json.dumps(payload.get('responseData'), indent=4, ensure_ascii=False)}")
print("=" * 50)
elif message['type'] == 'error':
print(f"[!] JavaScript Error: {message.get('description')}")
print(f" Stack: {message.get('stack')}")
else:
print(f" Unknown message: {message}")
def find_target_process(device, name_or_pid):
"""
查找目标进程,如果指定的是名字,可能会有多个实例,需要用户选择。
"""
try:
# 如果是PID
if isinstance(name_or_pid, int) or name_or_pid.isdigit():
print(f" Trying to attach to PID: {name_or_pid}")
return device.attach(int(name_or_pid))
# 如果是进程名
else:
print(f" Searching for process name: {name_or_pid}")
processes = [p for p in device.enumerate_processes() if p.name.lower() == name_or_pid.lower()]
if not processes:
print(f"[!] No process found with name: {name_or_pid}")
return None
if len(processes) == 1:
print(f" Found one process: {processes[0].name} (PID: {processes[0].pid})")
return device.attach(processes[0].pid)
else:
print(f" Found multiple processes with name '{name_or_pid}':")
for i, p in enumerate(processes):
# 尝试获取命令行参数或窗口标题来帮助区分 (这部分比较依赖系统和Frida能力)
try:
print(f" [{i}] PID: {p.pid}, Name: {p.name}")
except Exception:
print(f" [{i}] PID: {p.pid}, Name: {p.name}")
while True:
try:
choice = input(" Please select the process index to attach to: ")
selected_process = processes[int(choice)]
print(f" Attaching to selected process: {selected_process.name} (PID: {selected_process.pid})")
return device.attach(selected_process.pid)
except (ValueError, IndexError):
print(" Invalid input. Please enter a valid index number.")
except KeyboardInterrupt:
print("\n Attachment cancelled by user.")
return None
except frida.ProcessNotFoundError:
print(f"[!] Process {name_or_pid} not found.")
return None
except Exception as e:
print(f"[!] Error finding/attaching to process: {e}")
return None
def main():
session = None
try:
device = frida.get_local_device() # PC端使用 local_device
print(f" Attached to local device (PC).")
# 附加到目标进程 (关键步骤)
print(f" Please open the target WeChat Mini Program now if it's not already open.")
print(f" The script will try to attach to '{TARGET_PROCESS_NAME_OR_PID}'.")
session = find_target_process(device, TARGET_PROCESS_NAME_OR_PID)
if not session:
print("[!] Failed to attach to any process. Exiting.")
return
print(" Attached successfully to target process!")
with open(HOOK_SCRIPT_FILE, "r", encoding="utf-8") as f:
js_code = f.read()
script = session.create_script(js_code)
script.on('message', on_message) # 设置消息回调函数
print(" Loading script...")
script.load()
print(" Script loaded. Waiting for cloud function calls... (Press Ctrl+C to detach)")
# 如果JS脚本中有RPC导出,可以在这里调用
# script.exports.init() # 假设JS中有 rpc.exports.init
sys.stdin.read() # 阻塞,直到用户按任意键或Ctrl+C
except frida.ProcessNotFoundError:
print(f"[!] Process {TARGET_PROCESS_NAME_OR_PID} not found.")
print(f" Ensure the WeChat PC application and the target Mini Program are running.")
print(f" Use 'frida-ps -Ua' or Task Manager to find the PID and update TARGET_PROCESS_NAME_OR_PID.")
sys.exit(1)
except frida.TransportError as e:
print(f"[!] Frida transport error: {e}.")
except KeyboardInterrupt:
print(" Detaching and exiting...")
except Exception as e:
print(f"[!] Could not attach to target. Error: {e}")
sys.exit(1)
finally:
if session:
print(" Detaching from process...")
session.detach()
print(" Detached.")
if __name__ == '__main__':
main()
// hook_wx_cloud.js
// 尝试多次,直到 wx 对象和云函数API可用
function tryHookCloudFunction() {
if (typeof wx !== 'undefined' && wx.cloud && typeof wx.cloud.callFunction === 'function') {
console.log('[Frida] Found wx.cloud.callFunction. Attempting to hook...');
const originalCallFunction = wx.cloud.callFunction;
wx.cloud.callFunction = function(options) {
console.log('[Frida] wx.cloud.callFunction CALLED');
console.log('[Frida] Request Name:', options.name);
console.log('[Frida] Request Data:', JSON.stringify(options.data, null, 2));
// 发送请求数据到 Python 控制端
send({
type: 'request',
functionName: options.name,
requestData: options.data,
timestamp: new Date().toISOString()
});
// 调用原始函数
const promise = originalCallFunction.apply(this, arguments);
// Intercept the promise resolution/rejection
promise.then(function(res) {
console.log('[Frida] wx.cloud.callFunction SUCCESS');
console.log('[Frida] Response Data:', JSON.stringify(res, null, 2));
// 发送响应数据到 Python 控制端
send({
type: 'response',
functionName: options.name,
responseData: res,
isError: false,
timestamp: new Date().toISOString()
});
}).catch(function(err) {
console.log('[Frida] wx.cloud.callFunction ERROR');
console.error('[Frida] Error Data:', JSON.stringify(err, null, 2));
// 发送错误数据到 Python 控制端
send({
type: 'response',
functionName: options.name,
responseData: err, // 或者 err.message, err.stack
isError: true,
timestamp: new Date().toISOString()
});
});
return promise;
};
console.log('[Frida] wx.cloud.callFunction hooked successfully!');
send({ type: 'status', message: 'Hooked wx.cloud.callFunction successfully!' });
} else {
console.log('[Frida] wx.cloud.callFunction not found yet or wx object not ready. Retrying in 1 second...');
setTimeout(tryHookCloudFunction, 1000); // 1秒后重试
}
}
// Frida RPC 导出,允许 Python 端调用此函数(可选,如果需要在Python端控制何时开始hook)
/*
rpc.exports = {
init: function () {
tryHookCloudFunction();
}
};
*/
// 脚本加载时立即尝试Hook
tryHookCloudFunction();
目前想不到有其他什么好的思路或者方法,请大佬们指导指导!!!