安全基础系列写到这里,终于到了很多人又爱又怕的部分——网络攻击行为背后的主要算法。这里先说明一下:算法不是指密码学里的AES、RSA这类加解密算法,而是攻击者在侦察、突破、传播、隐蔽这条完整行为链路上实际使用的计算方法与策略。通俗点说,这篇文章想回答一个问题:攻击者动手之前、动手之中、动手之后,脑子里到底在算什么?
很多人刚开始接触安全领域时,第一反应往往是去学工具、记命令、背漏洞编号。这没错,但如果你只停留在这一层,很快就会撞上瓶颈——工具会迭代、参数会变化、利用场景也在变,唯一相对稳定的是藏在底层的算法思路。在信息科学与工程学的安全课程体系里,这也是从“看热闹”走向“看门道”的分水岭。
这篇文章适合三类人:刚入门安全方向的学生、准备安全相关认证的备考者,以及已经在做安全运营或运维、想补强攻击视角的工程师。我会把攻击行为里常见的算法按类别拆开讲,包括它们解决什么问题、核心的计算逻辑、对防御方的启示,以及我在实际安全观测中沉淀的一些经验。需要提前说明,内容聚焦算法原理和教育目的,不提供具体的漏洞利用操作指南——理解原理,远比背一条攻击命令更值钱。
1. 攻击行为中的算法思维:攻击者到底在算什么
1.1 攻击本质是一次有约束的搜索
先说一个我反复跟同事强调的观点:绝大多数网络攻击,本质上是一个在巨大可能性空间里做搜索的过程。攻击者在找一条能突破防御、又尽量不容易暴露的路径,就像在迷宫里找出口,而每个岔路口都有代价。暴力破解是在搜索口令空间,漏洞利用是在搜索可控的内存布局,横向移动是在搜索权限路径,甚至免杀变形也是在搜索“检测规则之外”的代码形态。这些全都是搜索,也就都能用算法的语言去描述和分析。
这个视角对防御方特别重要。如果你理解了攻击者是在做有约束的搜索,你会明白为什么有些安全加固看起来挺全面,却还是被拿下了——不是攻击者运气好,而是他在局部做了取舍:与其死磕一个强口令,不如花时间找一条更省力的搜索路径,比如先探测一个低版本组件,再顺手拿到某台闲置机器的权限。攻击者的搜索策略,基本决定了整个安全对抗的节奏。
防御方如果只会堆砌安全设备,不去研究攻击者的搜索路径,很容易出现“设备买了一堆、却没装在关键路径上”的尴尬。我见过不少场景,单位花重金采购各种安全设备,最后却被很简单的口令攻击打穿。原因其实不复杂:攻击者的搜索路径,根本没有经过那些设备重点盯防的区域。所以我说,理解搜索算法的本质,防御才可能走在攻击前面,而不是等攻击者进了门才开始响警报。
1.2 攻击算法的四大类别
结合我日常观察到的实际攻击行为,可以把攻击背后常用的算法归纳成四个大类:
- 穷举搜索类:不依赖系统内部细节,用算力换概率,典型是口令破解、字典攻击、掩码攻击、彩虹表预计算。
- 结构利用类:利用内存布局、协议格式、数据处理流程里的固有结构,典型是缓冲区溢出控制、返回导向编程、协议解析绕过。
- 传播扩散类:研究如何让恶意代码以最优速度感染更多节点,典型是蠕虫扫描策略、批量漏洞利用的扩散节奏。
- 隐蔽优化类:在“被发现的概率”和“达成目标的收益”之间做多目标优化,典型是免杀变形、流量隐藏、时间规避。
这个分类不追求严格的学术边界,更多是我用来快速给一次攻击行为定性的实用框架。拿到一份攻击日志,我会先问自己几个问题:这是哪一类算法在起作用?它的搜索空间是什么?约束条件是什么?最优解大概长什么样?把这些问题想清楚,防御优先级自然就出来了。比如遇到可疑流量,先判断它是穷举搜索还是隐蔽优化,应对策略是完全不同的——前者拼的是速率,后者拼的是形态。
| 算法类别 | 典型场景 | 核心目标 | 防御要点 |
|---|---|---|---|
| 穷举搜索 | 口令破解、批量撞库 | 在候选空间中寻找匹配项 | 扩大空间、放慢单次校验 |
| 结构利用 | 漏洞利用、内存操控 | 操纵固有结构达成逻辑跳转 | 内存保护、控制流校验 |
| 传播扩散 | 恶意代码批量感染 | 最大化有效传播范围 | 隔离、补丁、突发流量检测 |
| 隐蔽优化 | 免杀、隐蔽通信 | 收益与暴露风险的最优平衡 | 行为分析、异常统计建模 |
2. 暴力破解类算法:穷举与优化的对抗
2.1 口令空间计算:先算清楚搜索范围有多大
暴力破解算法的起点,是对口令空间做一个数量级估算。口令可以看作一个字符串,它的理论空间等于“字符集大小”的“长度”次幂。比如纯数字8位,字符集是10,空间就是10的8次方,一亿种;如果换成大小写字母加数字共62个字符集的8位口令,空间就是62的8次方,大约是2.18乘以10的14次方。两者相差约218万倍,对应的穷举时间也几乎是同比例增长。
我把常见的口令格式和理论空间对比如下,大家可以直观感受一下数量级的差距:
| 口令格式 | 字符集 | 长度 | 理论空间 | 相对8位数字口令 |
|---|---|---|---|---|
| 8位纯数字 | 10 | 8 | 约1×10^8 | 基线 |
| 8位小写字母 | 26 | 8 | 约2.09×10^11 | 约2088倍 |
| 8位大小写+数字 | 62 | 8 | 约2.18×10^14 | 约218万倍 |
| 12位大小写+数字+符号 | 95 | 12 | 约5.40×10^23 | 千亿亿倍级别 |
看这张表,还得理解攻击者不会傻乎乎地从头穷举。真正的优化在于“先试什么”:现实中大量口令都是弱口令,或者基于个人信息做的低强度变形。最有效的攻击算法是把历史泄露的口令数据做统计分析,排出一个高概率候选列表,先按列表试一遍,再用规则批量衍生——比如加年份后缀、替换大小写、替换常见字符。这就是典型的概率优先搜索,比均匀穷举高了几个数量级的效率。
从防御角度看,这个算法思路直接解释了两件事。第一,口令长度和字符集复杂度的确重要,因为它们成倍扩大了搜索空间;第二,光复杂还不够,必须避免使用任何出现在历史泄露名单里的口令,因为攻击者的搜索队列是根据真实泄露数据排序的,你的口令哪怕是“某规则+”年份”的变体,也可能正好落在高概率区。我给某单位做口令安全评估时,最常看到的问题不是口令太短,而是全单位口令高度同构——都是“首字母缩写+生日+固定符号”这种模式,规律性越强,概率优先搜索就越高效。
2.2 字典攻击、掩码攻击与彩虹表:不同约束下的优化
暴力破解家族里,除了最原始的穷举,还有几个经典变种值得单独拿出来讲。
字典攻击就是拿现成的口令字典去试,词典来自历史泄露数据和公开语料。它的搜索空间小、匹配速度快,但对“非主流”口令无效。这里要理解一个点:字典攻击的成功率,本质上反映的是用户的“可预测性”,只要口令是从人类语言或常见习惯里生长出来的,字典就永远会有一定命中率。
掩码攻击则是攻击者掌握了部分格式信息后的优化。比如某单位历史口令总是“年份+单位缩写+四位数字”,攻击者一旦知道这个规律,就可以设置掩码把搜索空间从全空间压缩到特定模式。这种攻击也提醒我们:口令策略的泄露、弱口令样例的公开,都在无意中向攻击者输送了搜索线索。
彩虹表则做的是时间与空间的经典交易。口令哈希破解中,每次计算完哈希再比对,耗时太久;把所有明文和哈希的对应关系全存下来,空间又不可接受。彩虹表的思路是用一条条哈希链把明文和哈希压缩,只在链首和链尾存值,破解时根据链的推进快速找到候选明文。它把“计算换空间”扭成“空间换时间”,但软肋也很明显:依赖固定的哈希算法,一旦系统给每个口令加了随机盐,同一口令在不同盐值下的哈希完全不一样,彩虹表就基本失效。这也是加盐能成为现代口令存储标准做法的原因。
我讲口令攻击时喜欢打一个比方:穷举是把所有钥匙都试一遍,字典是拿一本“最常见钥匙清单”优先试,掩码是知道钥匙大致形状后只试形似的那批,彩虹表是提前做了一本巨型索引只翻目录就能加速查找。理解了这些,你就明白为什么安全基线里总在强调“不要使用公开规则的简单变体”。
2.3 从暴力破解算法反推的防护策略
暴力破解的对抗,远不止“口令设复杂点”这一层,从算法角度能推出几条非常实用的防护策略。
第一是抬高单次尝试的代价。常见做法是使用带工作因子的慢哈希算法,故意让每次口令校验消耗几十到几百毫秒。这样攻击者即使拿到了哈希库,每秒能尝试的候选数也会大幅下降。第二是引入随机盐,让每个口令的哈希独立计算,破坏预计算和彩虹表。第三是限速与锁定策略:从算法视角看,这是直接限制了搜索的单位时间查询次数,相当于把穷举吞吐量按死。
我踩过的坑也必须分享:早期做安全评估时,我只验证了口令复杂度策略,却忽略了对后台哈希算法的检查,结果发现某系统虽然在策略文档里写着“口令长度不得少于10位”,实际存储仍在使用早期快速哈希算法。一旦哈希库泄露,配合硬件加速,攻击者可以做到每秒上亿次的口令尝试,再长的口令也扛不住这种吞吐。所以安全评估不能只看策略文档,还要看算法落地后的真实时间成本、空间成本和硬件加速潜力。
3. 网络侦察阶段的扫描算法
3.1 端口扫描:利用TCP状态机的算法设计
攻击者要入侵一台主机,第一步往往是侦察目标网络,看看哪些端口开放、背后跑着什么服务。端口扫描算法本质上是利用TCP/IP协议栈的状态机做探测。以TCP端口为例,最简单的全连接扫描会完整走一遍三次握手,服务端响应“连接成功”就说明端口开放。可这种方式会在目标系统留下完整的连接日志,隐蔽性差。
更隐蔽的SYN半连接扫描只发送SYN包,收到SYN+ACK就判定端口开放,紧接着回一个RST包断开连接,不完成三次握手。从算法角度看,这是利用TCP状态机的特性,既减少了握手开销,也降低了日志暴露。扫描加速的常见优化则包括提高并发度、合理设置超时重传、对目标网段做随机化而非顺序遍历。随机化尤其关键——它能让基于线性的异常检测模型更难抓到规律。
我把三种常见扫描方式放在一起对比:
| 扫描方式 | 握手过程 | 日志痕迹 | 速度 | 隐蔽性 |
|---|---|---|---|---|
| 全连接扫描 | 完整三次握手 | 明显 | 较慢 | 低 |
| SYN半连接扫描 | 仅发送SYN并快速RST | 较轻 | 较快 | 中 |
| 慢速随机扫描 | 低频随机探测 | 很低 | 最慢 | 高 |
扫描者在隐蔽性和覆盖完整性之间做的取舍,本质上就是一组算法参数的博弈。安全运营里,识别“有人在扫描”不难,难的是判断扫描的下一步意图——是想批量找弱口令,还是在精准探测某个特定漏洞。结合扫描速率和目标端口的频谱分布,往往能猜个八九不离十,这才是分析的价值所在。
3.2 指纹识别与匹配算法的博弈
开端口只是第一步,攻击者还要知道端口后面跑的是什么服务、什么版本,才能决定下一步用哪种攻击手法。这一步就靠指纹识别算法。传统方法包括抓取服务Banner字符串做正则匹配、对常见路径发起请求看响应特征,核心是模式匹配。匹配算法说白了就是特征工程:哪个特征最稳定、最不容易被伪装,就用哪个特征来识别。
现在这个环节的攻防已经升级了。防御侧的资产识别系统开始用机器学习:不只盯单一路径的响应,而是把HTTP响应头、TLS握手参数、证书信息、页面结构组合成高维特征,再用分类模型判断服务类型和版本。攻击侧也会用分类模型做更隐蔽的探测,尽量减少“特征请求过于明显”而触发告警。这是一场特征构造和特征检测的持续博弈,两边都在不断优化自己的特征集。
防御方在这个环节能做的,是收敛服务暴露面、关闭不必要端口、升级到不再被轻易识别的软件版本,并对对外服务的响应特征做一些脱敏处理。因为不管识别算法怎么进化,只要你暴露的服务数量足够少、指纹足够普通,攻击者的搜索空间就足够大,侦察成本就足够高。
3.3 从防御日志识别扫描算法特征
对付扫描攻击,先要能认出它的算法特征。我在安全运营里总结过几个实用观测点:如果某个源IP发起大量SYN请求、目标端口连续递增、目标主机地址也呈顺序变化,这基本是线性的顺序扫描。如果目标地址分布很随机、端口集中在少数常用端口、总体流量不高,可能是刻意放慢节奏的随机扫描。
要量化识别,可以统计每个源IP的连接请求速率、目标端口集合的信息熵、目标地址分布均匀度,再配合阈值和基线模型,就能把“像扫描”的行为从正常访问流里分离出来。算法对抗最后往往沉淀为统计特征的博弈,这个结论在很多行为分析平台上都成立。运营人员不需要理解每个模型的内部细节,但要理解思路:正常流量有正常的统计规律,异常扫描会在某个维度上偏离基线,找到那个维度才是关键。
4. 漏洞利用阶段的算法设计思路
4.1 内存布局控制与指令流引导的核心算法
漏洞利用是攻击行为里技术含量最高的部分。以经典的栈缓冲区溢出为例,当程序向栈上固定大小的缓冲区写入超出容量的数据时,多余数据会覆盖相邻的栈内存,其中就包括保存的返回地址。攻击者构造恶意输入的算法目标,是让被覆盖的返回地址指向一段可控代码,或者指向系统中已有的特定指令序列。
现代操作系统普遍开启了数据不可执行(NX)防护,单纯把代码放进栈里执行已经很难奏效,于是出现了返回导向编程(ROP)思路:程序自身就包含大量以ret指令结尾的代码片段,攻击者把这些片段筛选出来、按顺序拼接,就能组装出想要的逻辑。构造ROP链本质上是拼图搜索——在程序二进制中寻找可用的指令片段,排列组合成目标功能。这个搜索有专门的自动化工具辅助,但搜索空间巨大,性能优化是实用化的关键。
理解这套算法,防御者才能真正看懂内存防护的价值。地址空间随机化让攻击者不知道关键地址落在哪;栈保护值会在返回地址被覆盖前主动触发检测;控制流完整性则在程序试图跳转到非法地址时直接终止。每一条防护措施,本质上都在增加攻击者构造和搜索链的难度。想做好安全加固,不能只看漏洞编号,要看攻击者在内存布局搜索里卡在哪个环节。
4.2 权限提升与横向移动中的图搜索思想
当攻击者已经拿下某一台主机,接下来的目标往往是在内部网络中寻找权限提升和横向移动的路径。这个阶段非常适合用图来建模:节点是主机、账号、服务,边是访问关系、信任关系、可利用的条件。攻击者要解决的是图搜索问题——找到一条从当前节点到目标节点的可行路径。
经典的图搜索算法在这里有两个应用方向。广度优先搜索优先找跳数最少的路径,适合快速判断“最短能走几步到目标节点”;带权最短路径则把每条边赋予一个代价,比如利用难度、被检测风险、时间成本,然后寻找总代价最小的路线。实际攻防中,攻击者选路时会反复权衡,有时宁可多跳几步,也要避开高检测概率的节点。
防御端的应用是同一个图的反向剪枝。我建议安全团队定期梳理内网信任关系图,删除那些不必要的“边”——比如某台普通工作机居然有管理员的登录凭据,这就是一条让攻击者一步跳上顶层的捷径。用图分析工具把这些隐藏捷径找出来、断掉,比盲目追求“全端口封闭”高效得多。
4.3 利用链的串行与并行规划
现实中的攻击很少靠单个漏洞一蹴而就,更多是把几个小弱点串联成一条利用链。构造利用链的算法思路,和项目排期很类似:先列出所有可利用的弱点和前置条件,再按依赖关系排序,能并行的并行,必须串行的串行,最终形成从初始入口到最终目标的联动路径。
我参与过的一些内部模拟项目里,攻击链某个环节一旦失败,会自动回溯上一个决策点、换一个备选方案重试。这种带状态回退的搜索结构,本质上就是图搜索里的回溯算法。防御方做加固时,最忌讳只修单点漏洞、不看链路。正确的做法是站在攻击者的视角做一遍利用链推演,找出链路里每个可以下探针的位置,哪怕某个环节暂时修不了,也要在链上增加一个检测点,让攻击者的每一步都付出可被记录的成本。
5. 恶意程序传播与隐蔽对抗算法
5.1 从传染病模型看恶意代码的传播扩散
恶意代码在网络里的扩散,在数学上可以抽象成传染病模型。把主机分为易感主机和已感染主机两类,感染速率大致正比于两类主机数量的乘积。这意味着传播初期会有一段指数上升期,之后随着易感主机减少而进入饱和。理解这个模型,最大的价值是提醒你:在传播早期如果不及时隔离和打补丁,后面要花的阻断成本会指数级增长。
扫描式传播是这类模型的典型实现:顺序扫描逻辑简单,但从日志看规律太明显;随机扫描利用随机数生成器产生目标地址,不依赖先验情报,但会耗费大量网络带宽。正是因为这些传播算法存在明显的流量统计特征,防御方才能在网关和主机层做突发流量检测,一旦发现异常扫描,自动把异常节点隔离,直接截断传播链路。
我在内部演练里做过一次简化实验:在实验网络里首次发现异常连接后,如果人工响应延误几个小时,受影响的主机数量会差一个数量级。从那之后我坚定了一个看法——针对传播类攻击,人工响应速度是跟算法速度赛跑,唯一可行的对冲手段就是自动化应急响应。
5.2 多态与变形:让样本“认不出来”的算法
恶意样本要规避基于签名的检测,最常依赖的是变形算法。多态引擎每次生成样本时,会对载荷做不同的加密和编码,使每次生成的字节序列都不同,但运行时能够还原出原始逻辑。更进一步的是变形引擎,它在指令层做等价替换——把一条指令换成逻辑等价但字节完全不同的多条指令组合,再插入一些无意义操作码做干扰。
从算法角度,变形对抗的是“相同性匹配”:签名检测的前提是样本具有稳定的特征字节,变形算法直接破坏了这种稳定性。于是防御侧逐步转向行为检测,不再只看样本静态长什么样,而是观察它运行之后做了什么。这正是整个恶意代码对抗从特征匹配走向行为分析的根本原因。理解了这个演变,你就能明白为什么有些检测平台特别强调沙箱能力。
5.3 信息隐藏算法:把数据藏进看似正常的载体
攻击活动的隐蔽通信,经常用到信息隐藏算法。一张看起来完全正常的图片,可以通过最不重要位算法把秘密数据写进像素的最低几位,人眼几乎感知不到变化;一份普通文本里的标点、空格、格式可以被编码成数据载体;网络协议的某些字段也能被改造成隐藏信道。
这类算法给防御带来一个独特难题:单看内容看不出异常,因为载体本身合法。防御思路往往转向统计特征建模——比如数据包的到达间隔是否符合应用正常规律、图片噪声分布是否符合自然图像的统计特性。我在做数据泄露防护评估时经常提醒团队:只检查明文敏感词远远不够,对异常信道行为的统计建模才是这类对抗的核心。
6. 常见问题与排查技巧实录
6.1 我见过的算法理解误区
先说三个我个人特别有感触的误区。
第一个误区是觉得暴力破解很初级、“没技术含量”。实际情况恰恰相反,结合概率排序、掩码生成、硬件加速的破解攻击,是门非常讲究的工程优化。防御方如果低估它的威胁,弱口令就会长期潜伏在系统里。
第二个误区是“背下算法名就等于学会了”。好多人把算法过程背得滚瓜烂熟,却在一次实际的协议误配置面前看不出问题。算法知识必须通过动手实验才能变成直觉,光靠看书是不行的。
第三个误区是只关注攻击算法、不关注防御算法。实际上两者是同一个硬币的两面,不理解攻击面就无法设计出有说服力的防御面,不理解检测算法也无法判断一次攻击的隐蔽程度究竟有多高。我建议把进攻和防御两条线并行学习,而不是只盯着其中一边。
6.2 学习攻击算法的实用路径
想去深入理解攻击算法的人,我分享一条经过验证的学习路径,分三个阶段推进。
第一阶段是复现观察:在完全隔离的实验环境里搭建靶场,用无害的样本和模拟系统,逐个观察攻击算法的输入、输出和中间过程。重点是慢动作分析,而不是追求速度。第二阶段是日志反推:拿脱敏后的防御设备告警日志做材料,尝试还原攻击者用到了哪种搜索或构造策略。这个过程很锻炼人,因为日志通常不完整,你需要用推理把证据链补全。第三阶段是参数调优:对同一种算法,改不同参数、换不同约束跑几轮对比结果,你才能真正理解复杂度的含义。
这条路径不依赖高配设备,一台普通实验机就能完成前两步。前提是坚持只做学习性研究,不针对任何真实系统做未授权测试——这一点既是职业操守,也是红线。
6.3 把算法知识落地到日常安全的实操心得
最后分享一个我一直在用的落地方法。每隔一段时间,我会给自己安排一次“算法视角复盘”:挑出最近半个月里最值得关注的安全告警,反复问自己——这个攻击者的搜索空间是什么?他使用的是穷举、结构利用、传播扩散还是隐蔽优化?我当前的检测策略有没有把它的搜索成本拉高?如果他换个参数重来一遍,我还认不认得出来?
这个习惯的价值在于,它把抽象的算法知识和具体的运营工作连在了一起。一次告警不再只是一个事件编号,而是攻击者算法输出的一个观测点。坚持做下去,你会慢慢形成一种直觉:看到某类流量特征,大概能判断对方在算什么。这种直觉比任何单一工具都值钱。
我个人在陪团队处理了几轮真实攻击告警之后,最大的体会是这样一句话:防御的目的不是证明攻击者不能成功,而是把他们的搜索成本抬到高于收益的水平。理解了算法,你就理解了该在哪里多设一道坎。这几步复盘做下来,你会发现自己看告警的方式都会有变化。