当前位置: 首页 > news >正文

Android应用抓包实战:绕过反代理与SSL证书绑定检测

1. 项目概述:当APP安全机制成为“拦路虎”

在移动应用安全测试或逆向分析的过程中,我们常常会遇到一个令人头疼的局面:当你兴致勃勃地打开抓包工具,准备一窥APP的网络通信时,却发现应用要么直接闪退,要么弹出一个“网络环境不安全”的提示,然后拒绝任何网络请求。这背后,往往是应用开发者部署的“反代理”与“反证书检测”机制在起作用。这些机制就像给APP穿上了一层“防刺服”,旨在防止中间人攻击,保护数据传输安全,但也给我们的安全评估、调试或研究设置了障碍。

我最近就遇到了一个金融类APP,它使用了多种手段来检测系统代理和证书状态,常规的抓包方法完全失效。经过一番折腾,我总结出了一套行之有效的免费方案,成功绕过了这些防线。这篇文章,就是这次“实战”的完整记录。无论你是安全研究人员、移动应用开发者(想测试自己APP的防护强度),还是对移动安全感兴趣的学习者,这套从原理到实操的“组合拳”都能为你提供清晰的路径。我们将彻底拆解APP如何检测代理与证书,并一步步演示如何用免费工具“拆解”这些防护。

2. 核心防线拆解:APP如何感知“被窥探”

在开始“绕过”之前,我们必须先理解“防线”是如何建立的。知其然,更要知其所以然,这样才能针对性地找到破绽。

2.1 反代理检测的常见手段

APP检测代理,主要是为了防止流量被第三方工具(如Charles、Fiddler、Burp Suite)截获和分析。其原理是检查系统是否设置了全局HTTP/HTTPS代理。

2.1.1 系统属性检查(针对Android)这是最基础也是最常见的检测方式。APP会读取系统的http.proxyHosthttp.proxyPort属性。如果这些属性不为空,且指向一个非预期的地址(如本地环回地址127.0.0.1localhost),APP就会判定当前处于代理环境。

// Java示例代码 String proxyHost = System.getProperty("http.proxyHost"); String proxyPort = System.getProperty("http.proxyPort"); if (proxyHost != null && !proxyHost.isEmpty()) { // 触发代理检测逻辑,可能终止运行或清空网络栈 throw new RuntimeException("Proxy detected!"); }

实操心得:很多早期或防护简单的APP仅依赖这一层检查。绕过方法相对简单,可以通过Hook(挂钩)这些系统属性的获取方法,使其始终返回null

2.1.2 网络连接信息检查更深入的检测会通过ConnectivityManagerNetwork类来获取当前活动网络的详细配置,检查其是否使用了代理。

// Android中检查WIFI代理的示例 ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { ProxyInfo proxyInfo = cm.getDefaultProxy(); if (proxyInfo != null) { // 检测到代理配置 } }

注意事项:这种方法能检测到更具体的代理配置,包括PAC(代理自动配置)脚本。单纯的系统属性修改可能无法绕过。

2.1.3 原生层(Native)检测为了增加逆向难度,一些安全要求高的APP会将检测逻辑写在C/C++代码中,编译进SO库。它们可能直接读取/proc/net/tcp等系统文件,或调用底层的网络API来检查是否有本地端口被监听(这正是抓包工具的工作方式)。这种检测在Java层不可见,静态分析和动态Hook的难度都更大。

2.2 反证书检测(SSL Pinning)的深度解析

反代理检测是“第一道门”,而SSL证书绑定(SSL Pinning)则是更核心的“第二道锁”。它的目的是确保APP只与自己信任的特定服务器证书(或公钥)通信,从而防止攻击者安装自定义根证书进行中间人攻击。

2.2.1 证书绑定的实现层级

  1. 网络框架层绑定:在使用OkHttp、Retrofit等流行网络库时,开发者可以很方便地配置证书绑定。例如,OkHttp的CertificatePinner类允许开发者指定特定主机名必须匹配的证书指纹(SHA-256或SHA-1)。

    // OkHttp证书绑定示例 val certificatePinner = CertificatePinner.Builder() .add("api.securebank.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") .build() val client = OkHttpClient.Builder() .certificatePinner(certificatePinner) .build()

    如果中间人证书的指纹不匹配,连接会立即被终止。

  2. 系统证书库信任链验证:即使没有显式绑定,APP默认也会信任系统预置的根证书库(Android系统CA证书)。当我们把Burp或Charles的根证书安装到系统“受信任的凭据”中时,就相当于“骗过”了这一层验证。反证书检测会主动检查是否有多余的、可疑的(特别是自签名的)根证书被安装。

  3. 自定义信任管理器(TrustManager):这是更灵活也更隐蔽的方式。APP可以完全绕过系统的证书验证流程,自己实现X509TrustManager接口,在checkServerTrusted方法中编写自定义的验证逻辑,比如只认可自己硬编码在代码里的某几个特定证书。

    public class MyTrustManager implements X509TrustManager { @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // 不是调用标准的验证流程,而是与自己内置的证书对比 if (!isMyCertificate(chain[0])) { throw new CertificateException("Server certificate not trusted!"); } } // ... 其他方法 }

    踩过的坑:对付自定义的TrustManager,常规的安装系统证书方法完全无效。必须修改APP的运行时代码,要么Hook这个自定义验证方法使其总是通过,要么替换掉整个SSL上下文。

2.2.2 证书检测的主动扫描除了在通信时验证,一些APP还会在启动或定期扫描系统的证书存储区,寻找已知的抓包工具证书(如PortSwigger CA、Charles Proxy CA)。一旦发现,就会提示风险并退出。这种检测独立于SSL握手过程,需要单独处理。

3. 免费工具链搭建与环境准备

工欲善其事,必先利其器。我们完全可以使用一套免费、开源的工具链来完成整个绕过过程。以下是我亲测可用的组合,运行在Windows或macOS宿主机上,通过虚拟化技术操作Android环境。

3.1 核心工具选型与原理

  1. Android模拟器:Android Studio 内置模拟器 (AVD)

    • 为什么选它?相比真机,模拟器具有更高的可控性和可重复性。我们可以轻松获取Root权限、修改系统镜像、快照回滚,这对调试和测试至关重要。Genymotion等第三方模拟器虽然也不错,但AVD免费、官方且与开发环境集成度最高。
    • 关键配置:创建AVD时,必须选择x86 或 x86_64 架构的系统镜像(如Android 11.0 x86_64)。因为后续使用的核心工具Frida在x86架构下的稳定性和兼容性最好。同时,在“Advanced Settings”中,将“Internal Storage”和“SD card”大小适当调大(如2GB),以便安装更多工具。
  2. 动态插桩框架:Frida

    • 核心作用:Frida是一个动态代码插桩工具包。它允许我们将JavaScript代码片段注入到目标APP(或系统进程)的运行时内存中,从而Hook(拦截和修改)函数调用、操作内存数据。它是绕过各种检测的“瑞士军刀”。
    • 工作原理:Frida在目标端运行一个守护进程frida-server,与桌面端的控制脚本通过管道通信。脚本中定义的Hook逻辑会被注入到目标进程,实时改变其行为。
    • 获取:从Frida官网 (frida.re) 下载对应版本的frida-server(Android x86_64) 和通过pip安装frida-tools
  3. 逆向分析辅助:Objection

    • 为什么选它?Objection是基于Frida的命令行工具,封装了许多针对移动端(尤其是Android/iOS)安全的常用测试命令。它可以让SSL Pinning绕过、Root检测绕过等操作变得像输入一行命令那么简单,极大提升了效率。
    • 获取:通过pip安装:pip install objection
  4. 抓包工具:Burp Suite Community Edition 或 mitmproxy

    • Burp Suite:功能强大的图形化抓包和渗透测试平台,社区版免费。我们将用它来设置上游代理,并安装其CA证书。
    • mitmproxy:轻量级、命令行驱动的中间人代理,完全免费开源,脚本化能力强。适合喜欢命令行操作和自动化集成的用户。
    • 二选一即可,本文以Burp Suite为例进行演示。

3.2 环境配置详细步骤

3.2.1 模拟器与系统准备

  1. 启动AVD,在模拟器的“设置” -> “关于平板电脑” -> 多次点击“版本号”以开启“开发者选项”。
  2. 进入“开发者选项”,开启“USB调试”。这是Frida能够连接设备的基石。
  3. 为了后续方便,同时开启“网络ADB调试”(允许通过网络连接ADB)。

3.2.2 推送Frida-server并启动

  1. 从官网下载与本地frida-tools版本匹配的frida-server-x.x.x-android-x86_64.xz,解压得到frida-server文件。
  2. 使用ADB命令将文件推送到模拟器,并赋予执行权限:
    adb push frida-server /data/local/tmp/ adb shell "chmod 755 /data/local/tmp/frida-server"
  3. 在模拟器的shell中以后台方式启动frida-server:
    adb shell cd /data/local/tmp ./frida-server &
  4. 在宿主机终端验证连接:frida-ps -U。如果能看到设备上的进程列表,说明Frida环境搭建成功。

3.2.3 配置抓包代理

  1. 启动Burp Suite,在Proxy -> Options中,确保代理监听在0.0.0.0:8080(而不仅仅是127.0.0.1),这样模拟器才能访问到。
  2. 在模拟器的WIFI设置中,长按已连接的网络 -> 修改网络 -> 高级选项 -> 代理选择“手动”。
    • 代理主机名:填写你宿主机的IP地址(在macOS/Linux上用ifconfig,Windows上用ipconfig查看,通常是10.0.2.2192.168.x.x)。
    • 代理端口:8080
  3. 此时,模拟器的HTTP流量应该已经能流向Burp。访问一个HTTP网站测试。

3.2.4 安装Burp的CA证书到系统信任区这是绕过基础SSL验证的关键一步,但仅对未做SSL Pinning的APP有效。

  1. 在模拟器浏览器中访问http://burp,下载Burp的CA证书(cacert.der)。
  2. 将证书文件后缀改为.cer
  3. 进入系统“设置” -> “安全” -> “加密与凭据” -> “从存储设备安装证书” -> “CA证书”,找到并安装该证书。
  4. 重要检查:安装后,在“受信任的凭据” -> “用户”标签页下,应能看到“PortSwigger CA”的证书。至此,基础抓包环境就绪。

4. 实战绕过:从反代理到SSL Pinning

假设我们的目标APP名为com.secure.app。完成上述准备后,你会发现直接打开APP,它可能检测到代理而无法联网,或者即使能联网,HTTPS请求也会因SSL Pinning而失败。下面我们分步攻克。

4.1 阶段一:禁用反代理检测逻辑

我们使用Frida来Hook常见的代理检测方法。创建一个名为disable_proxy.js的脚本:

Java.perform(function() { console.log("[*] Starting anti-proxy detection bypass..."); // 1. Hook System.getProperty var System = Java.use("java.lang.System"); System.getProperty.overload('java.lang.String').implementation = function(key) { if (key.includes("proxy")) { console.log("[+] System.getProperty called for key: " + key); // 对于代理相关的属性,返回null return null; } return this.getProperty(key); }; // 2. Hook android.net.ProxyInfo (常见于检查当前网络代理) var ProxyInfo = Java.use("android.net.ProxyInfo"); if (ProxyInfo) { ProxyInfo.getHost.implementation = function() { console.log("[+] ProxyInfo.getHost() called, returning null"); return null; }; ProxyInfo.getPort.implementation = function() { console.log("[+] ProxyInfo.getPort() called, returning -1"); return -1; }; } // 3. Hook ConnectivityManager.getDefaultProxy (另一种常见方式) var ConnectivityManager = Java.use("android.net.ConnectivityManager"); if (ConnectivityManager) { ConnectivityManager.getDefaultProxy.implementation = function() { console.log("[+] ConnectivityManager.getDefaultProxy() called, returning null"); return null; }; } console.log("[*] Anti-proxy hooks installed."); });

使用Frida加载此脚本到目标APP:

frida -U -f com.secure.app -l disable_proxy.js --no-pause

-f参数表示启动APP,--no-pause表示立即启动主线程。观察控制台输出,如果看到Hook成功的日志,并且APP不再因代理检测而崩溃或断网,说明第一步成功。

注意事项:有些APP的检测逻辑可能在Native层,或者使用了更冷门的API。如果上述脚本无效,需要结合静态分析(使用Jadx-GUI反编译APK)搜索proxyProxygetProxy等关键词,找到具体的检测类和方法,然后针对性地编写Hook脚本。

4.2 阶段二:绕过SSL证书绑定(SSL Pinning)

这是攻坚的核心。我们使用Objection这个“神器”,它能自动化完成许多常见的SSL Pinning绕过。

4.2.1 使用Objection的自动化绕过首先,确保目标APP进程正在运行(如果上一步已用Frida启动,则已运行)。然后使用Objection连接并注入通用绕过脚本:

objection -g com.secure.app explore

进入Objection的交互命令行后,执行:

android sslpinning disable

这条命令会尝试一系列操作:

  1. 寻找并Hook常见的证书验证类,如TrustManagerImplOkHttpCertificatePinnerApache HttpClientSSLSocketFactory等。
  2. 将这些类的关键验证方法(如checkServerTrustedverify)设置为空实现或修改其逻辑,使其总是返回成功。
  3. 尝试从内存中搜索并解除证书绑定。

执行成功后,Objection会输出类似“SSL Pinning disabled”的信息。此时,再尝试在APP内触发网络请求,Burp Suite中应该就能成功截获和解密HTTPS流量了。

4.2.2 当Objection失效时的手动深度Hook有些应用使用了自定义的SSL验证库,或者代码混淆严重,Objection的通用脚本可能无法识别。这时就需要我们手动分析并Hook。

步骤一:定位关键验证点

  1. 使用Jadx-GUI打开目标APK。
  2. 搜索关键词:X509TrustManagercheckServerTrustedCertificatePinnerSSLContextTrustManager
  3. 仔细查看搜索结果,找到自定义的TrustManager实现类或证书绑定代码。记下完整的类名和方法名。

步骤二:编写精准Hook脚本假设我们找到了一个自定义类com.secure.app.network.CustomTrustManager,它重写了checkServerTrusted方法。我们可以编写如下Frida脚本 (bypass_custom_pinning.js):

Java.perform(function() { console.log("[*] Attempting to bypass custom SSL pinning..."); var CustomTrustManager = Java.use("com.secure.app.network.CustomTrustManager"); if (CustomTrustManager) { console.log("[+] Found CustomTrustManager class."); CustomTrustManager.checkServerTrusted.implementation = function(chain, authType) { console.log("[+] CustomTrustManager.checkServerTrusted() HOOKED!"); console.log(" |- Auth type: " + authType); // 直接什么都不做,让验证通过 // 如果需要,也可以在这里打印或操作证书链信息 // var cert = chain[0]; // console.log(" |- Subject: " + cert.getSubjectDN().getName()); return; // 不抛出异常即表示验证通过 }; console.log("[*] CustomTrustManager hook installed."); } // 同时,也Hook标准的TrustManagerFactory,以防万一 var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory"); TrustManagerFactory.getTrustManagers.implementation = function() { console.log("[+] TrustManagerFactory.getTrustManagers() called."); var originalManagers = this.getTrustManagers(); // 这里可以替换或修改返回的TrustManager数组 return originalManagers; }; });

使用Frida加载这个脚本:

frida -U -F com.secure.app -l bypass_custom_pinning.js

-F参数表示附加到最前台的APP。

实操心得:手动Hook的关键在于精准定位。有时类名可能被混淆,如变成a.a.a.c,这时需要结合代码上下文(如方法参数、调用的其他API)和行为分析来判断。可以先用Objection尝试,如果失败,再根据Objection的日志或错误信息来缩小搜索范围。

4.3 阶段三:对抗证书存储区扫描

如果APP在启动时扫描系统证书库并发现了Burp证书,我们有两个策略:

  1. 临时重命名/隐藏证书(推荐):在安装Burp证书时,不要使用默认名称。安装后,通过ADB shell进入/data/misc/user/0/cacerts-added/(路径可能因系统版本而异),找到对应的证书文件(一个数字哈希名.0),将其临时移动到其他目录或改名。需要抓包时再移回来。这需要Root权限。

    adb shell su mv /data/misc/user/0/cacerts-added/xxxxxx.0 /data/local/tmp/ # 需要抓包时 mv /data/local/tmp/xxxxxx.0 /data/misc/user/0/cacerts-added/
  2. Hook证书扫描逻辑:分析APP扫描证书的代码(可能涉及KeyStoreCertificateFactory等类),Hook相关方法,在返回的证书列表中过滤掉Burp的证书。这需要对代码有更深的理解。

5. 疑难排查与进阶技巧

即使按照上述步骤操作,你也可能会遇到各种问题。这里记录一些常见的“坑”和解决方法。

5.1 常见问题速查表

问题现象可能原因排查步骤与解决方案
Frida连接失败,frida-ps -U无输出1.frida-server未运行或崩溃。
2. 设备USB调试未开启。
3. 端口冲突或被防火墙阻止。
1. 检查adb shellfrida-server进程是否存在 (ps | grep frida)。
2. 重启frida-server
3. 确认开发者选项和USB调试已开启。
4. 尝试使用frida-ps -U时指定传输方式-D 000000000000(设备ID)。
Objection执行ssl pinning disable后仍抓不到包1. APP使用了Objection不支持的Pinning方案(如自定义Native验证)。
2. 反代理检测仍然生效,导致无网络流量。
3. 脚本注入的时机不对,验证逻辑在注入前已执行。
1. 使用android hooking list classes搜索sslcert等关键词,手动分析并Hook。
2. 确认反代理Hook脚本已生效(查看日志)。
3. 尝试在APP启动早期就注入脚本 (-f参数启动)。
4. 使用-f并加上--pause,在脚本加载后再恢复APP运行 (%resume)。
APP启动立即闪退1. APP有强大的反调试或反注入机制。
2. Frida或Hook脚本被检测。
3. Hook脚本本身有错误,导致目标进程崩溃。
1. 尝试使用Frida的隐身模式,重命名frida-server为其他名字(如fs1286)并相应修改连接代码。
2. 寻找并Hook反调试检测点(如android.os.Debug.isDebuggerConnected())。
3. 分步注释Hook脚本,定位导致崩溃的Hook点。
4. 使用frida -U -f com.xxx --no-pause但不加载脚本,看是否仍闪退,以判断是Frida本身被检测。
Burp能抓到HTTP包,但HTTPS包显示Client TLS handshake failed1. 系统CA证书未正确安装或不被信任。
2. APP使用了证书绑定且绕过未成功。
3. Android 7.0+ 上,APP可能设置了网络安全配置,只信任系统预装证书。
1. 确认Burp CA证书已安装在“系统信任的凭据”中(用户目录)。
2. 重点检查并执行SSL Pinning绕过步骤。
3. 对于Android 7+,需将Burp证书安装到系统分区(需Root),或修改APP的网络安全配置文件(需反编译重打包)。
流量时有时无,或特定请求失败1. APP对不同域名或API使用了不同的网络库或配置。
2. 证书绑定可能只针对核心API域名,其他静态资源域名未绑定。
1. 在Burp中观察,是哪些Host的请求失败。针对特定域名进行更深入的代码分析。
2. 确认Hook脚本是否覆盖了所有可能的网络请求路径(如WebView、图片库等发起的请求)。

5.2 进阶技巧与深度防御对抗

5.2.1 应对Native层检测如果APP的核心检测逻辑在SO库中,就需要使用Frida的Native API (Interceptor) 进行Hook。

// 示例:Hook Native层的 `getaddrinfo` 函数(可能用于检测本地代理) Interceptor.attach(Module.findExportByName(null, "getaddrinfo"), { onEnter: function(args) { var hostname = Memory.readCString(args[0]); console.log("[Native] getaddrinfo called for: " + hostname); // 可以在这里修改hostname参数,例如将指向代理检测服务器的域名解析到一个无效地址 }, onLeave: function(retval) { // 可以修改返回值 } });

这需要对Linux系统API和ARM/X86汇编有一定了解。

5.2.2 使用r0capture进行全能抓包如果觉得配置Frida脚本太麻烦,可以尝试一个强大的集成工具:r0capture。它是一个基于Frida的抓包工具,专门针对安卓应用,可以自动绕过SSL Pinning和代理检测。

# 安装 pip install frida-tools git clone https://github.com/r0ysue/r0capture # 使用 (需先运行frida-server) python r0capture.py -U -f com.secure.app -v

它会自动注入一系列绕过脚本,并将解密后的HTTP/HTTPS流量以pcap格式保存,方便用Wireshark分析。注意:这是一个中国安全研究员开发的开源工具,使用前请确保符合你的测试规范。

5.2.3 模拟器指纹修改一些高级APP会检测运行环境是否为模拟器(通过检查IMEI、Build属性、传感器等)。如果检测到是模拟器,可能会拒绝运行或启用更严格的防护。我们可以使用Magisk模块(如MagiskHide Props Config)或专门修改模拟器指纹的工具来伪装成真实设备。

5.2.4 对抗代码混淆与加固对于经过严重混淆或商业加固(如梆梆、爱加密)的APP,直接反编译可能看不到有意义的Java代码。这时:

  1. 动态分析优先:直接运行APP,用Frida去Hook那些在运行时必然会调用的系统级API(如SSLContext.initTrustManagerFactory.getInstance),从调用栈回溯来定位关键代码区域。
  2. 脱壳:对于加固APP,可能需要先进行脱壳,获取原始的DEX文件。这本身就是一个复杂的话题,涉及动态加载、内存Dump等技术,有特定的工具链(如Frida-DEXDump、FART)。
  3. 耐心与经验:分析这类APP更像是一场耐心的较量。结合静态分析(看汇编或经过简单反混淆的代码)、动态调试、网络行为监控,一点点拼凑出它的防护逻辑。

绕过APP的安全防线是一个“道高一尺,魔高一丈”的持续对抗过程。我个人的体会是,没有一劳永逸的银弹。最有效的方法是建立一套清晰的排查思路:先确保基础代理和证书环境无误,然后用Objection等自动化工具尝试通用绕过,失败则静下心来逆向分析,从网络行为、日志、崩溃点中寻找线索,最后编写针对性的Hook脚本。整个过程不仅考验技术,更考验耐心和系统性思维。最后记住,所有这些技术都应在合法授权的范围内进行,用于安全研究、自我测试或已获许可的评估,这是每一位从业者必须坚守的底线。

http://www.cnnetsun.cn/news/3006729.html

相关文章:

  • 极致CMS 1.7插件机制安全审计:远程ZIP下载与任意目录打包漏洞深度剖析
  • 从协议层到调度层:AI API中转站架构深度拆解
  • SWEET32漏洞实战:TLS/SSL中64位分组密码的生日攻击与修复指南
  • 2026年AI模型接口中转站权威测评推荐榜单 全场景适配优质平台选购指南
  • 3分钟搞定缠论分析:ChanlunX开源插件让通达信自动画出中枢笔段
  • Unreal Engine 5.8 全部新增功能总结
  • 夹缝中的企业投融资部
  • 基于魔珐星云数字人平台的职场顾问全双工语音交互系统实践
  • 百景公会清退措施已出台,助您顺利申请减损补偿
  • Composer:PHP 项目的依赖管理工具
  • 移动云怎么样?
  • 2026免费靠谱八字排盘APP推荐:适合初学者和小白的八字排盘软件怎么选?
  • 如何在5分钟内让通达信自动绘制缠论中枢和笔段:告别手动分析的终极解决方案
  • PVE Tools:Proxmox VE终极管理工具箱,让虚拟化配置变得简单快速
  • 好用的 AI 配音工具都有哪些?实测 6 款热门工具,覆盖全场景需求
  • 专业会务管理系统怎么选,会助力智能会务系统用功能说话
  • Ryujinx模拟器快速上手:免费开源Switch游戏完美运行指南
  • 都在说学AI,那线上学还是线下学?
  • Django毕设项目:基于 Django+Vue 的双相患者线上互助管理系统设计与实现 基于 Django+Vue 的情绪疏导交流分享平台设计与实现 (源码+文档,讲解、调试运行,定制等)
  • 3步掌握窗口自由:从新手到专家的WindowResizer完整指南
  • 荷兰重点进口货物类型和主要来源国家梳理
  • 2026年制造业ISO 9001认证实操:从图纸数字化到自动化检验计划构建
  • SQLazy:告别盲信 AI,分步构建可靠查询
  • 如何拥有一个较好的配色方案(低审美福音)
  • 调查研究-194 Qwen3 MoE vs Dense 怎么选?2026 工程部署视角完整指南
  • 知识蒸馏实战:面向计算机视觉的模型轻量化与部署优化
  • OpenAI Projects:从临时对话到持久AI工作台的范式升级
  • 视觉指令微调实战:工业质检场景下的多模态模型精准训练
  • DonkeyCar油门校准:从PWM信号到ESC驱动的完整指南
  • AI写论文优选!4款AI论文写作工具,为写期刊论文提供新思路!