news 2026/10/20 7:21:21

DVWA靶场DOM型XSS全等级通关:原理、绕过与防御实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DVWA靶场DOM型XSS全等级通关:原理、绕过与防御实战

1. 先搞清楚:DOM型XSS和反射型、存储型不是一回事

前阵子有朋友在群里问,DVWA里的DOM型XSS到底怎么打,为什么照着反射型XSS的payload直接抄过去却经常不弹窗。DVWA(Damn Vulnerable Web Application)里的XSS模块有三个入口,分别是反射型、存储型和DOM型,其中DOM型最容易被当成“改参数、看回显”来理解,结果新手经常在这个模块卡住。这篇我把DVWA的xss_d模块从Low到Impossible四个难度完整过一遍,把每一步的payload、源码和绕过思路都摊开讲,顺便把DOM型XSS的防御方法也聊透。

先花点时间把这三种XSS的本质区别说清楚。反射型XSS和存储型XSS有一个共同特征:恶意脚本会出现在服务端的响应里。反射型是服务端把URL参数原样拼进页面返回,存储型是服务端把恶意代码存进数据库,之后每次渲染都带出来。这两种XSS的检测思路往往是看响应包、看服务端输出,所以很多人习惯拿着“看回显”的思维来做题。

DOM型XSS完全不一样。它的恶意代码从头到尾根本不进服务端,服务端返回的就是一个正常的静态页面。真正出问题的是页面里的JavaScript,它读取了浏览器URL中的某一段数据,然后直接把它当成HTML写了进去。恶意脚本是在浏览器端、由前端代码自己“亲手”执行的。如果说反射型和存储型是快递员把危险包裹原样送到你家门口,那DOM型就是快递员只把门牌号报给你,你自己把门打开了。

这也是为什么DOM型XSS在学习时很容易产生认知偏差:你在浏览器里明明看到了弹窗,打开网络面板却发现服务端响应里干干净净,没有任何可疑标签。只有去读前端JavaScript源码,才能看到漏洞点在哪里。

DVWA这个靶场之所以适合练这个,是因为它把XSS分成了三种场景,又把每种场景拆成四个安全等级,从完全没有防护到彻底修复都有对应代码,可以直接读源码观察防御是怎么一步步变强的。在真实项目里做前端安全审计时,你同样需要按这个思路去追:数据从哪里来,最后写到了哪个DOM接口,中间有没有校验和编码。

整篇文章的路线是这样的:先把DVWA跑起来,认准xss_d模块的入口,然后分别走一遍Low、Medium、High、Impossible四个等级的通关步骤,每步都会配上payload和源码片段,最后再回到DOM型XSS的原理和防御层面做总结。

2. 环境准备与入口:先把DVWA跑起来

2.1 部署、登录与安全等级切换

学习DVWA之前,先把环境准备利索。你不需要用特别复杂的架构,一个本地PHP集成环境就够了,把DVWA源码丢到网站根目录,启动MySQL和PHP,然后访问安装页面完成初始化。也可以用容器方式拉起一个现成的靶场镜像,省去手动配置数据库的时间。两种方式我都试过,集成环境更适合观察源码和中间件配置,因为所有文件都在本地,想改代码、加日志、打断点都很方便;容器方式胜在干净快速,五分钟就能进到登录页。

DVWA的默认登录账密是admin/password,登录成功后先不要急着进漏洞模块,去DVWA Security页面把安全等级切成Low。这一步容易被忽略,但非常关键:DVWA的很多漏洞在High和Impossible等级下防护逻辑差别很大,如果你默认等级是Impossible,直接访问xss_d模块会发现怎么打都不弹窗,容易产生“是不是环境坏了”的错觉。通关时按Low → Medium → High → Impossible的顺序逐级切换,每切一次就重新访问一次模块页面,确保当前等级的源码生效。

有一个细节要注意:切换安全等级之后,DVWA不会自动刷新你的会话。如果浏览器里开了很久的页面,或者登录状态已经过期,切完等级后访问模块可能直接被弹回登录页。这时候重新登录一次就好,不需要重新初始化数据库。

2.2 先观察xss_d模块的正常行为

进入xss_d模块后,你会看到一个语言选择下拉框。正常页面URL里带着?default=English这样的参数,下拉框默认选中English。试着手动把URL改成?default=French,刷新页面,你会看到下拉框中多了一个French选项。

此时打开浏览器的开发者工具,看Network面板里这次请求的响应内容。你会发现一个很有意思的现象:服务端返回的HTML里根本没有French这个词。也就是说,下拉框里的French不是服务端帮你渲染的,而是页面里的JavaScript读取了URL里的default值,用DOM操作动态写进去的。

这个观察就是理解DOM型XSS的钥匙。当URL参数被前端JavaScript读取,并且用document.write、innerHTML这类接口拼进页面时,参数内容就不再是简单的“字符串”,而是会被浏览器当成HTML解析的“代码”。一旦这个拼接过程没有任何过滤,XSS就成立了。

2.3 给DOM型XSS画一条数据流

在我开始逐个等级打靶之前,建议你先在脑子里建立一个数据流模型。DOM型XSS的数据流是这样的:浏览器URL的某一段(比如location.search或者location.hash)作为输入源,被前端JavaScript用location.href、location.search、location.hash等方式读取,然后经过字符串截取、解码、拼接,最终传到了document.write、innerHTML、eval等危险接口。

在这个链路里,服务端只有两种姿态:一种是不管,直接把页面返回,前端自己惹祸;另一种是尝试在入口处做过滤,但因为过滤只作用在服务端能看到的字符串上,而DOM型XSS的真正触发位置在浏览器端,所以绕过空间经常比反射型XSS大得多。

后面谈Medium和High的绕过方法时,你会反复用到这个数据流模型。尤其是“服务端能不能看到这段payload”这个判断,会直接决定一条payload是否可用。

3. Low等级通关:从改语言到弹窗

3.1 先看Low级别的源码,漏洞一目了然

Low等级通关逻辑很简单,但源码值得细读。打开DVWA的xss_d模块对应源码文件,核心JavaScript长这样:

var lang = 'English'; if (document.location.href.indexOf("default=") >= 0) { var lang = document.location.href.substring(document.location.href.indexOf("default=")+8); } document.write("<option value='" + lang + "'>" + decodeURIComponent(lang) + "</option>");

这段代码做了什么?它先默认lang是English,然后检查当前URL的完整字符串里有没有default=。如果有,就从default=后面把所有内容截出来,当作lang的值,最后用document.write把lang拼进一个option标签里写入页面。

这里有两个容易被忽略的细节。第一,document.location.href拿到的是浏览器地址栏的完整URL,包括参数和编码后的内容;第二,写入前调用了decodeURIComponent,也就是URL编码会被还原。这两个细节叠加在一起,意味着攻击者完全可以通过URL编码,把带有尖括号的HTML标签安全地送进document.write,浏览器在解析时看到的又是还原后的原始标签。

3.2 正式通关:用script标签弹窗

在地址栏访问下面这个URL:

http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=<script>alert(1)</script>

浏览器会自动把尖括号做URL编码,实际请求会变成类似%3Cscript%3Ealert(1)%3C%2Fscript%3E的形态。前端JS用substring截取到编码后的字符串,再经decodeURIComponent还原成<script>alert(1)</script>,最后document.write把它写进页面。浏览器解析这段HTML时,遇到<script>标签就会执行里面的JavaScript,弹窗出现。

为了稳妥,你也可以手动把payload编码后放进URL:

http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=%3Cscript%3Ealert(1)%3C%2Fscript%3E

两种方式效果一样。如果页面弹出了alert(1),说明Low等级已经通关。

3.3 Low等级为什么完全拦不住

Low等级没有任何服务端过滤,前端也完全没有校验。整个漏洞的根源就一句话:外界可控的数据被当成HTML代码写入了DOM。document.write这个接口本身就不是用来写普通文本的,它直接把字符串交给HTML解析器。只要字符串里含有标签,就会按照标签处理。

这也解释了为什么要避免在真实项目里用document.write拼接任何用户可控数据。哪怕你对参数做了一次性过滤,只要某个环节漏了一个payload变体,DOM型XSS就可能复活。Low等级的教训,本质上是在说:不能用黑名单思想去修DOM型XSS。

4. Medium等级通关:被拦了别慌,换条路走

4.1 先踩坑:script标签直接被拦

切到Medium等级后,先用Low等级的payload测试。访问?default=<script>alert(1)</script>,页面没有弹窗,URL被重定向成了?default=English。这说明服务端已经开始插手过滤了。

打开源码文件,Medium等级的服务端处理大概长这样:

if (array_key_exists("default", $_GET) && !is_null($_GET['default'])) { $default = $_GET['default']; // 过滤script标签 if (stripos($default, "<script") !== false) { header("location: ?default=English"); exit; } }

stripos是不区分大小写的字符串查找,所以<script>、<SCRIPT>、<Script>都会被拦下来。过滤方式简单粗暴:只要参数里含有<script这六个字符的开头组合,就强制重定向回English。

但注意,这里只过滤了<script。这个漏洞到了Medium等级依然很容易打,因为XSS并不是只靠script标签才能触发。

4.2 用非script标签绕过:实测三个可用payload

HTML里能被浏览器解析并执行JavaScript的标签远不止script一个。<img>、<svg>、<body>、<iframe>、<input>、<details>等标签配合事件属性,都能触发脚本。

我在Medium等级下实测有效的payload有这几种:

<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>

这些payload的共同点是:不包含<script子串,所以能骗过服务端的stripos检查。当document.write把它们写入页面后,HTML解析器会创建对应元素,事件属性里的alert会在特定时机执行。比如<img>标签加载src失败就会触发onerror,弹窗出现。

完整URL之一:

http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=<img src=x onerror=alert(1)>

刷新后弹窗成功,Medium通关。从这里开始你会感受到DOM型XSS的绕过规律:过滤规则只会盯着某几个特征串,HTML标签和事件属性的组合多到数不清,黑名单很难防全。

4.3 更隐蔽的玩法:把payload藏进URL的#号后面

除了换标签,Medium还有一个更巧妙的绕过思路:把payload放在URL的hash片段里。HTTP请求中,浏览器只会把#前面的部分发给服务端,#后面的内容只存在浏览器端,服务端根本看不到。

DVWA的JavaScript读取的是document.location.href,这个属性包含完整的URL,包括hash部分。所以你可以这样构造:

http://127.0.0.1/dvwa/vulnerabilities/xss_d/#default=<img src=x onerror=alert(1)>

服务端拿到的URL路径里没有default参数,连检查都不会触发;前端JavaScript从location.href里找到了default=,截取后面的payload,decodeURIComponent还原后照样写入DOM执行。

这个技巧在真实场景里很有价值:WAF、服务端日志、IDS看到的都是干净请求,恶意内容只存在于浏览器的地址栏里,安全设备很难感知。做防御时需要意识到,DOM型XSS的检测不能只看网络层,还要看前端代码的输入源和危险接口使用情况。

4.4 Medium的教训:黑名单过滤挡不住DOM执行链

Medium等级让我最感慨的一点是:它确实出了力,在服务端做了检测,但这个检测只拦了一个特征,而且完全没有意识到DOM型XSS的执行链是“前端读取URL → 前端拼接HTML”,服务端对URL参数做再多过滤,只要前端JS依然信任location.href,绕过就是时间问题。

所以在实际项目里,如果你遇到一个DOM型XSS,先在代码里找两个东西:输入源是哪个接口,输出点是哪个DOM API。这两个点之间的路径,才是修复的重点。服务端加过滤即使能挡住一部分攻击,也只能算临时缓解,不能叫修复。

5. High等级通关:过滤更猛,但DOM还是那个DOM

5.1 High比Medium严在哪里

切到High等级后,先按Medium的payload试一下<img src=x onerror=alert(1)>。某些版本的DVWA在High等级会把事件属性也拉黑,此时onerror会被识别并拦截,URL被跳回English。再看源码,可能会看到类似这样的规则:

// 过滤script标签 if (stripos($default, "<script") !== false) { header("location: ?default=English"); exit; } // 过滤常见事件属性 if (preg_match('/on[a-zA-Z]+\s*=/i', $default)) { header("location: ?default=English"); exit; }

这个正则会把onerror、onload、onclick这一类事件属性全部拦下。Medium里顺手可用的<img onerror>、<svg onload>在High等级下直接失效。看起来防护更强了,但DOM型XSS真正的问题并没有解决:前端JavaScript还是老代码,还在读location.href,还在用document.write。

这个阶段最需要的是冷静梳理还有哪些标签和属性可以携带并执行JavaScript。黑名单管得住已知的坏字符,但管不住组合变形。

5.2 换一个执行通道:iframe配合伪协议

如果事件属性被拦了,可以试着用javascript:伪协议。iframe标签的src属性可以指向一段javascript:协议的代码,浏览器在加载iframe时会执行这段JavaScript。payload长这样:

<iframe src="javascript:alert(1)">

这个payload里没有<script,没有on开头的事件属性,可以绕过上面那种关注黑名单的过滤规则。在High等级下构造完整URL访问:

http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=<iframe src="javascript:alert(1)">

刷新页面后,iframe被写入DOM,浏览器尝试加载src指定的内容,JavaScript执行,弹窗出现。

5.3 hash绕过依然是杀手锏

High等级下最省事的通关方式,依然是把payload放到#后面。因为服务端的正则再强,也只能检查它自己收到的HTTP请求参数,而hash部分压根不会出现在请求里。构造下面这个URL:

http://127.0.0.1/dvwa/vulnerabilities/xss_d/#default=<img src=x onerror=alert(1)>

页面刷新后,前端JS从location.href中截取payload,document.write触发img加载失败,onerror弹窗。即使DVWA在High等级下已经把事件属性写进了黑名单,这条payload依然有效,因为服务端连等于都没看到,正则根本没有机会执行。

这给了我们一个重要启示:服务端过滤对DOM型XSS只有在“前端读取的数据恰好是服务端能验证的数据”时才有点用。一旦前端数据源包含location.hash、window.name、document.referrer这类服务端看不到的入口,服务端过滤就会完全失效。

5.4 各等级下payload存活情况速查

payloadLowMediumHigh说明
<script>alert(1)</script>弹窗被拦被拦黑名单重点关照对象
<img src=x onerror=alert(1)>弹窗弹窗视版本可能被拦事件属性被拉黑后失效
<svg onload=alert(1)>弹窗弹窗视版本可能被拦同上
<iframe src=javascript:alert(1)>弹窗弹窗弹窗不含script、不含on事件
#default=<img src=x onerror=alert(1)>弹窗弹窗弹窗服务端看不到hash,绕过滤

这张表不一定在所有DVWA版本里完全一致,因为不同版本High等级过滤规则有小差异,但核心结论是稳定的:payload解法越多,越能理解DOM型XSS的绕过本质。

6. Impossible等级:看看什么叫做“治本”

6.1 白名单 + 服务端渲染,才是真正的修复

切到Impossible等级后,正常访问xss_d模块,再试前面那些payload。你会发现无论把payload放在query里还是hash里,页面都不再执行脚本,连URL都会被重置回?default=English。

查看Impossible源码,根因就很清楚了:

if (array_key_exists("default", $_GET) && !is_null($_GET['default'])) { $default = $_GET['default']; // 白名单,只允许预定义的语言 switch ($default) { case "English": case "French": case "German": case "Spanish": case "Portuguese": case "Chinese": break; default: header("location: ?default=English"); exit; } }

这一版不再试图识别坏payload,而是直接规定什么值是合法的。不是English、French、German等预设语言之一,就强制跳回English。黑名单和正则再长也有穷举不完的变形;白名单直接缩小到几个固定值,攻击者输入的字符串从一开始就不在允许名单里,注入无从谈起。

6.2 前端代码彻底放弃了location

更重要的是,Impossible等级的前端代码也不再从document.location.href里读取语言值了。select下拉框的选项是服务端写死的静态HTML,JavaScript最多做一下UI交互,不会把URL参数当成HTML写入页面。危险接口document.write被移除,用户可控数据没有一个输入源能流向它。

我在本地试过各种绕过思路:改成#default=、URL编码变体、大小写变形、用iframe伪协议,全部无效。原因很简单——输入源被白名单卡死在服务端,DOM写入接口的危险调用被移除。两层防御叠加,DOM型XSS的执行链彻底断掉。

6.3 Impossible的防御思路值得抄进真实项目

看完了Impossible等级的写法,再回头看前面三个等级的源码,可以总结出一个非常清晰的修复套路:服务端做白名单校验,客户端避免将不可信数据写入HTML接口。两件事里只要做到任何一件,这种漏洞就基本堵住了;两件都做,才能算真正的治本。

另外,Impossible等级还体现了“默认拒绝”的安全思想。它不试图预测所有攻击payload,而是把默认行为设为拒绝,只放行明确允许的值。这个思路在处理其他安全问题时同样适用:与其穷举黑名单,不如用白名单把风险边界画出来。

7. 从一通到底,追溯DOM XSS的本质

7.1 为什么服务端过滤对DOM XSS只能“碰运气”

把四个等级全部通关之后,我最大的体会是:DOM型XSS的核心矛盾在于,攻击代码在客户端执行,但很多人习惯在服务端做防御。服务端能看到的只是HTTP请求的一部分,而前端JavaScript能读到的数据范围更广,包括URL的hash、window.name、document.referrer等。

只要前端代码存在“读取不可信数据 → 写入DOM”的链路,服务端不管做多少过滤,都只是在入口处设关卡。可攻击者可以换一条服务端看不到的入口进来,也可以在出口处换一种标签、属性、编码方式躲过特征检查。这也是为什么DOM型XSS在真实项目中看起来很“轻”,调起门槛不高,但检测和修复却经常踩坑。

7.2 常见输入源与危险输出接口

做DOM型XSS审计时,我习惯先列一张表,把输入源和输出接口分别找出来,再沿着数据流看中间有没有净化。常见的输入源包括:

输入源说明
location.href完整URL,包含query和hash
location.searchURL的query部分
location.hashURL的hash部分,服务端不可见
document.referrer来源页面URL
window.name浏览器窗口名,可跨页面传递
postMessage父页面与iframe之间的消息传递

常见危险输出接口包括:

输出接口风险说明
document.write/writeln直接把字符串交给HTML解析器
element.innerHTML/outerHTML解析并生成DOM元素
insertAdjacentHTML类似innerHTML的解析行为
eval把字符串当JavaScript代码执行
setTimeout/setInterval传字符串同样会执行字符串代码
location/location.href赋值可触发javascript:伪协议

如果一条数据流里,输入源可控并且没有可靠编码或白名单校验,输出接口恰好是这些危险API,那DOM型XSS基本可以判定存在。

7.3 修复建议:白名单、编码、避免拼接

从DVWA的Impossible等级可以推导出一套完整修复方案。服务端入口处,对参数做严格白名单校验,拒绝预期格式之外的所有值。前端代码里,不要用document.write或innerHTML拼接用户可控数据;需要动态渲染文本时,用textContent赋值,或者使用createElement、appendChild这类不会解析HTML的DOM操作。

如果业务上必须使用innerHTML,也需要先对数据做HTML实体编码。前端框架在默认情况下会对插值表达式做转义,所以很多使用现代框架的项目能把XSS风险压得很低,但一旦项目里出现v-html、dangerouslySetInnerHTML这类直接插入HTML的API,就需要格外小心。

7.4 把思路从靶场延伸到实战审计

通关DVWA后,我建议你用同样的思路去审一审自己参与过的前端项目。全局搜索项目代码里的document.write、innerHTML、insertAdjacentHTML、eval,对每个命中点追一下数据来源:这个变量来自网络请求吗?来自URL参数吗?中间有过滤或编码吗?有没有经过白名单校验?

有一次我在一个内部系统的前端代码里看到location.hash被直接拼进innerHTML,当时所有人都在关注服务端接口的输入校验,没人注意到前端还有这样一条数据流。后来用DVWA里学到的hash绕过思路去验证,果然是DOM型XSS。这种场景在真实项目里并不少见,因为服务端接口容易统一治理,前端散落的DOM操作很容易被遗漏。

8. 通关过程中最常见的坑与排查思路

8.1 常见问题速查表

在我反复打DVWA DOM XSS模块的过程中,遇到过不少看起来“灵异”的现象,整理成下面的速查表,供你排查时参考:

现象可能原因解决办法
改了default参数,下拉框没变化安全等级还在Impossible去DVWA Security页面切到对应等级
弹窗没出现,URL被跳回English服务端黑名单拦截检查当前等级,换绕过payload或改用hash
<script>标签在Medium被跳转服务端用stripos过滤了<script改用<img onerror>、<svg onload>等
引号、尖括号粘贴到地址栏后显示混乱浏览器自动转码导致URL不直观直接粘贴原始payload让浏览器处理,或预先用encodeURIComponent编码
hash绕过时页面不执行hash里的payload编码不正确确保payload在URL里是合法编码,不要出现未编码空格
登录后等级设置不生效会话过期或页面缓存重新登录,重新进入模块
明明用img标签却弹不出某些版本High把on事件拉黑换iframe伪协议或hash绕过

8.2 提升效率的调试思路

第一个建议是直接用浏览器开发者工具控制台调试payload。在Console里输入document.location.href = "http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default=...",回车即跳转,比手动复制粘贴地址栏更快。想反复测试不同payload时,可以在Console里维护一个payload列表,逐个赋值给location.href,观察页面行为。

第二个建议是善用源码审计。DVWA源码文件每个等级是独立的,切到对应等级后打开对应源码文件,用最快速度找到JavaScript里读location和调用document.write的位置,就能判断当前等级的过滤范围和可绕过方向。与其盲试payload,不如先看代码再猜解法。

第三个建议是注意浏览器的编码行为。浏览器地址栏会自动把非URL合法字符转成百分号编码,这是正常现象。前端JS里的decodeURIComponent会把编码还原,所以很多看起来乱码的URL实际执行时依然有效。关键是不要因为你“看不懂”地址栏里的payload就以为它失效了。

8.3 为什么会漏判DOM型XSS

最后我想单独说一个现象:很多人在做安全测试时习惯只看服务端响应包,发现响应的HTML里没有注入点就判断没有XSS,结果漏掉了DOM型XSS。判断DOM型XSS的正确姿势是,先看页面加载后的实际DOM结构,再看前端JavaScript是否把URL里的数据动态写入了页面。浏览器开发者工具的Elements面板能直接看到document.write生成的内容,Network面板反而看不到。

如果你在做某次测试时发现页面出现了预期外的DOM节点,但响应包里没有对应字符串,第一反应就应该是“这里有DOM型XSS”。反过来,如果你在某个页面里发现了DOM型XSS,再去看服务端日志,日志里也未必有攻击痕迹,因为攻击可能一直藏在hash里。这个经验在做安全监控和应急响应时尤其重要。

最后再分享一点心得体会

通关完DVWA的DOM XSS模块之后,我自己的收获并不只是几个payload,而是重新理解了“数据与代码区分”这个安全原则。DOM型XSS最典型的特征,就是太多人把它当成“字符串处理问题”,而不是“代码执行问题”。当你看到前端代码把一个字符串拼进HTML时,你就应该意识到:这个字符串不再只是数据,它马上就要变成页面代码了。

以我个人的习惯,拿到一个前端安全任务时,我一般会先从危险输出接口反向追数据流,找到所有可能进入这些接口的输入源;服务端能做校验的地方尽量用白名单做限制;前端代码能避免拼接HTML的地方就优先用textContent这类安全接口。DVWA只是把这些攻防逻辑压缩在一个小靶场里,让你用最直观的方式体验一遍。

如果你现在已经把Low到Impossible全部打通,我建议你回到源码文件,自己改一版防御代码:比如在Level High的基础上再增加一层过滤,或者在Medium的基础上移除document.write改用安全的DOM接口,然后重新测试原来的payload能不能绕过。这个过程比单纯通关节奏更有价值,因为你在练习的是攻防双方都需要的思考方式:永远比对方多想一步。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 7:20:54

Llama 3 架构精读:词表扩容、GQA 与 FP8 量化长上下文实测

1. 为什么值得花时间精读 Llama 3 的架构细节Llama 3 发布之后&#xff0c;我身边不少做推理部署的朋友第一反应是"又来了一个新模型"&#xff0c;第二反应才是"这次架构上到底改了什么"。说实话&#xff0c;如果你只是调用 API 或者跑个现成的对话 Demo&a…

作者头像 李华
网站建设 2026/10/20 7:20:53

棉田虫害轻量化检测:从数据采集到边缘部署全流程实战

种地的都知道&#xff0c;棉田虫害发现晚一周&#xff0c;产量损失就补不回来。我前两年跟着某农业示范基地的植保团队做课题&#xff0c;天天蹲在田里拍虫子、数虫子、被棉铃虫折磨到头秃&#xff0c;最后落地了一套基于深度学习的棉田虫害轻量化检测系统。说它"轻量化&q…

作者头像 李华
网站建设 2026/10/20 7:20:52

Unity传送失效之谜:从物理引擎到刚体休眠的完整排查指南

1. 传送失效&#xff1a;一场由物理引擎引发的"灵异事件"先跟你讲个真实场景&#xff1a;某天你写好了传送代码&#xff0c;transform.position new Vector3(...)一行搞定&#xff0c;测试时角色也确实瞬移过去了。但下一帧&#xff0c;角色要么被弹回原地&#xff…

作者头像 李华
网站建设 2026/10/20 7:20:14

MTCNN人脸检测完整实现:P-Net/R-Net/O-Net三级级联详解

简介&#xff1a;本资源是一套基于MTCNN&#xff08;Multi-Task Cascaded Convolutional Networks&#xff09;实现人脸检测的完整开源代码工程&#xff0c;面向深度学习初学者、计算机视觉方向学生及人脸相关应用开发者&#xff0c;解决从模型构建、训练到推理部署的一站式实践…

作者头像 李华
网站建设 2026/10/20 7:19:59

Virtuoso ADE L用户指南翻译实战:模拟IC仿真流程与高频功能详解

接到Virtuoso ADE L用户指南翻译任务时&#xff0c;我第一反应是&#xff1a;这活儿可不好干。作为天天泡在模拟IC设计里的工程师&#xff0c;ADE L这个窗口我几乎每天都要点开&#xff0c;但真要把厚厚一本英文用户指南逐字翻译成中文&#xff0c;等于把平时闭着眼都能操作的界…

作者头像 李华
网站建设 2026/10/20 7:19:54

LeetCode 121详解:从暴力到贪心,Java实现买卖股票最佳时机

我记得很清楚&#xff0c;第一次看到“买卖股票的最佳时机”这道题时&#xff0c;我还在按部就班地刷LeetCode热题100。当时群里有人说这题“秒了”&#xff0c;我心想估计又是那种背个模板就能过的题。结果自己动手一写&#xff0c;暴力解法提交直接超时&#xff0c;吓得我赶紧…

作者头像 李华