<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Frida on 逍遥笔记</title><link>https://blog.7qiang.com/tags/frida/</link><description>Recent content in Frida on 逍遥笔记</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>逍遥笔记</copyright><lastBuildDate>Wed, 22 Jul 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://blog.7qiang.com/tags/frida/index.xml" rel="self" type="application/rss+xml"/><item><title>Google Play 内购 CC Max 漏洞深度拆解 — 一个 Bundle.putInt 就能白嫖 $250/月的 Claude Max</title><link>https://blog.7qiang.com/posts/google-play-ccmax-proration-vulnerability-2026/</link><pubDate>Wed, 22 Jul 2026 10:00:00 +0800</pubDate><guid>https://blog.7qiang.com/posts/google-play-ccmax-proration-vulnerability-2026/</guid><description>&lt;img src="https://blog.7qiang.com/blog-cover-cyber-mask.gif" alt="Featured image of post Google Play 内购 CC Max 漏洞深度拆解 — 一个 Bundle.putInt 就能白嫖 $250/月的 Claude Max" /&gt;&lt;section class="xiaoyao-contact-card" aria-label="联系逍遥"&gt;
 &lt;img class="xiaoyao-contact-card__qr" src="https://blog.7qiang.com/contact-qr.png" width="690" height="690" loading="lazy" decoding="async" alt="逍遥微信二维码"&gt;
 &lt;div class="xiaoyao-contact-card__content"&gt;
 &lt;h3 class="xiaoyao-contact-card__title"&gt;联系逍遥&lt;/h3&gt;
 &lt;p class="xiaoyao-contact-card__description"&gt;扫码添加微信，或点击下方按钮复制联系方式。&lt;/p&gt;
 &lt;div class="xiaoyao-contact-buttons" data-contact-buttons&gt;
 &lt;button class="xiaoyao-contact-button xiaoyao-contact-button--wechat" type="button" data-copy-contact="plus6566" data-copy-label="微信号"&gt;
 &lt;span class="xiaoyao-contact-button__label"&gt;微信&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__value"&gt;plus6566&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__status" data-copy-status&gt;点击复制&lt;/span&gt;
 &lt;/button&gt;
 &lt;button class="xiaoyao-contact-button xiaoyao-contact-button--qq" type="button" data-copy-contact="826215906" data-copy-label="QQ 号"&gt;
 &lt;span class="xiaoyao-contact-button__label"&gt;QQ&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__value"&gt;826215906&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__status" data-copy-status&gt;点击复制&lt;/span&gt;
 &lt;/button&gt;
 &lt;span class="xiaoyao-contact-feedback" role="status" aria-live="polite"&gt;&lt;/span&gt;
&lt;/div&gt;

 &lt;/div&gt;
&lt;/section&gt;

&lt;p&gt;进微信群请联系博主，各位觉得文章对你有帮助的话可否打赏一些呀~&lt;/p&gt;
&lt;hr&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;⚠️ 免责声明&lt;/strong&gt;：本文仅供安全研究与技术讨论。本文描述的漏洞&lt;strong&gt;已于 2026 年 7 月被修复&lt;/strong&gt;。任何利用类似手段对正式服务进行未授权操作属违法行为，后果自负。&lt;/p&gt;
&lt;p&gt;部分思路来自 &lt;a class="link" href="https://cctest.ai" target="_blank" rel="noopener"
 &gt;cctest.ai&lt;/a&gt; 作者，在此致谢。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="0x00-背景20-的-pro250-的-max中间差了一个-hook"&gt;0x00 背景：$20 的 Pro，$250 的 Max，中间差了一个 hook
&lt;/h2&gt;&lt;p&gt;Claude 的 Android 客户端走 Google Play 内购（Google Play Billing Library）处理订阅。价格梯度大概是这样：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;方案&lt;/th&gt;
 &lt;th&gt;月费&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Pro&lt;/td&gt;
 &lt;td&gt;$20&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Max 5x&lt;/td&gt;
 &lt;td&gt;$125&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Max 20x&lt;/td&gt;
 &lt;td&gt;$250&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;正常流程：你是 Pro 用户，想升级到 Max，Google Play 会按剩余天数计算差价，立刻从你的信用卡上扣。&lt;/p&gt;
&lt;p&gt;但如果我告诉你，有个参数决定了 Google Play 对这笔&amp;quot;升级&amp;quot;收不收钱呢？&lt;/p&gt;
&lt;p&gt;而且这个参数，就是 Android Bundle 里一个普普通通的 &lt;code&gt;putInt&lt;/code&gt; 调用？&lt;/p&gt;
&lt;h2 id="0x01-prorationmodegoogle-play-里最被低估的攻击面"&gt;0x01 prorationMode：Google Play 里最被低估的攻击面
&lt;/h2&gt;&lt;p&gt;Google Play Billing Library 在处理订阅升/降级时，有个参数叫 &lt;code&gt;prorationMode&lt;/code&gt;（比例分配模式），定义在 &lt;code&gt;BillingFlowParams.SubscriptionUpdateParams&lt;/code&gt; 里。它决定了用户切换订阅方案时的扣费逻辑：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;值&lt;/th&gt;
 &lt;th&gt;常量名&lt;/th&gt;
 &lt;th&gt;行为&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY&lt;/td&gt;
 &lt;td&gt;未知&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;WITH_TIME_PRORATION&lt;/td&gt;
 &lt;td&gt;按剩余时间折算差价，&lt;strong&gt;立刻扣费&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;CHARGE_PRORATED_PRICE&lt;/td&gt;
 &lt;td&gt;按比例收取差价&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;WITHOUT_PRORATION&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;立刻升级，本周期不收费，下个周期按新价扣&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;CHARGE_FULL_PRICE&lt;/td&gt;
 &lt;td&gt;立刻全额扣费&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;6&lt;/td&gt;
 &lt;td&gt;DEFERRED&lt;/td&gt;
 &lt;td&gt;延迟到下个周期才生效&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;重点关注 &lt;code&gt;3 — WITHOUT_PRORATION&lt;/code&gt;：Google 官方文档里写得很清楚，这个模式的设计意图是&amp;quot;让用户立刻获得高级功能，但推迟扣费到下个计费周期&amp;quot;。本来是给某些业务场景用的（比如试用期升级），但如果被滥用……&lt;/p&gt;
&lt;p&gt;Claude 的客户端代码里，升级订阅时用的是模式 &lt;code&gt;1&lt;/code&gt;（WITH_TIME_PRORATION），也就是正常的按比例扣差价。它通过 &lt;code&gt;Bundle.putInt(&amp;quot;prorationMode&amp;quot;, 1)&lt;/code&gt; 把这个值传给 Google Play 的计费 Activity。&lt;/p&gt;
&lt;p&gt;这个 &lt;code&gt;Bundle.putInt&lt;/code&gt; 调用发生在客户端侧。客户端侧的东西，你懂的。&lt;/p&gt;
&lt;h2 id="0x02-攻击链frida-一条龙"&gt;0x02 攻击链：Frida 一条龙
&lt;/h2&gt;&lt;p&gt;整个攻击链其实非常简洁，所有操作都在模拟器上完成。用到的工具：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MuMu 模拟器&lt;/strong&gt;（x86_64，因为要跑 Frida server 的 x86 版本）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KernelSU&lt;/strong&gt;（MuMu 自带，用来获取 root）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frida 17.16.0&lt;/strong&gt;（动态插桩框架）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;特定版本的 Claude APK&lt;/strong&gt;（v1.260330.27，在 Uptodown 可以下到历史版本）&lt;/li&gt;
&lt;li&gt;一个能扣 $20 的美区 Google 账号&lt;/li&gt;
&lt;li&gt;家宽 IP（避免 Google 风控拦截）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;步骤拆解：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步：搭环境&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;MuMu 模拟器装好后，用它自带的 Google 安装器装上 Google 套件 + Play 商店。打开 KernelSU Manager 给 Shell 授权 root。这步没啥技术含量，MuMu 对 Google 服务兼容性比 LDPlayer 好不少。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步：准备 Claude APK&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这里有个前置问题——你不能直接从 Play 商店装 Claude。&lt;/p&gt;
&lt;p&gt;现在的 Android 应用普遍使用 App Bundle（AAB）格式发布，Play 商店下发的是 split APK：base.apk 加一堆按设备拆分的 config splits（ABI、密度、语言）。x86_64 模拟器拿到的 splits 跟 ARM 真机不一样，而且 split APK 不能直接 &lt;code&gt;adb install&lt;/code&gt; 侧载。&lt;/p&gt;
&lt;p&gt;所以需要一个&lt;strong&gt;经过修补、移除了 split 限制的完整 APK&lt;/strong&gt;。实测可用的版本是 &lt;code&gt;v1.260330.27&lt;/code&gt;，从 Uptodown 等第三方市场可以找到历史版本的完整包。关键词：“已修补 split 限制”——就是把 App Bundle 重新打包成单个 APK，绕过 Play 商店的分发限制。&lt;/p&gt;
&lt;p&gt;还有一个连锁问题：修补过的 APK 签名跟 Google Play 原版不一致（相当于 debug 签名），&lt;strong&gt;Google OAuth 登录会直接拒绝&lt;/strong&gt;——点 “Continue with Google” 没反应或者报错。解决办法很简单：用邮箱登录（Continue with email），输入 Claude 账号的邮箱和密码，完全不走 OAuth。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三步：部署 Frida&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb push frida-server-17.16.0-android-x86_64 /data/local/tmp/frida-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb shell chmod &lt;span class="m"&gt;755&lt;/span&gt; /data/local/tmp/frida-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb shell su -c &lt;span class="s2"&gt;&amp;#34;setenforce 0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb shell su -c &lt;span class="s2"&gt;&amp;#34;/data/local/tmp/frida-server -D &amp;amp;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;MuMu 有个坑：它的 ADB 端口不是标准 5555，而是 5557（多开的话 5559、5561 递增）。另外 MuMu 用 houdini 做 ARM 翻译，所以 Frida 必须用 &lt;strong&gt;attach 模式&lt;/strong&gt;，不能用 spawn 模式（&lt;code&gt;-f&lt;/code&gt; 参数），否则 houdini 翻译层直接 SIGSEGV 崩掉。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第四步：注入 Hook&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;核心的 hook 脚本其实就干了一件事——拦截 &lt;code&gt;Bundle.putInt&lt;/code&gt;，把 key 为 &lt;code&gt;prorationMode&lt;/code&gt; 的值从 1 改成 3：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Bundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;android.os.Bundle&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putInt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;java.lang.String&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;int&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;prorationMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[*] 拦截 prorationMode: &amp;#34;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; → 3 [WITHOUT_PRORATION]&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 就这一行，价值 $230/月
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意启动方式——必须先手动打开 Claude，再用 &lt;code&gt;-H&lt;/code&gt; 连接（而不是 &lt;code&gt;-U&lt;/code&gt;），因为 MuMu 的 USB 层跟标准 Android 不一样。而且 Frida 的进程名参数必须用&lt;strong&gt;显示名 &lt;code&gt;Claude&lt;/code&gt;&lt;/strong&gt;，不能用包名 &lt;code&gt;com.anthropic.claude&lt;/code&gt;——MuMu 上 &lt;code&gt;-H&lt;/code&gt; 模式下 Frida 按包名是找不到进程的，只认 app_process 里注册的显示名：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb forward tcp:27042 tcp:27042
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;frida -H 127.0.0.1:27042 Claude -l hook-replacement-mode.js
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 注意：用 com.anthropic.claude 会报 &amp;#34;unable to find process&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里还有个细节：脚本额外拦截了 &lt;code&gt;SentryNdk.loadNativeLibraries&lt;/code&gt; 和 &lt;code&gt;SentryAndroidNdk&lt;/code&gt; 的初始化方法，因为 Sentry 的 native crash 上报模块在 houdini 翻译层下也会崩。不拦截的话 App 直接闪退。&lt;/p&gt;
&lt;p&gt;除了核心的 prorationMode 拦截，脚本还 hook 了 &lt;code&gt;PurchaseReceipt&lt;/code&gt; 的构造函数，打印 &lt;code&gt;purchase_token&lt;/code&gt; 和 &lt;code&gt;organization_id&lt;/code&gt;。这个 org_id 是 Anthropic 后端用来标识组织/用户的唯一 ID（格式类似 &lt;code&gt;6a085918-8383-44e5-9538-c4c81c6e122b&lt;/code&gt;），在规模化操作时用于追踪哪个 Claude 账号绑定了哪笔 Google Play 订阅——一个 Google 账号只能给一个 Claude 账号开通订阅，org_id 就是这个映射关系的 key。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第五步：走一遍正常支付&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;hook 注入成功后（控制台会显示 &lt;code&gt;Frida Hook 注入成功!&lt;/code&gt;，App 里也会弹 Toast），正常操作：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用邮箱登录 Claude 账号（不能用 Google OAuth，原因见上）&lt;/li&gt;
&lt;li&gt;在模拟器里绑定支付卡（需要能扣 $20 的真实/虚拟信用卡）&lt;/li&gt;
&lt;li&gt;通过 Google Play 订阅 Pro（$20/月）—— 这笔钱是真扣的&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;第六步：触发升级&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pro 订阅成功后，直接在 App 里点&amp;quot;升级到 Max&amp;quot;。这时候 hook 就发挥作用了：&lt;/p&gt;
&lt;p&gt;控制台输出：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[*] 拦截 prorationMode: 1 [WITH_TIME_PRORATION] → 3 [WITHOUT_PRORATION]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同时 &lt;code&gt;PurchaseReceipt&lt;/code&gt; 的 hook 会打印出新订阅的 org_id，确认升级已经走通了 Anthropic 后端。&lt;/p&gt;
&lt;p&gt;Google Play 的计费页面会显示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;产品：Claude Max&lt;/li&gt;
&lt;li&gt;价格：$250.00/month（日区显示 JP¥42,500/month）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开始日期：2026年8月20日&lt;/strong&gt;（注意，是下个月！）&lt;/li&gt;
&lt;li&gt;“我们将于 2026年8月20日向您收取第一笔费用”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;看到了吗？因为 prorationMode 被改成了 &lt;code&gt;WITHOUT_PRORATION&lt;/code&gt;，Google Play 认为&amp;quot;当前不收费，下个计费周期再扣&amp;quot;。点击订阅，立刻升级到 Max，卡上不会多扣一分钱。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第七步：善后&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;升级成功后，去 &lt;a class="link" href="https://payments.google.com" target="_blank" rel="noopener"
 &gt;payments.google.com&lt;/a&gt; 把这个订阅的支付方式换成余额钱包（Google Play 余额一般是 0）或者一张空的虚拟卡，然后解绑原来的支付卡。&lt;/p&gt;
&lt;p&gt;下个月续费的时候，余额不够或者虚拟卡扣费失败，订阅自然过期。但这一个月的 Max 你已经用上了。&lt;/p&gt;
&lt;p&gt;$20 的成本，享受 $250 的服务。利润率 1150%。&lt;/p&gt;
&lt;p&gt;有一个规模化的硬约束：&lt;strong&gt;一个 Google 账号只能给一个 Claude 账号开通订阅&lt;/strong&gt;。想批量撸就得不断囤 Google 号——这也是为什么这条灰产链的瓶颈不在技术，而在号源。&lt;/p&gt;
&lt;h2 id="0x03-为什么这个-bug-能成立"&gt;0x03 为什么这个 bug 能成立
&lt;/h2&gt;&lt;p&gt;从技术层面分析，这个漏洞能成立需要几个条件同时满足：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. prorationMode 由客户端决定&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是最根本的问题。Google Play Billing Library 的设计是把 &lt;code&gt;prorationMode&lt;/code&gt; 作为客户端参数传递给 Google Play 的计费系统。Google Play 本身不会校验&amp;quot;这个 App 有没有资格用 WITHOUT_PRORATION 模式&amp;quot;——它无条件信任客户端传来的值。&lt;/p&gt;
&lt;p&gt;这是一个经典的&lt;strong&gt;信任边界错误&lt;/strong&gt;：把安全关键参数的决定权放在了不可信的客户端侧。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 服务端验证缺位&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Claude 的后端在收到 Google Play 的订阅回调时，主要验证的是&amp;quot;这个 purchase token 是否有效&amp;quot;和&amp;quot;订阅是否 active&amp;quot;。它不会去检查 &lt;code&gt;prorationMode&lt;/code&gt; 是什么——因为这个信息在服务端回调里根本就没有。Google Play 的 &lt;code&gt;purchases.subscriptions&lt;/code&gt; API 返回的数据里不包含当初用的是哪个 proration mode。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 历史版本 APK 的可用性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新版 Claude 可能已经做了混淆或者改变了参数传递方式，但旧版本在 Uptodown 等第三方市场永远可以下到。只要 Google Play 的 Billing API 版本还兼容，旧 APK 照样能完成订阅操作。&lt;/p&gt;
&lt;h2 id="0x04-不用-hook-的路子速刷"&gt;0x04 不用 hook 的路子：速刷
&lt;/h2&gt;&lt;p&gt;值得一提的是，prorationMode hook 并不是唯一的利用方式。圈子里还流传一种叫&amp;quot;速刷&amp;quot;的打法——不需要 Frida，不需要 hook，纯靠旧版本客户端的某些行为差异来打时间差。&lt;/p&gt;
&lt;p&gt;具体原理不在本文展开（毕竟还没被修），但核心思路类似：利用 Google Play Billing Library 旧版本在处理订阅变更时的窗口期，在扣费确认到达之前完成订阅切换。跟 prorationMode hook 相比，速刷的门槛更低（不需要 root、不需要 Frida），但成功率也更低，而且强依赖特定的历史版本 APK。&lt;/p&gt;
&lt;p&gt;这两种方法本质上攻击的是同一个面：&lt;strong&gt;Google Play 对客户端行为的过度信任&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="0x05-修复状态与后续"&gt;0x05 修复状态与后续
&lt;/h2&gt;&lt;p&gt;截至 2026 年 7 月，prorationMode hook 这个特定的攻击路径已被修复。从修复思路上猜测，可能的措施包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;客户端侧&lt;/strong&gt;：新版 Claude APK 不再使用 Bundle 明文传递 prorationMode，可能改用了加密或者服务端控制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务端侧&lt;/strong&gt;：在处理升级回调时增加了额外验证（比如检查 &lt;code&gt;linkedPurchaseToken&lt;/code&gt; 的订阅金额是否合理）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Play 侧&lt;/strong&gt;：Google 可能限制了 WITHOUT_PRORATION 模式的使用场景（需要应用显式在 Google Play Console 配置）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但说实话，&lt;strong&gt;Google Play Billing 的这个攻击面远没有被堵死&lt;/strong&gt;。&lt;code&gt;prorationMode&lt;/code&gt; 只是其中一个参数，&lt;code&gt;BillingFlowParams&lt;/code&gt; 里还有其他可操控的字段。只要&amp;quot;客户端构建支付参数 → 传给 Google Play → Google Play 无条件执行&amp;quot;这个模型不变，同类问题就会持续出现。&lt;/p&gt;
&lt;p&gt;据了解，目前仍有针对其他参数或其他 App 的类似攻击手法在流通。Google Play 内购系统的安全模型，说白了就是建立在&amp;quot;客户端可信&amp;quot;这个脆弱假设上的。&lt;/p&gt;
&lt;h2 id="0x06-技术启示"&gt;0x06 技术启示
&lt;/h2&gt;&lt;p&gt;如果你是开发者，从这个漏洞可以学到：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;永远不要信任客户端传来的支付参数&lt;/strong&gt;。即使是通过 Google Play 这种&amp;quot;可信&amp;quot;中间人，底层的 &lt;code&gt;BillingFlowParams&lt;/code&gt; 仍然是客户端构造的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务端必须独立验证订阅状态&lt;/strong&gt;。不要只检查 token 有效性，还要验证订阅的实际扣费金额（通过 &lt;code&gt;purchases.subscriptions&lt;/code&gt; 的 &lt;code&gt;priceAmountMicros&lt;/code&gt; 字段）与预期是否一致。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin APK 版本&lt;/strong&gt;。如果你依赖客户端逻辑做安全控制，服务端应该检查客户端版本号，拒绝过旧版本的请求。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果你是安全研究者，这个 case 是一个很好的&amp;quot;API 信任边界&amp;quot;研究样本。Google Play Billing Library 把自己定位成&amp;quot;安全的支付中间件&amp;quot;，但它实际上信任了太多来自客户端的输入。类似 Frida hook &lt;code&gt;Bundle.putInt&lt;/code&gt; 这种低成本的攻击手段，在整个 Android 内购生态里适用面很广。&lt;/p&gt;
&lt;hr&gt;

 &lt;blockquote&gt;
 &lt;p&gt;本文记录的是一个已修复的安全问题，旨在帮助开发者理解 Google Play 内购系统的安全边界。&lt;/p&gt;
&lt;p&gt;如果你对 Android 安全、支付系统攻防感兴趣，欢迎关注博客，后续会持续更新更多分析。&lt;/p&gt;

 &lt;/blockquote&gt;</description></item><item><title>GPT Plus 订阅漏洞深度分析 - Google Play Billing 鉴权缺失导致 0 元订阅</title><link>https://blog.7qiang.com/posts/gpt-plus-exploit-revenuecat-vulnerability/</link><pubDate>Mon, 20 Apr 2026 05:30:00 +0800</pubDate><guid>https://blog.7qiang.com/posts/gpt-plus-exploit-revenuecat-vulnerability/</guid><description>&lt;img src="https://blog.7qiang.com/blog-cover-cyber-mask.gif" alt="Featured image of post GPT Plus 订阅漏洞深度分析 - Google Play Billing 鉴权缺失导致 0 元订阅" /&gt;&lt;section class="xiaoyao-contact-card" aria-label="联系逍遥"&gt;
 &lt;img class="xiaoyao-contact-card__qr" src="https://blog.7qiang.com/contact-qr.png" width="690" height="690" loading="lazy" decoding="async" alt="逍遥微信二维码"&gt;
 &lt;div class="xiaoyao-contact-card__content"&gt;
 &lt;h3 class="xiaoyao-contact-card__title"&gt;联系逍遥&lt;/h3&gt;
 &lt;p class="xiaoyao-contact-card__description"&gt;扫码添加微信，或点击下方按钮复制联系方式。&lt;/p&gt;
 &lt;div class="xiaoyao-contact-buttons" data-contact-buttons&gt;
 &lt;button class="xiaoyao-contact-button xiaoyao-contact-button--wechat" type="button" data-copy-contact="plus6566" data-copy-label="微信号"&gt;
 &lt;span class="xiaoyao-contact-button__label"&gt;微信&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__value"&gt;plus6566&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__status" data-copy-status&gt;点击复制&lt;/span&gt;
 &lt;/button&gt;
 &lt;button class="xiaoyao-contact-button xiaoyao-contact-button--qq" type="button" data-copy-contact="826215906" data-copy-label="QQ 号"&gt;
 &lt;span class="xiaoyao-contact-button__label"&gt;QQ&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__value"&gt;826215906&lt;/span&gt;
 &lt;span class="xiaoyao-contact-button__status" data-copy-status&gt;点击复制&lt;/span&gt;
 &lt;/button&gt;
 &lt;span class="xiaoyao-contact-feedback" role="status" aria-live="polite"&gt;&lt;/span&gt;
&lt;/div&gt;

 &lt;/div&gt;
&lt;/section&gt;

&lt;p&gt;进微信群请联系博主，各位觉得文章对你有帮助的话可否打赏一些呀~&lt;/p&gt;
&lt;hr&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;⚠️ 时效性提醒（2026-07 更新）&lt;/strong&gt;：本文发布于 2026 年 4 月，距今已过去 3 个月。文中方案三（批量开 Pro）已在发布时标注为已修复；方案一（API 响应注入）和方案二（offerToken 替换）经过近 3 个月，&lt;strong&gt;当前可用性存疑&lt;/strong&gt;，OpenAI/Google 可能已加强校验。本文保留仅供安全研究与技术原理学习参考。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="前言"&gt;前言
&lt;/h2&gt;&lt;p&gt;今天给大家带来一个相当有意思的支付安全案例分析。这个漏洞的核心在于 ChatGPT 安卓客户端在调用 Google Play Billing 时，服务端未对订阅凭证进行二次校验，导致攻击者可以通过两种方式实现 Plus/Pro 权益的零元订阅。&lt;/p&gt;
&lt;p&gt;先说结论：这不是传统意义上的&amp;quot;破解&amp;quot;，而是典型的业务逻辑漏洞。漏洞根源在于 Google Play Billing 过度信任客户端传入的优惠凭证，且未与服务端进行资格校验。&lt;/p&gt;
&lt;h2 id="两种攻击方式对比"&gt;两种攻击方式对比
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;攻击方式&lt;/th&gt;
 &lt;th&gt;攻击点&lt;/th&gt;
 &lt;th&gt;技术难度&lt;/th&gt;
 &lt;th&gt;需要 Root&lt;/th&gt;
 &lt;th&gt;稳定性&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;方式一：API 响应注入&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;HTTP 层（MITM）&lt;/td&gt;
 &lt;td&gt;中&lt;/td&gt;
 &lt;td&gt;否&lt;/td&gt;
 &lt;td&gt;依赖服务端校验&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;方式二：offerToken 替换&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;内存层（Frida）&lt;/td&gt;
 &lt;td&gt;高&lt;/td&gt;
 &lt;td&gt;是&lt;/td&gt;
 &lt;td&gt;更稳定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="方式一api-响应注入无需-root"&gt;方式一：API 响应注入（无需 Root）
&lt;/h2&gt;&lt;h3 id="攻击原理"&gt;攻击原理
&lt;/h3&gt;&lt;p&gt;ChatGPT 安卓应用在启动时会调用以下接口获取当前登录用户信息：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GET https://android.chat.openai.com/backend-api/accounts/check/v4-2023-04-27
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;响应包中包含 &lt;code&gt;eligible_promo_campaigns&lt;/code&gt; 字段，用于存储当前账号可用的优惠活动。正常情况下，这个字段由服务端根据账号资格动态返回。&lt;/p&gt;
&lt;p&gt;通过中间人攻击（MITM），我们可以修改响应包，强行插入优惠码。&lt;/p&gt;
&lt;h3 id="环境准备"&gt;环境准备
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;必要条件&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;美区谷歌账号 × 1（任意区均可，非必须英区）&lt;/li&gt;
&lt;li&gt;任意美卡 × 1（用于绑定账号，实际不扣费）&lt;/li&gt;
&lt;li&gt;安卓设备 × 1（需 Root 以安装 MITM 证书，模拟器亦可）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;工具链&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MITM 抓包工具（推荐 HttpCanary 或 Charles）&lt;/li&gt;
&lt;li&gt;Root 权限管理工具（Magisk）&lt;/li&gt;
&lt;li&gt;ChatGPT 安卓客户端&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="可用优惠码"&gt;可用优惠码
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;固定优惠码（每次可用）&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;优惠码&lt;/th&gt;
 &lt;th&gt;效果&lt;/th&gt;
 &lt;th&gt;稳定性&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;3-day-free-trial&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;3 天免费试用&lt;/td&gt;
 &lt;td&gt;固定可用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;plus-1-month-free-trial&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;1 个月免费试用&lt;/td&gt;
 &lt;td&gt;固定可用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;1-month-10-dollars&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;半价优惠（$5/月）&lt;/td&gt;
 &lt;td&gt;固定可用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;pro-winback-1-month-free&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Pro 挽回试用 1 个月&lt;/td&gt;
 &lt;td&gt;特定资格账号&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;特殊优惠码（限时/限资格）&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;优惠码&lt;/th&gt;
 &lt;th&gt;效果&lt;/th&gt;
 &lt;th&gt;说明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;2wqkodfx51z2x&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;6 个月免费试用&lt;/td&gt;
 &lt;td&gt;限时优惠&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;2ispxs5mtgz35&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;12 个月免费试用&lt;/td&gt;
 &lt;td&gt;限时优惠&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这些优惠码是固定的，每次都可以使用。这也是为什么外面卡网可以持续生产低价 Plus 会员的根本原因。&lt;/p&gt;
&lt;h3 id="构造优惠响应"&gt;构造优惠响应
&lt;/h3&gt;&lt;p&gt;以下是注入 1 个月免费试用优惠的响应包示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;eligible_promo_campaigns&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;plus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;plus-1-month-free&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;plan_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;chatgptplusplan&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;linux.do&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;summary&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;你已获得 1 个月的 Plus 套餐优惠促销代码。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;discount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;percentage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;credit_grant&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;duration&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;num_periods&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;period&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;month&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;schedule&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;price_period&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;recurring&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;promotion_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;discount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;promotion_type_label&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1-month free trial&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;no_auto_renewal_at_discount_end&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;plan_type_change&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键字段说明&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;discount.percentage&lt;/code&gt;: 100 表示 100% 折扣（即 0 元）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;duration.num_periods&lt;/code&gt;: 优惠持续时间（1 表示 1 个月）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;no_auto_renewal_at_discount_end&lt;/code&gt;: true 表示优惠结束后不自动续费&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="零元订阅与风控绕过"&gt;零元订阅与风控绕过
&lt;/h3&gt;&lt;p&gt;修改响应后重新打开 ChatGPT 应用，点击升级即可看到免费试用界面。&lt;/p&gt;
&lt;p&gt;由于是 0 元订阅，Google Play 的风控级别极低，仅需通过验卡环节即可完成订阅。这也是为什么需要提前绑定一张美卡的原因——不是为了扣费，而是为了通过 Google 的风控验证。&lt;/p&gt;
&lt;h3 id="提取订阅凭证"&gt;提取订阅凭证
&lt;/h3&gt;&lt;p&gt;订阅成功后，ChatGPT 会向 RevenueCat 回调接口发送订阅凭证：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POST https://api.revenuecat.com/v1/receipts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;拦截该请求，提取响应中的 &lt;code&gt;fetch_token&lt;/code&gt; 字段：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;fetch_token&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;xxxx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个 &lt;code&gt;fetch_token&lt;/code&gt; 就是订阅凭证。将其保存后，即可用于给其他账号开通 Plus 权益。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="方式二offertoken-内存替换需要-root"&gt;方式二：offerToken 内存替换（需要 Root）
&lt;/h2&gt;&lt;h3 id="攻击原理-1"&gt;攻击原理
&lt;/h3&gt;&lt;p&gt;ChatGPT Android 调用 Google Play Billing 时，把当前 SKU 的默认 &lt;code&gt;offerToken&lt;/code&gt; 传给 Google Pay。这时候就可以在内存里把这个 token 替换成 &lt;code&gt;plus-1-month-free-trial&lt;/code&gt; 的 &lt;code&gt;offerToken&lt;/code&gt;，让 Google Play 按免费试用处理。实际支付金额就是 0 刀。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工作本质&lt;/strong&gt;：并非攻击 OpenAI 的服务器，而是在用户本地设备上篡改客户端与 Google Play 之间的计费数据。&lt;/p&gt;
&lt;h3 id="环境准备-1"&gt;环境准备
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;设备/工具&lt;/th&gt;
 &lt;th&gt;用途&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Root 的 Android 手机&lt;/td&gt;
 &lt;td&gt;需要刷 Magisk&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Windows 电脑&lt;/td&gt;
 &lt;td&gt;用于运行 Frida 客户端和 ADB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Frida HLUDA Server&lt;/td&gt;
 &lt;td&gt;正常版本谷歌有检测 Hook 会闪退&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="四步攻击流程"&gt;四步攻击流程
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;第一步&lt;/strong&gt;：通过 Frida 的 &lt;code&gt;Java.choose&lt;/code&gt; 接口遍历内存中名为 &lt;code&gt;c3q&lt;/code&gt; 的混淆计费类实例，利用反射强制访问其私有字段 &lt;code&gt;b&lt;/code&gt;（对应 &lt;code&gt;offerId&lt;/code&gt;）与 &lt;code&gt;c&lt;/code&gt;（对应 &lt;code&gt;offerToken&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步&lt;/strong&gt;：脚本持续比对，当发现某个实例的 &lt;code&gt;offerId&lt;/code&gt; 与目标免费试用档位一致、且其 &lt;code&gt;offerToken&lt;/code&gt; 以 &lt;code&gt;Adumm&lt;/code&gt; 为前缀时，将该 &lt;code&gt;offerToken&lt;/code&gt; 捕获并缓存。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三步&lt;/strong&gt;：对 Android 系统框架层的三个方法进行 Hook，分别为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;android.content.Intent.putExtra(String, String)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;android.os.Bundle.putString(String, String)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;android.os.Bundle.putStringArrayList(String, ArrayList)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在 ChatGPT 客户端发起付费订阅购买请求的瞬间，Hook 代码识别到即将写入的原始付费档位 &lt;code&gt;offerToken&lt;/code&gt;（同样以 &lt;code&gt;Adumm&lt;/code&gt; 开头），即将其替换为此前已缓存的免费试用 &lt;code&gt;offerToken&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第四步&lt;/strong&gt;：经篡改后的购买请求被 Google Play 按&amp;quot;免费试用成功&amp;quot;处理支付成功后并返回成功回执。&lt;/p&gt;
&lt;h3 id="可用优惠码-1"&gt;可用优惠码
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;优惠码&lt;/th&gt;
 &lt;th&gt;效果&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;2wqkodfx51z2x&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;6 个月免费&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;2ispxs5mtgz35&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;12 个月免费&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="完整-frida-脚本简化版"&gt;完整 Frida 脚本（简化版）
&lt;/h3&gt;&lt;p&gt;下面是经过整理的简化版 Hook 脚本，移除了复杂的动态捕获逻辑，直接注入已知的免费试用 offerToken：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * GPT Plus 免费订阅 Hook 脚本 - 简化版
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 用途：Hook Google Play Billing，直接替换 offerToken 为免费试用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 使用方法：
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 1. 手机 Root 并安装 Magisk
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 2. 推送 frida-server 到手机并运行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 3. 电脑端运行：frida -U -f com.openai.chatgpt -l hook.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 4. 在 ChatGPT App 中点击订阅
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 5. 自动替换为免费试用，扣费 0 元
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;use strict&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 配置区域：免费试用 offerToken（GPT Plus 1 个月）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;OFFER_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;AdummIvzNOk965s/0UOf08hi8zE1QBQA0qHs28TasLNjkP+H9peebMqSzAJF85XTHZsGLhCLb8sUqKa79ScsbZ1UI8MnOiU9VvkCLLFXKQHE1K9KRT9pYVT2qZz0SC9N9IEs3jhI+hkaTkvc/Vc=&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;_keepAlive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[GPT] &amp;#34;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;启动 — 注入 plus-1-month-free-trial&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// SSL 解除（防止证书验证失败）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;TM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;com.android.org.conscrypt.TrustManagerImpl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;TM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkTrustedRecursive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;[Ljava.security.cert.X509Certificate;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;java.net.Socket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;boolean&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;boolean&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;boolean&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;java.util.Collection&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;java.util.Collection&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;java.util.ArrayList&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;$new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;android.security.net.config.NetworkSecurityTrustManager&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkPins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;android.net.http.X509TrustManagerExtensions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkServerTrusted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;[Ljava.security.cert.X509Certificate;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;java.lang.String&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;java.lang.String&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;java.util.ArrayList&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;$new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 注入 offerToken（Bundle 层）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;JStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;java.lang.String&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Bundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;android.os.Bundle&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putStringArrayList&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;java.lang.String&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;java.util.ArrayList&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SKU_OFFER_ID_TOKEN_LIST&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OFFER_ID_TOKEN_LIST&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OFFER_TOKEN&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;offerToken 已注入&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putStringArrayList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 注入 offerToken（JSONObject 层）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;JSONObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;org.json.JSONObject&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;JSONObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$init&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;java.lang.String&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;oai.chatgpt.plus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;offerToken&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;patched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sr"&gt;/&amp;#34;offerToken&amp;#34;\s*:\s*&amp;#34;[^&amp;#34;]+&amp;#34;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#34;offerToken&amp;#34;:&amp;#34;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;OFFER_TOKEN&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;patched&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;就绪。请在 ChatGPT 中点击订阅按钮。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="完整-frida-脚本动态捕获版"&gt;完整 Frida 脚本（动态捕获版）
&lt;/h3&gt;&lt;p&gt;如果你拿到的 offerToken 格式有变化，可以使用这个动态捕获版本。它会自动扫描内存中的 offerToken 并替换：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Dynamic offerToken — 1 MONTH FREE Plus trial
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[*] plus-1-month-free-trial&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;TARGET_OFFER_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;plus-1-month-free-trial&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;capturedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;scanC3qInstances&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c3q&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;onMatch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;clazz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getClass&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDeclaredField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;bF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAccessible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;cF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clazz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getDeclaredField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;cF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAccessible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;offerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;offerToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;oidStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;(default)&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;offerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;tokStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerToken&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;null&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;offerToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Adumm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;oidStr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;TARGET_OFFER_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;capturedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokStr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;gt;&amp;gt;&amp;gt; FOUND &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;TARGET_OFFER_ID&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; &amp;lt;&amp;lt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;capturedToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanC3qInstances&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;android.content.Intent&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Bundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;android.os.Bundle&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;maybeSwap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;orig&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Adumm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;capturedToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanC3qInstances&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;capturedToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;] SWAP -&amp;gt; &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;TARGET_OFFER_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;capturedToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putExtra&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;java.lang.String&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;java.lang.String&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Adumm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;maybeSwap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Intent&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Adumm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;maybeSwap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Bundle&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putStringArrayList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;implementation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;sv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Adumm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maybeSwap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BundleArr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putStringArrayList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[+] Open subscription page first.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;使用说明（简化版脚本）&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;启动 Frida 服务端&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在手机上执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb push frida-server /data/local/tmp/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb shell chmod &lt;span class="m"&gt;755&lt;/span&gt; /data/local/tmp/frida-server
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;adb shell su -c &lt;span class="s1"&gt;&amp;#39;/data/local/tmp/frida-server &amp;amp;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;注入脚本&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在电脑端执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;frida -U -f com.openai.chatgpt -l hook.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;看到 &lt;code&gt;[GPT] 启动 — 注入 plus-1-month-free-trial&lt;/code&gt; 后继续。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;完成购买&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 ChatGPT 里点击升级订阅 → 在 Google Play 弹窗里点确认 → 完成。&lt;/p&gt;
&lt;p&gt;控制台应该显示 &lt;code&gt;[GPT] offerToken 已注入&lt;/code&gt;，支付金额显示为 0 元。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;使用说明（动态捕获版脚本）&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;手机 Root 并安装 Magisk&lt;/li&gt;
&lt;li&gt;推送 &lt;code&gt;frida-server&lt;/code&gt; (HLUDA 版本) 到手机并运行&lt;/li&gt;
&lt;li&gt;打开 ChatGPT 应用，进入升级 - 订阅 Plus 页面&lt;/li&gt;
&lt;li&gt;电脑端运行 &lt;code&gt;frida -U -f com.openai.chatgpt -l script.js&lt;/code&gt; 开启脚本&lt;/li&gt;
&lt;li&gt;脚本会自动捕获并替换 token（控制台显示 &lt;code&gt;SWAP -&amp;gt; plus-1-month-free-trial&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;在订阅页面点击升级，弹出的谷歌支付弹窗即显示 0 元&lt;/li&gt;
&lt;li&gt;完成验证后订阅成功&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;建议使用简化版脚本，更稳定&lt;/li&gt;
&lt;li&gt;如果简化版不工作，再尝试动态捕获版&lt;/li&gt;
&lt;li&gt;使用 HLUDA 版本 Frida 可绕过部分检测&lt;/li&gt;
&lt;li&gt;部分设备可能需要关闭 Google Play 保护机制&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="漏洞根源分析"&gt;漏洞根源分析
&lt;/h2&gt;&lt;h3 id="方案一api-响应注入"&gt;方案一：API 响应注入
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;漏洞根源&lt;/strong&gt;：服务端未校验 &lt;code&gt;eligible_promo_campaigns&lt;/code&gt; 中优惠码的获取途径合法性，仅验证格式有效即允许使用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;修复状态&lt;/strong&gt;：部分修复。目前部分优惠码已与账号资格绑定，但固定优惠码仍可使用。&lt;/p&gt;
&lt;h3 id="方案二offertoken-替换"&gt;方案二：offerToken 替换
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;漏洞根源&lt;/strong&gt;：Google Play Billing 信任客户端传入的 &lt;code&gt;offerToken&lt;/code&gt;，未与服务端二次校验账号是否真正具备该优惠的使用资格。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;修复状态&lt;/strong&gt;：未修复。这是 Google Play Billing 的设计缺陷，需要谷歌层面修复。&lt;/p&gt;
&lt;h3 id="方案三批量开-pro已修复"&gt;方案三：批量开 Pro（已修复）
&lt;/h3&gt;&lt;p&gt;这是之前某个公益 Bot 使用的大规模开 Pro 方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;正价开通一个 ChatGPT Pro 账号&lt;/li&gt;
&lt;li&gt;在客户端内点击&amp;quot;降级为 Plus&amp;quot;&lt;/li&gt;
&lt;li&gt;客户端向 RevenueCat 请求新的 &lt;code&gt;fetch_token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;该 token 为一次性凭证，未使用前可无限生成&lt;/li&gt;
&lt;li&gt;将 token 分发给需要开 Pro 的账号&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;漏洞根源&lt;/strong&gt;：RevenueCat 作为第三方订阅管理平台，与 ChatGPT 服务端之间的回调接口缺乏鉴权机制。服务端未校验 &lt;code&gt;fetch_token&lt;/code&gt; 的来源合法性，仅验证 token 格式有效即开通权益。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;修复状态&lt;/strong&gt;：该方案已被修复。目前 &lt;code&gt;fetch_token&lt;/code&gt; 已与设备指纹和账号绑定，无法跨账号使用。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="技术总结"&gt;技术总结
&lt;/h2&gt;&lt;h3 id="漏洞类型"&gt;漏洞类型
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;业务逻辑漏洞&lt;/strong&gt;：服务端过度信任客户端传入的订阅凭证&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第三方集成风险&lt;/strong&gt;：RevenueCat/Google Play Billing 回调接口缺乏鉴权&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优惠码校验缺失&lt;/strong&gt;：未校验优惠码的获取途径合法性和账号资格&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="攻击链关键点"&gt;攻击链关键点
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;中间人攻击可行性&lt;/strong&gt;：安卓客户端未启用 SSL Pinning（或可被 Root 绕过）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内存 Hook 可行性&lt;/strong&gt;：Google Play Billing 未检测 Frida 等 Hook 框架&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零元订阅风控宽松&lt;/strong&gt;：Google Play 对 0 元交易验证级别低&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;凭证复用漏洞&lt;/strong&gt;：&lt;code&gt;fetch_token&lt;/code&gt;/&lt;code&gt;offerToken&lt;/code&gt; 未与账号/设备绑定&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="防御建议"&gt;防御建议
&lt;/h3&gt;&lt;h4 id="对开发者的建议"&gt;对开发者的建议
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;服务端校验&lt;/strong&gt;：所有订阅状态变更必须与 Google Play Billing 侧二次确认&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;凭证绑定&lt;/strong&gt;：&lt;code&gt;fetch_token&lt;/code&gt;/&lt;code&gt;offerToken&lt;/code&gt; 应绑定设备指纹、账号 ID、时间戳&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优惠码校验&lt;/strong&gt;：记录优惠码使用历史，检测异常使用模式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSL Pinning&lt;/strong&gt;：移动端应用应启用证书锁定防止中间人攻击&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反 Hook 检测&lt;/strong&gt;：检测 Frida、Xposed 等 Hook 框架&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="对用户的提醒"&gt;对用户的提醒
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;此类漏洞属于灰色地带，使用可能导致账号被封禁&lt;/li&gt;
&lt;li&gt;绑定的支付方式存在潜在风险，建议使用虚拟卡&lt;/li&gt;
&lt;li&gt;漏洞随时可能被修复，不建议作为长期使用方案&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="法律免责声明"&gt;法律免责声明
&lt;/h2&gt;&lt;p&gt;本文仅用于技术研究与安全交流，请勿将所述技术用于非法用途。未经授权的订阅漏洞利用可能违反以下法律：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;《中华人民共和国网络安全法》&lt;/li&gt;
&lt;li&gt;《计算机信息网络国际联网安全保护管理办法》&lt;/li&gt;
&lt;li&gt;美国 Computer Fraud and Abuse Act (CFAA)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如因滥用本文技术导致的法律后果，作者不承担任何责任。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.revenuecat.com/" target="_blank" rel="noopener"
 &gt;RevenueCat 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.android.com/google/play/billing/security" target="_blank" rel="noopener"
 &gt;Google Play Billing 安全最佳实践&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://owasp.org/www-project-mobile-top-10/" target="_blank" rel="noopener"
 &gt;OWASP Mobile Top 10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://frida.re/docs/" target="_blank" rel="noopener"
 &gt;Frida 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/frida/frida/releases" target="_blank" rel="noopener"
 &gt;HLUDA - Undetectable Frida Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;标签&lt;/strong&gt;: #ChatGPT #订阅漏洞 #GooglePlayBilling #Frida #支付安全 #移动安全 #漏洞分析&lt;/p&gt;</description></item></channel></rss>