8点击蓝字
关注我们
声明
本文作者:Jammny
本文字数:3404字
阅读时长:约10分钟
附件/链接:点击查看原文下载
本文属于【狼组安全社区】原创奖励计划,未经许可禁止转载
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,狼组安全团队以及文章作者不为此承担任何责任。
狼组安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经狼组安全团队允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
❝
开启 devtools 的思路来源于志远的开源项目,原项目脚本有点问题,思路也比较简单,我优化了一下脚本。但是脚本中有三个偏移地址是需要根据本地实际上的插件版本而变换的,本文聊一下这三个偏移地址是怎么找的。
Frida hook 脚本
先把优化后的脚本放出来:
import frida, sys, os
js_code = """
// 8461_x64 版本偏移地址
var address = {
"LaunchAppletBegin": "0x1B40138",
"open_devtool_plus":"0x2ECA1CD",
"wechat_web":"0x7C0D7AD"
}
// 获取 WeChatAppEx.exe 的基址
var base = Process.findModuleByName("WeChatAppEx.exe").base;
// console.log(`Base: "${base}`)
address.LaunchAppletBegin = base.add(address.LaunchAppletBegin);
address.open_devtool_plus = base.add(address.open_devtool_plus);
address.wechat_web = base.add(address.wechat_web);
function readStdString(s) {
var flag = s.add(23).readU8()
if (flag == 0x80) {
// 从堆中读取
var size = s.add(8).readUInt()
return s.readPointer().readUtf8String(size)
} else {
// 从栈中读取
return s.readUtf8String(flag)
}
}
function writeStdString(s, content) {
var flag = s.add(23).readU8()
if (flag == 0x80) {
// 从堆中写入
var orisize = s.add(8).readUInt()
if (content.length > orisize) {
throw "must below orisize!"
}
s.readPointer().writeUtf8String(content)
s.add(8).writeUInt(content.length)
} else {
// 从栈中写入
if (content.length > 22) {
throw "max 23 for stack str"
}
s.writeUtf8String(content)
s.add(23).writeU8(content.length)
}
}
// HOOK 启动配置
Interceptor.attach(address.LaunchAppletBegin, {
onEnter(args) {
send(`[HOOK] 小程序加载:${readStdString(args[1])}`)
for (var i = 0; i < 1024; i+=8) {
try {
var s = readStdString(args[2].add(i))
// console.log(`[${i}] ${s}`, )
if (s.includes('"enable_vconsole":false')){
//console.log(`[${i}] ${s}`)
s = s.replaceAll('"enable_vconsole":false', '"enable_vconsole":true')
writeStdString(args[2].add(i), s)
// console.log("已开启调试功能!")
}
} catch (a) {
// console.log(a)
}
}
}
})
// HOOK F12配置 替换原本内容
Interceptor.attach(address.open_devtool_plus, {
onEnter(args) {
this.context.rdx = address.wechat_web;
send("[success] 已还原完整调试功能!")
}
})
"""
def onMessage(message, data):
if message["type"] == 'send':
print(f"{message['payload']}")
if "success" in message['payload']:
os._exit(0)
else:
print(message)
local = frida.get_local_device()
for proc in local.enumerate_processes():
if proc.name == "WeChatAppEx.exe":
WeChatAppEx_pid = proc.pid
session = frida.attach(WeChatAppEx_pid)
print(f"[*] 现在你可以打开你想要调试的小程序")
script = session.create_script(js_code)
script.on('message', onMessage)
script.load()
sys.stdin.read()
使用此脚本需要安装 frida 环境:pip install frida
第一个偏移地址
先找到小程序的本地路径:
C:Users用户AppDataRoamingTencentWeChatXPluginPluginsRadiumWMPF
这个目录下的文件夹,数字就是对应本地小程序版本号:如果有多个版本,可以通过 任务管理器 查看目前微信正在使用的版本号是哪个,我这里使用的是 8461,如下图:接着到 WeChatAppEx.exe 路径下,拷贝一份它的副本,并在 IDA 中打开。在 IDA 里面搜关键字符串 LaunchApplet :接着进入到引用的它的代码段中去:划到这个匿名函数开始的地方,选中下面红框的地址,这个地址可以作为加载配置的起始地址:这里 IDA 起始地址为140000000,那么相对偏移地址为:0x1B40138,对应 frida 脚本中的:
var address = {
"LaunchAppletBegin": "0x1B40138", // 根据自己的版本进行修改
....
}
第二个偏移量
在 IDA 里面搜关键字符串:https://applet-debug.com/devtools/wechat_web.html,接着在拿它对应的 .rdata 资源数据段地址:147C0D7AD,偏移地址就是:0x7C0D7AD对应 frida 脚本中的:
var address = {
....
"wechat_web":"0x7C0D7AD" // 根据自己的版本进行修改
}
第三个偏移量
进入到引用 “https://applet-debug.com/devtools/wechat_web.html” 的匿名函数中去。查看伪代码中匿名函数入参 v8 原本应该对 wechat_app 的地址,需要改成 wechat_web 的地址才会开启完整版的调试。所以这里需要 hook 红框中的匿名函数,更改 v8 的地址。那么这里的 frida hook 需要进入的地址为:142ECA1CD,偏移地址:0x2ECA1CD,对应 frida 脚本中的:
var address = {
....
"open_devtool_plus":"0x2ECA1CD", // 根据自己的版本进行修改
....
}
至此,根据以上思路可以找到各个版本对应的三个偏移量地址,最后替换到 frida 脚本中即可完成一键启动调试。
作者
Jammny
假如你坚持一个月做同一件事情
那么它很快会成为你的习惯,学习亦是如此。
扫描关注公众号回复加群
和师傅们一起讨论研究~
长
按
关
注
WgpSec狼组安全团队
微信号:wgpsec
Twitter:@wgpsec
原文始发于微信公众号(WgpSec狼组安全团队):Frida + IDA 开启小程序 devtools