├── .gitignore ├── .vscode ├── extensions.json ├── global.code-snippets └── settings.json ├── README.md ├── __init__.py ├── configs ├── address_13080712_arm.json ├── address_13080812_arm.json ├── address_13080813_arm.json ├── address_13080911_arm.json └── address_13080a10_arm.json ├── main.py ├── requirements.txt ├── scripts └── hook.js └── utils ├── __init__.py ├── banner.py ├── colors.py ├── commons.py └── wechatutils.py /.gitignore: -------------------------------------------------------------------------------- 1 | frida-example 2 | .DS_Store 3 | __pycache__ 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | // my extensions, ofc :P 4 | "antfu.browse-lite", 5 | "antfu.iconify", 6 | "antfu.slidev", 7 | "antfu.unocss", 8 | "antfu.vite", 9 | "antfu.where-am-i", 10 | "antfu.open-in-github-button", 11 | "lokalise.i18n-ally", 12 | 13 | // themes & icons 14 | "antfu.icons-carbon", 15 | "antfu.theme-vitesse", 16 | "file-icons.file-icons", 17 | "sainnhe.gruvbox-material", 18 | 19 | // life savers! 20 | "dbaeumer.vscode-eslint", 21 | "Vue.volar", 22 | "GitHub.copilot", 23 | "usernamehw.errorlens", 24 | "streetsidesoftware.code-spell-checker", 25 | 26 | // up to you 27 | "eamodio.gitlens", 28 | "EditorConfig.EditorConfig", 29 | "github.vscode-github-actions", 30 | "GitHub.vscode-pull-request-github", 31 | "johnsoncodehk.vscode-tsconfig-helper", 32 | "mpontus.tab-cycle", 33 | "naumovs.color-highlight", 34 | "WakaTime.vscode-wakatime", 35 | "znck.grammarly" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /.vscode/global.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "import": { 3 | "scope": "javascript,typescript", 4 | "prefix": "im", 5 | "body": [ 6 | "import { $1 } from '$2';" 7 | ], 8 | "description": "Import a module" 9 | }, 10 | "export-all": { 11 | "scope": "javascript,typescript", 12 | "prefix": "ex", 13 | "body": [ 14 | "export * from '$2';" 15 | ], 16 | "description": "Export a module" 17 | }, 18 | "vue-script-setup": { 19 | "scope": "vue", 20 | "prefix": "", 23 | "const props = defineProps<{", 24 | " modelValue?: boolean,", 25 | "}>()", 26 | "$1", 27 | "", 28 | "", 29 | "", 34 | ] 35 | }, 36 | "vue-template-ref": { 37 | "scope": "javascript,typescript,vue", 38 | "prefix": "tref", 39 | "body": [ 40 | "const ${1:el} = shallowRef()", 41 | ] 42 | }, 43 | "vue-computed": { 44 | "scope": "javascript,typescript,vue", 45 | "prefix": "com", 46 | "body": [ 47 | "computed(() => { $1 })" 48 | ] 49 | }, 50 | "vue-watch-effect": { 51 | "scope": "javascript,typescript,vue", 52 | "prefix": "watchE", 53 | "body": [ 54 | "watchEffect(() => {", 55 | " $1", 56 | "})" 57 | ] 58 | }, 59 | "if-vitest": { 60 | "scope": "javascript,typescript", 61 | "prefix": "ifv", 62 | "body": [ 63 | "if (import.meta.vitest) {", 64 | " const { describe, it, expect } = import.meta.vitest", 65 | " ${1}", 66 | "}" 67 | ] 68 | }, 69 | "markdown-api-table": { 70 | "scope": "markdown", 71 | "prefix": "table", 72 | "body": [ 73 | "", 74 | "", 75 | "", 82 | "", 89 | "", 90 | "
", 76 | "", 77 | "### API", 78 | "", 79 | "Description", 80 | "", 81 | "
", 83 | "", 84 | "```ts", 85 | "// code block", 86 | "```", 87 | "", 88 | "
", 91 | ], 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // =========extension=========// 3 | 4 | 5 | // ========== Visuals ========== 6 | "editor.cursorBlinking":"smooth", 7 | "editor.cursorSmoothCaretAnimation":"on", 8 | "files.autoSave": "onFocusChange", 9 | "editor.fontFamily": "Input Mono, monospace", 10 | "editor.fontSize": 15, 11 | "editor.guides.bracketPairs": true, 12 | "editor.guides.bracketPairsHorizontal":true, 13 | "search.collapseResults": "auto", 14 | "editor.hover.delay":0, 15 | "editor.lineNumbers": "interval", 16 | "editor.renderWhitespace": "boundary", 17 | "editor.bracketPairColorization.independentColorPoolPerBracketType": true, 18 | "editor.columnSelection": true, 19 | "editor.padding.top":2, 20 | "editor.smoothScrolling":true, 21 | "editor.showFoldingControls":"always", 22 | "window.autoDetectColorScheme": true, 23 | "workbench.colorTheme": "Vitesse Light", 24 | "workbench.editor.tabActionLocation": "left", 25 | "workbench.fontAliasing": "antialiased", 26 | "workbench.iconTheme": "catppuccin-latte", 27 | "workbench.list.smoothScrolling": true, 28 | "workbench.preferredDarkColorTheme": "Vitesse Dark", 29 | "workbench.preferredLightColorTheme": "Vitesse Light", 30 | "workbench.productIconTheme": "icons-carbon", 31 | "workbench.sideBar.location": "left", 32 | "workbench.startupEditor": "newUntitledFile", 33 | "workbench.tree.expandMode": "singleClick", 34 | "workbench.tree.indent": 10, 35 | "search.showLineNumbers": true, 36 | "search.seedOnFocus": true, 37 | "workbench.quickOpen.preserveInput": true, 38 | 39 | // ========== Editor ========== 40 | "diffEditor.renderSideBySide": false, 41 | "debug.onTaskErrors": "debugAnyway", 42 | "diffEditor.ignoreTrimWhitespace": false, 43 | "editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\·\",.<>/?", 44 | "editor.find.addExtraSpaceOnTop": false, 45 | 46 | "editor.find.seedSearchStringFromSelection":"never", 47 | "editor.inlineSuggest.enabled": true, 48 | "editor.multiCursorModifier": "ctrlCmd", 49 | "editor.suggestSelection": "recentlyUsed", 50 | "editor.tabSize": 2, 51 | "editor.unicodeHighlight.invisibleCharacters": false, 52 | "editor.stickyScroll.enabled": true, 53 | "editor.hover.sticky": true, 54 | "editor.snippetSuggestions": "top", 55 | 56 | "editor.codeActionsOnSave": { 57 | "source.fixAll": "never", 58 | "source.fixAll.eslint": "explicit", 59 | "source.organizeImports": "never" 60 | }, 61 | "explorer.confirmDelete": false, 62 | "explorer.confirmDragAndDrop": false, 63 | "files.eol": "\n", 64 | "files.insertFinalNewline": true, 65 | "files.simpleDialog.enable": true, 66 | "git.autofetch": true, 67 | "git.confirmSync": false, 68 | "git.enableSmartCommit": true, 69 | "git.untrackedChanges": "separate", 70 | "scm.diffDecorationsGutterWidth": 2, 71 | "terminal.integrated.cursorBlinking": true, 72 | "terminal.integrated.cursorStyle": "line", 73 | "terminal.integrated.fontWeight": "300", 74 | "terminal.integrated.persistentSessionReviveProcess": "never", 75 | "terminal.integrated.tabs.enabled": true, 76 | "workbench.editor.closeOnFileDelete": true, 77 | "workbench.editor.highlightModifiedTabs": true, 78 | "workbench.editor.limit.enabled": true, 79 | "workbench.editor.limit.perEditorGroup": true, 80 | "workbench.editor.limit.value": 5, 81 | "search.exclude": { 82 | "**/*.snap": true, 83 | "**/*.svg": true, 84 | "**/.git": true, 85 | "**/.github": false, 86 | "**/.nuxt": true, 87 | "**/.output": true, 88 | "**/.pnpm": true, 89 | "**/.vscode": true, 90 | "**/.yarn": true, 91 | "**/assets": true, 92 | "**/bower_components": true, 93 | "**/dist/**": true, 94 | "**/logs": true, 95 | "**/node_modules": true, 96 | "**/out/**": true, 97 | "**/package-lock.json": true, 98 | "**/pnpm-lock.yaml": true, 99 | "**/public": true, 100 | "**/temp": true, 101 | "**/yarn.lock": true, 102 | "**/CHANGELOG*": true, 103 | "**/LICENSE*": true, 104 | }, 105 | 106 | 107 | //=====commands ===// 108 | "workbench.commandPalette.experimental.suggestCommands": true, 109 | "workbench.commandPalette.history": 50, 110 | "workbench.commandPalette.preserveInput": true, 111 | "workbench.reduceMotion": "auto", 112 | 113 | "search.useParentIgnoreFiles": true, 114 | 115 | 116 | // ========== Global Level Config, needs to put in User Settings ========== 117 | "window.dialogStyle": "custom", 118 | "window.nativeTabs": true, // this is great, macOS only 119 | "window.title": "${rootName}", // this make tabs more readable 120 | "window.titleBarStyle": "custom", 121 | "editor.defaultFormatter": "esbenp.prettier-vscode", 122 | "extensions.autoUpdate": "onlyEnabledExtensions", 123 | 124 | // ========== Extension configs ========== 125 | "emmet.showSuggestionsAsSnippets": true, 126 | "emmet.triggerExpansionOnTab": false, 127 | "errorLens.enabledDiagnosticLevels": [ 128 | "warning", 129 | "error" 130 | ], 131 | "errorLens.excludeBySource": [ 132 | "cSpell", 133 | "Grammarly", 134 | "eslint" 135 | ], 136 | 137 | // ESLint config: https://github.com/antfu/eslint-config 138 | "eslint.codeAction.showDocumentation": { 139 | "enable": true 140 | }, 141 | "eslint.quiet": true, 142 | // Silent the stylistic rules in you IDE, but still auto fix them 143 | "eslint.rules.customizations": [ 144 | { "rule": "style/*", "severity": "off" }, 145 | { "rule": "format/*", "severity": "off" }, 146 | { "rule": "*-indent", "severity": "off" }, 147 | { "rule": "*-spacing", "severity": "off" }, 148 | { "rule": "*-spaces", "severity": "off" }, 149 | { "rule": "*-order", "severity": "off" }, 150 | { "rule": "*-dangle", "severity": "off" }, 151 | { "rule": "*-newline", "severity": "off" }, 152 | { "rule": "*quotes", "severity": "off" }, 153 | { "rule": "*semi", "severity": "off" } 154 | ], 155 | "eslint.validate": [ 156 | "javascript", 157 | "javascriptreact", 158 | "typescript", 159 | "typescriptreact", 160 | "vue", 161 | "html", 162 | "markdown", 163 | "json", 164 | "jsonc", 165 | "yaml", 166 | "toml" 167 | ], 168 | 169 | "github.copilot.enable": { 170 | "*": true, 171 | "markdown": true, 172 | "plaintext": false, 173 | }, 174 | "cSpell.allowCompoundWords": true, 175 | "cSpell.language": "en,en-US", 176 | "css.lint.hexColorLength": "ignore", 177 | "githubIssues.workingIssueFormatScm": "#${issueNumberLabel}", 178 | "githubPullRequests.fileListLayout": "tree", 179 | "gitlens.codeLens.authors.enabled": false, 180 | "gitlens.codeLens.enabled": false, 181 | "gitlens.codeLens.recentChange.enabled": false, 182 | "gitlens.menus": { 183 | "editor": { 184 | "blame": false, 185 | "clipboard": true, 186 | "compare": true, 187 | "history": false, 188 | "remote": false 189 | }, 190 | "editorGroup": { 191 | "blame": true, 192 | "compare": false 193 | }, 194 | "editorTab": { 195 | "clipboard": true, 196 | "compare": true, 197 | "history": true, 198 | "remote": true 199 | }, 200 | "explorer": { 201 | "clipboard": true, 202 | "compare": true, 203 | "history": true, 204 | "remote": true 205 | }, 206 | "scm": { 207 | "authors": true 208 | }, 209 | "scmGroup": { 210 | "compare": true, 211 | "openClose": true, 212 | "stash": true 213 | }, 214 | "scmGroupInline": { 215 | "stash": true 216 | }, 217 | "scmItem": { 218 | "clipboard": true, 219 | "compare": true, 220 | "history": true, 221 | "remote": false, 222 | "stash": true 223 | } 224 | }, 225 | "i18n-ally.autoDetection": false, 226 | "i18n-ally.displayLanguage": "en", 227 | "i18n-ally.ignoredLocales": [], 228 | "iconify.annotations": true, 229 | "iconify.inplace": true, 230 | "svg.preview.mode": "svg", 231 | 232 | // I only use Prettier for manually formatting 233 | "prettier.enable": false, 234 | "prettier.printWidth": 200, 235 | "prettier.semi": false, 236 | "prettier.singleQuote": true, 237 | 238 | // ========== File Nesting ========== 239 | // this might not be up to date with the repo, please check yourself 240 | // https://github.com/antfu/vscode-file-nesting-config 241 | "explorer.fileNesting.enabled": true, 242 | "explorer.fileNesting.expand": false, 243 | "explorer.fileNesting.patterns": { 244 | "*.asax": "$(capture).*.cs, $(capture).*.vb", 245 | "*.ascx": "$(capture).*.cs, $(capture).*.vb", 246 | "*.ashx": "$(capture).*.cs, $(capture).*.vb", 247 | "*.aspx": "$(capture).*.cs, $(capture).*.vb", 248 | "*.bloc.dart": "$(capture).event.dart, $(capture).state.dart", 249 | "*.c": "$(capture).h", 250 | "*.cc": "$(capture).hpp, $(capture).h, $(capture).hxx", 251 | "*.cjs": "$(capture).cjs.map, $(capture).*.cjs, $(capture)_*.cjs", 252 | "*.component.ts": "$(capture).component.html, $(capture).component.spec.ts, $(capture).component.css, $(capture).component.scss, $(capture).component.sass, $(capture).component.less", 253 | "*.cpp": "$(capture).hpp, $(capture).h, $(capture).hxx", 254 | "*.cs": "$(capture).*.cs", 255 | "*.cshtml": "$(capture).cshtml.cs", 256 | "*.csproj": "*.config, *proj.user, appsettings.*, bundleconfig.json", 257 | "*.css": "$(capture).css.map, $(capture).*.css", 258 | "*.cxx": "$(capture).hpp, $(capture).h, $(capture).hxx", 259 | "*.dart": "$(capture).freezed.dart, $(capture).g.dart", 260 | "*.ex": "$(capture).html.eex, $(capture).html.heex, $(capture).html.leex", 261 | "*.go": "$(capture)_test.go", 262 | "*.java": "$(capture).class", 263 | "*.js": "$(capture).js.map, $(capture).*.js, $(capture)_*.js", 264 | "*.jsx": "$(capture).js, $(capture).*.jsx, $(capture)_*.js, $(capture)_*.jsx", 265 | "*.master": "$(capture).*.cs, $(capture).*.vb", 266 | "*.mjs": "$(capture).mjs.map, $(capture).*.mjs, $(capture)_*.mjs", 267 | "*.module.ts": "$(capture).resolver.ts, $(capture).controller.ts, $(capture).service.ts", 268 | "*.pubxml": "$(capture).pubxml.user", 269 | "*.resx": "$(capture).*.resx, $(capture).designer.cs, $(capture).designer.vb", 270 | "*.tex": "$(capture).acn, $(capture).acr, $(capture).alg, $(capture).aux, $(capture).bbl, $(capture).blg, $(capture).fdb_latexmk, $(capture).fls, $(capture).glg, $(capture).glo, $(capture).gls, $(capture).idx, $(capture).ind, $(capture).ist, $(capture).lof, $(capture).log, $(capture).lot, $(capture).out, $(capture).pdf, $(capture).synctex.gz, $(capture).toc, $(capture).xdv", 271 | "*.ts": "$(capture).js, $(capture).d.ts.map, $(capture).*.ts, $(capture)_*.js, $(capture)_*.ts", 272 | "*.tsx": "$(capture).ts, $(capture).*.tsx, $(capture)_*.ts, $(capture)_*.tsx", 273 | "*.vbproj": "*.config, *proj.user, appsettings.*, bundleconfig.json", 274 | "*.vue": "$(capture).*.ts, $(capture).*.js, $(capture).story.vue", 275 | "*.xaml": "$(capture).xaml.cs", 276 | "+layout.svelte": "+layout.ts,+layout.ts,+layout.js,+layout.server.ts,+layout.server.js,+layout.gql", 277 | "+page.svelte": "+page.server.ts,+page.server.js,+page.ts,+page.js,+page.gql", 278 | ".clang-tidy": ".clang-format, .clangd, compile_commands.json", 279 | ".env": "*.env, .env.*, .envrc, env.d.ts", 280 | ".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*", 281 | ".project": ".classpath", 282 | "//": "Last update at 4/29/2023, 2:04:58 PM", 283 | "BUILD.bazel": "*.bzl, *.bazel, *.bazelrc, bazel.rc, .bazelignore, .bazelproject, WORKSPACE", 284 | "CMakeLists.txt": "*.cmake, *.cmake.in, .cmake-format.yaml, CMakePresets.json", 285 | "I*.cs": "$(capture).cs", 286 | "artisan": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, server.php, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, webpack.mix.js, windi.config.*", 287 | "astro.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 288 | "cargo.toml": ".clippy.toml, .rustfmt.toml, cargo.lock, clippy.toml, cross.toml, rust-toolchain.toml, rustfmt.toml", 289 | "composer.json": ".php*.cache, composer.lock, phpunit.xml*, psalm*.xml", 290 | "default.nix": "shell.nix", 291 | "deno.json*": "*.env, .env.*, .envrc, api-extractor.json, deno.lock, env.d.ts, import-map.json, import_map.json, jsconfig.*, tsconfig.*, tsdoc.*", 292 | "dockerfile": ".dockerignore, docker-compose.*, dockerfile*", 293 | "flake.nix": "flake.lock", 294 | "gatsby-config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, gatsby-browser.*, gatsby-node.*, gatsby-ssr.*, gatsby-transformer.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 295 | "gemfile": ".ruby-version, gemfile.lock", 296 | "go.mod": ".air*, go.sum", 297 | "go.work": "go.work.sum", 298 | "mix.exs": ".credo.exs, .dialyzer_ignore.exs, .formatter.exs, .iex.exs, .tool-versions, mix.lock", 299 | "next.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, next-env.d.ts, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 300 | "nuxt.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 301 | "package.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*", 302 | "pubspec.yaml": ".metadata, .packages, all_lint_rules.yaml, analysis_options.yaml, build.yaml, pubspec.lock, pubspec_overrides.yaml", 303 | "pyproject.toml": ".pdm.toml, pdm.lock, pyproject.toml", 304 | "quasar.conf.js": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, quasar.extensions.json, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 305 | "readme*": "authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying, credits, governance.md, history.md, license*, maintainers, readme*, security.md, sponsors*", 306 | "remix.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, remix.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 307 | "rush.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*", 308 | "shims.d.ts": "*.d.ts", 309 | "svelte.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, houdini.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, mdsvex.config.js, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vite.config.*, vitest.config.*, webpack.config.*, windi.config.*", 310 | "vite.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*", 311 | "vue.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*" 312 | }, 313 | 314 | } 315 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### **注意本库只能作为学习用途, 造成的任何问题与本库开发者无关, 如侵犯到你的权益,请联系删除。** 2 | 3 | ### **注意本库只能作为学习用途, 造成的任何问题与本库开发者无关, 如侵犯到你的权益,请联系删除。** 4 | 5 | ### **注意本库只能作为学习用途, 造成的任何问题与本库开发者无关, 如侵犯到你的权益,请联系删除。** 6 | 7 | --- 8 | 9 | 10 | ## 支持版本列表 11 | 12 | > 感谢志远大佬的WeChatOpenDevTool开源、感谢JaveleyQAQ大佬、感谢Sndav大佬,小弟只是新增支持Mac arm架构,重要代码都是上述3位大佬的 13 | 14 | | MAC 微信版本 | 小程序版本 | 是否为最新版 | 是否支持内置浏览器f12 | 15 | | ---------------- | ---------- | ------------ | ------------ | 16 | | 3.8.9(28564) | 13080911 | ✅ | ✅ | 17 | | 3.8.8 | 13080813 | ❌ | ✅ | 18 | | 3.8.8 (28486) | 13080812 | ❌ | ✅ | 19 | | 3.8.7 (28245) | 13080712 | ❌ | ❌ | 20 | 21 | 22 | 23 | 24 | ## 使用方法 25 | 26 | 27 | 28 | 1. 安装python3版本 29 | 30 | 安装依赖 31 | 32 | ``` 33 | pip3 install -r requirements.txt 34 | ``` 35 | 36 | 运行✅ 37 | 38 | ``` 39 | python main.py 40 | ``` 41 | --- 42 | 43 | ### 常见问题 44 | 未适配版本,按下述方法ida自行添加,记得做了新地址帮作者补充下😊 45 | > 1、ida打开/Applications/WeChat.app/Contents/MacOS/WeChatAppEx.app/Contents/Frameworks/WeChatAppEx Framework.framework/Versions/C/WeChatAppEx Framework;注意选择arm架构打开 46 | > 47 | > 2、JsonGetBoolFunc:搜索字符串“enable_vconsole”,找到交叉引用,找到“if ( sub_25F4C88((__int64)v53, "enable_vconsole", 0LL) & 1 )”中的sub_25F4C88地址 48 | > 49 | > 3、DevToolStringAddr:搜索字符串“closeNetLog”,下面的devTools就只要找的地址 50 | > 51 | > 4、WechatWebStringAddr:搜索字符串“https://applet-debug.com/devtools/wechat_app.html” 52 | > 53 | > 5、xwebadress地址:搜索字符串“xweb-enable-inspect” 54 | 55 | 56 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | -------------------------------------------------------------------------------- /configs/address_13080712_arm.json: -------------------------------------------------------------------------------- 1 | { 2 | "DevToolStringAddr": "0x6C21AF8", 3 | "WechatWebStringAddr": "0x7258F58", 4 | "JsonGetBoolFunc": "0x25F4E3C" 5 | } -------------------------------------------------------------------------------- /configs/address_13080812_arm.json: -------------------------------------------------------------------------------- 1 | { 2 | "xwebadress": "0x23F09D8", 3 | "DevToolStringAddr": "0x6C219F8", 4 | "WechatWebStringAddr": "0x7258E58", 5 | "JsonGetBoolFunc": "0x25F4E6C" 6 | } -------------------------------------------------------------------------------- /configs/address_13080813_arm.json: -------------------------------------------------------------------------------- 1 | { 2 | "xwebadress": "0x23F07F4", 3 | "DevToolStringAddr": "0x6C218F8", 4 | "WechatWebStringAddr": "0x7258D58", 5 | "JsonGetBoolFunc": "0x25F4C88" 6 | } -------------------------------------------------------------------------------- /configs/address_13080911_arm.json: -------------------------------------------------------------------------------- 1 | { 2 | "xwebadress": "0x23F07F4", 3 | "DevToolStringAddr": "0x6C218F8", 4 | "WechatWebStringAddr": "0x7258D58", 5 | "JsonGetBoolFunc": "0x25F4C88" 6 | } -------------------------------------------------------------------------------- /configs/address_13080a10_arm.json: -------------------------------------------------------------------------------- 1 | { 2 | "DevToolStringAddr": "0x6C218EC", 3 | "WechatWebStringAddr": "0x7258D58", 4 | "JsonGetBoolFunc": "0x25F4C88" 5 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | 2 | from argparse import RawTextHelpFormatter 3 | from utils.commons import Commons 4 | from utils.banner import generate_banner 5 | from utils.colors import Color 6 | import argparse 7 | 8 | 9 | def print_colored_message(message, color): 10 | print(color + message + Color.END) 11 | 12 | def main(): 13 | HELPALL = """ 14 | 请选择要执行的方法: 15 | [+] python main.py -h 查看帮助 16 | [+] python main.py -p 指定pid 17 | 18 | """ 19 | parser = argparse.ArgumentParser(description=HELPALL, formatter_class=RawTextHelpFormatter) 20 | parser.add_argument('-p', help='指定pid',dest="pid", type=int) 21 | args = parser.parse_args() 22 | 23 | if args.pid: 24 | commons.load_wechatEx_configs_pid(args.pid) 25 | else: 26 | commons.load_wechatEx_configs() 27 | 28 | 29 | if __name__ == "__main__": 30 | generate_banner() 31 | commons = Commons() 32 | main() 33 | 34 | 35 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | frida==16.1.11 2 | psutil==5.9.7 3 | pyfiglet==1.0.2 4 | -------------------------------------------------------------------------------- /scripts/hook.js: -------------------------------------------------------------------------------- 1 | ; 2 | //获取WeChatAppEx.exe的基址 3 | var module = Process.findModuleByName('WeChatAppEx Framework') 4 | var base = module.base; 5 | // console.log("模块名称:",module.name); 6 | // console.log("模块地址:",module.base); 7 | // console.log("大小:",module.size); 8 | 9 | 10 | send("[+] WeChatAppEx 注入成功!"); 11 | send("[+] 等待小程序加载..."); 12 | 13 | 14 | // 过新版8555检测 15 | setImmediate(() => { 16 | let devToolString = base.add(address.DevToolStringAddr) 17 | // console.log("[+] devToolString = ", devToolString) 18 | let oldDevToolString = devToolString.readCString() 19 | // console.log("[+] oldDevToolString = ", oldDevToolString) 20 | 21 | if (oldDevToolString == "devTools"){ 22 | Memory.protect(devToolString, 8, 'rw-') 23 | devToolString.writeUtf8String("DevTools") 24 | Memory.protect(devToolString, 8, 'r--') 25 | // console.log("[+] newDevToolString = ", devToolString.readCString()) 26 | } 27 | 28 | let devToolsPageString = base.add(address.WechatWebStringAddr) 29 | let devToolsPageStringVal = devToolsPageString.readCString() 30 | // console.log("[+] oldDevToolsPageStringVal = ", devToolsPageStringVal) 31 | if(devToolsPageStringVal == "https://applet-debug.com/devtools/wechat_app.html"){ 32 | Memory.protect(devToolsPageString, 0x20, 'rw-') 33 | devToolsPageString.writeUtf8String("https://applet-debug.com/devtools/wechat_web.html") 34 | // console.log("[+] newDevToolsPageStringVal = ", devToolString.readCString()) 35 | Memory.protect(devToolsPageString, 0x20, 'r--') 36 | } 37 | 38 | Interceptor.attach(base.add(address.JsonGetBoolFunc), { // json_get_bool 39 | onEnter(args) { 40 | this.name = args[1].readCString() 41 | }, 42 | 43 | onLeave(retval) { 44 | if(this.name == "enable_vconsole"){ 45 | // console.log("[+] enable_vconsole detected, replace retval to true") 46 | retval.replace(1) 47 | } 48 | } 49 | }) 50 | Interceptor.attach(base.add(address.xwebadress), { // json_get_bool 51 | onLeave(retval) { 52 | // console.log("[+] enable_vconsole detected, replace retval to true") 53 | retval.replace(1) 54 | } 55 | }) 56 | }) 57 | 58 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | -------------------------------------------------------------------------------- /utils/banner.py: -------------------------------------------------------------------------------- 1 | import pyfiglet 2 | import random 3 | from utils.colors import Color 4 | 5 | def colored_print(text, color_code): 6 | print(f"{color_code}{text}"+Color.END) 7 | 8 | def generate_banner(): 9 | selected_fonts = ['standard', 'big', 'slant', 'small', 'shadow'] 10 | selected_font = random.choice(selected_fonts) 11 | font = pyfiglet.Figlet(font=selected_font) 12 | ascii_banner = font.renderText("WX DevTools") 13 | color_codes = [Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.CYAN, Color.PURPLE] 14 | selected_color = random.choice(color_codes) 15 | ascii_banner_with_author = ascii_banner.rstrip('\r\n') 16 | colored_print(ascii_banner_with_author, selected_color) -------------------------------------------------------------------------------- /utils/colors.py: -------------------------------------------------------------------------------- 1 | class Color: 2 | END = '\033[0m' 3 | RED = '\033[91m' 4 | GREEN = '\033[92m' 5 | YELLOW = '\033[93m' 6 | BLUE = '\033[94m' 7 | CYAN = '\033[96m' 8 | PURPLE = '\033[95m' 9 | -------------------------------------------------------------------------------- /utils/commons.py: -------------------------------------------------------------------------------- 1 | #commons.py //2024年3月5日23点25分 2 | 3 | from utils.colors import Color 4 | from utils.wechatutils import WechatUtils 5 | import frida,sys 6 | 7 | 8 | class Commons: 9 | def __init__(self): 10 | self.wechatutils_instance = WechatUtils() 11 | self.device = frida.get_local_device() 12 | self.process = self.device.enumerate_processes() 13 | self.pid = -1 14 | self.version_list = [] 15 | self.configs_path = "" 16 | 17 | def onMessage(self, message, data): 18 | if message['type'] == 'send': 19 | print(Color.GREEN + message['payload'], Color.END) 20 | elif message['type'] == 'error': 21 | print(Color.RED + message['stack'], Color.END) 22 | 23 | def inject_wehcatEx(self, pid, code): 24 | session = frida.attach(pid) 25 | script = session.create_script(code) 26 | script.on("message", self.onMessage) 27 | script.load() 28 | sys.stdin.read() 29 | # session.detach() 30 | 31 | 32 | def load_wechatEx_configs(self): 33 | path = self.wechatutils_instance.get_configs_path() 34 | pid, version = self.wechatutils_instance.get_wechat_pid_and_version_mac() 35 | if pid or version is not None: 36 | wehcatEx_hookcode = open(path + "../scripts/hook.js", "r", encoding="utf-8").read() 37 | wechatEx_addresses = open(path + "../configs/address_{}_arm.json".format(version)).read() 38 | wehcatEx_hookcode = "var address=" + wechatEx_addresses + wehcatEx_hookcode 39 | self.inject_wehcatEx(pid, wehcatEx_hookcode) 40 | else: 41 | self.wechatutils_instance.print_process_not_found_message() 42 | 43 | def load_wechatEx_configs_pid(self,pid): 44 | path = self.wechatutils_instance.get_configs_path() 45 | version = self.wechatutils_instance.get_wechat_version_mac() 46 | if pid or version is not None: 47 | wehcatEx_hookcode = open(path + "../scripts/hook.js", "r", encoding="utf-8").read() 48 | wechatEx_addresses = open(path + "../configs/address_{}_arm.json".format(version)).read() 49 | wehcatEx_hookcode = "var address=" + wechatEx_addresses + wehcatEx_hookcode 50 | self.inject_wehcatEx(pid, wehcatEx_hookcode) 51 | else: 52 | self.wechatutils_instance.print_process_not_found_message() 53 | -------------------------------------------------------------------------------- /utils/wechatutils.py: -------------------------------------------------------------------------------- 1 | import os,re,sys 2 | import psutil,subprocess 3 | from utils.colors import Color 4 | 5 | class WechatUtils: 6 | version_command = "ps aux | grep 'WeChatAppEx' | grep -v 'grep' | grep ' --client_version' | grep '-user-agent=' | grep -oE 'MacWechat/[0-9]+\.[0-9]+\.[0-9]+\(0x[0-9a-f]+\)' | grep -oE '0x[0-9a-f]+' | sed 's/0x//g' | head -n 1" 7 | def __init__(self): 8 | self.configs_path = self.get_configs_path() 9 | self.version_list = self.get_version_list() 10 | if sys.platform.startswith('win'): 11 | import winreg 12 | else: 13 | winreg = None 14 | 15 | # self.pid , self.version = self.get_wechat_pid_and_version() 16 | # if self.pid is None and self.version is None: 17 | # self.print_process_not_found_message() 18 | 19 | def get_configs_path(self): 20 | current_path = os.path.abspath(__file__) 21 | relative_path = '../configs/' 22 | return os.path.join(os.path.dirname(current_path), relative_path) 23 | 24 | def get_version_list(self): 25 | configs_path = self.configs_path 26 | version_list = os.listdir(configs_path) 27 | versions_list = [file.split('_')[1] for file in version_list if file.startswith('address_')] 28 | return versions_list 29 | 30 | def is_wechatEx_process(self, cmdline): 31 | process_name = "WeChatAppEx" 32 | return cmdline and process_name in cmdline[0] and "--type=" not in ' '.join(cmdline) 33 | 34 | def find_installation_path(self, program_name): 35 | try: 36 | reg_path = r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" 37 | reg_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path) 38 | 39 | for i in range(1024): 40 | try: 41 | sub_key_name = winreg.EnumKey(reg_key, i) 42 | sub_key = winreg.OpenKey(reg_key, sub_key_name) 43 | display_name = winreg.QueryValueEx(sub_key, "DisplayName")[0] 44 | # 排除企业微信 和 适配英文区域安装的WeChat 45 | if program_name == display_name or display_name == 'WeChat': 46 | install_location = winreg.QueryValueEx(sub_key, "InstallLocation")[0]+"\WeChat.exe" 47 | print(Color.GREEN + f"[+] 查找到{program_name}的安装路径是:{install_location}" + Color.END) 48 | print(Color.GREEN + f"[+] 正在尝试重启微信..."+ Color.END) 49 | return install_location 50 | except WindowsError: 51 | pass 52 | 53 | except Exception as e: 54 | print(Color.RED + f"[-] 查找安装路径时出错:{e}"+ Color.END) 55 | 56 | 57 | def extract_version_number(self, cmdline): 58 | str = ' '.join(cmdline) 59 | version_match = re.search(r'"version":(\d+)', str) 60 | return int(version_match.group(1)) if version_match else None 61 | 62 | def get_wechat_pid_and_version(self): 63 | processes = (proc.info for proc in psutil.process_iter(['pid', 'cmdline'])) 64 | wechatEx_processes = (p for p in processes if self.is_wechatEx_process(p['cmdline'])) 65 | for process in wechatEx_processes: 66 | pid = process['pid'] 67 | version = self.extract_version_number(process['cmdline']) 68 | if version in self.version_list: 69 | return pid, version 70 | 71 | return None, None 72 | 73 | def print_process_not_found_message(self): 74 | print(Color.RED + "[-] 未找到匹配版本的微信进程或微信未运行" + Color.END) 75 | 76 | def get_wechat_pid_and_version_mac(self): 77 | try: 78 | pid_command="ps aux | grep 'WeChatAppEx' | grep -v 'grep' | grep ' --client_version' | grep '-user-agent=' | awk '{print $2}' | tail -n 1" 79 | pid = subprocess.run(pid_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.replace("\n","") 80 | print(Color.GREEN + f"[+] 查找到微信的pid是:{pid}" + Color.END) 81 | version = subprocess.run(self.version_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.replace("\n","") 82 | print(Color.GREEN + f"[+] 查找到微信的版本是:{version}" + Color.END) 83 | return int(pid),version 84 | except subprocess.CalledProcessError as e: 85 | return e.stderr 86 | 87 | def get_wechat_version_mac(self): 88 | try: 89 | version = subprocess.run(self.version_command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.replace("\n","") 90 | print(Color.GREEN + f"[+] 查找到微信的版本是:{version}" + Color.END) 91 | return version 92 | except subprocess.CalledProcessError as e: 93 | return e.stderr 94 | --------------------------------------------------------------------------------