资讯动态

smsBomb 短信轰炸机运行机制完整拆解:一次攻击请求背后的加权调度与多进程并发

发布时间:2026/8/14 2:45:59 来源:尧图企业网站定制
smsBomb 短信轰炸机运行机制完整拆解一次攻击请求背后的加权调度与多进程并发【免费下载链接】smsBomb短信炸项目地址: https://gitcode.com/gh_mirrors/sms/smsBombsmsBomb 是一款用 Python 3 编写的短信轰炸机工具核心思路是利用公开代码仓库中泄漏的短信服务商密钥批量调用阿里云、腾讯云、创蓝 253 等十余家平台的验证码接口。本文不准备罗列它的功能清单而是跟随一次真实的攻击请求从上到下走完命令行解析、插件加载、加权选路、故障降权、多进程并发、进度回传的整条链路把 smsBomb 的内核调度机制讲透。读完之后你不仅能熟练使用它还能自己动手接入一个新的短信服务商。一条命令到一枚验证码先看一次攻击的完整旅行一切从命令行开始。python -m smsBomb实际执行的是smsBomb/__main__.py它只做一件事——调用cli.main()from smsBomb import cli if __name__ __main__: cli.main()进入cli.main()后程序按顺序完成四步准备工作扫描插件目录调用smsBomb.load_plugins(plugins)利用pkgutil.iter_modules遍历plugins/目录下所有.py文件把它们全部动态导入为一个字典key 是插件模块名解析命令行参数parse_command_line()用argparse接收-t目标手机号、-n攻击次数、-p指定服务商、-c配置文件、--process并发进程数、-m自定义短信内容、-v/-vv/-vvv日志级别、-x代理加载配置文件load_config(args.config, args.product)读取config/sms.json若指定了-p则只过滤出对应产品的配置项组装轰炸机对象并启动把插件字典、配置列表、目标手机号塞进SmsBomb构造函数最后调用sms_bomb.start()。sms_bomb smsBomb.SmsBomb(sms_plugins, config, args.target, process_numargs.process_num, msgargs.message, limitargs.times, prefixplugin_prefix, proxiesproxies) sms_bomb.start()这段代码是整条链路的总闸门。SmsBomb是核心类start()则是它的主循环——后面三节讲的所有调度逻辑都发生在这个while循环里。CLI 版本启动后终端会立刻输出彩色日志逐步展示攻击进度图中可以看到典型的日志节奏DEBUG级别打印请求细节INFO级别记录插件调用与 API 响应最后输出攻击完毕成功 X 次失败 Y 次的汇总。加权随机选路weight 字段如何决定下一个短信节点smsBomb 最核心的设计是把所有短信配置当作一组可以随机挑选的节点。打开config/sms.json你会发现它是一长串 JSON 数组每个元素代表一个可用节点例如{ product: netease, desc: 网易短信验证码, auth: { app_key: d5275854a775369121a2e80536a5884b, app_secret: a3a5477f8b97 }, payloads: { templateid: 3992639 }, weight: 10 }注意weight字段它是调度的核心。start()主循环每轮要发一条短信时都会调用_random_weight_select()挑选下一个节点def _random_weight_select(self): weight_lst [[k, v.copy()] for (k, v) in enumerate(self.config_lst) for _ in range(v.get(weight, 1))] if weight_lst: return random.choice(weight_lst) return None这行代码很短但很精妙值得逐段翻译enumerate(self.config_lst)给每个配置编号得到(索引, 配置)for _ in range(v.get(weight, 1))把每个配置按权重复制 N 份——权重是 10 的网易节点会被塞进列表 10 次权重默认 1 的节点只出现 1 次random.choice(weight_lst)从这份膨胀后的名单里均匀随机抽取。于是权重越大被抽中的概率越高。这就是 README 中提到的从随机算法升级为加权随机负载均衡。这样设计的好处有两个一是避免所有短信都打在同一家服务商上降低被限流的风险二是让更稳定、更划算的渠道承担更多流量。故障节点自动降权失败越多出场越少短信接口总有挂掉的时候——密钥失效、签名过期、服务商风控。smsBomb 的应对策略不是简单地跳过而是动态降权 失败池回收这是它最值得学习的容错设计。看start()主循环中处理失败的分支if success: success_cnt 1 else: self.logger.warning(节点%s请求失败,尝试降低此配置的优先级,并标记此节点已经失败, current_config) self.config_lst[index][weight] max(current_config.get(weight, 1) - 1, 0) current_config[weight] 1 self.failed_config_lst.append(current_config) failed_cnt 1当一个节点发送失败时程序执行三个动作降权weight - 1且下限为 0。权重归 0 后这个节点就再也不会被_random_weight_select()抽中等于被暂时雪藏复制到失败池把当前配置权重重置为 1追加进failed_config_lst计数failed_cnt 1。如果所有节点都被降权到 0_random_weight_select()会返回None此时主循环进入兜底分支if not cfg: self.logger.warning(没有可用配置可供使用!尝试重置配置列表:%s, self.failed_config_lst) self.re_config(self.failed_config_lst) failed_cnt 1 continuere_config()会把失败池里的配置整体复位重新投入调度同时清空失败池。这带来一个很有意思的循环全部节点失败 → 重置 → 再全部失败 → 再重置……直到触发全局熔断。熔断机制是max_allowed_failed_rateself.max_allowed_failed_rate 0.95 # 最大允许的失败率.超过这个失败率之后会宣告失败主循环条件success_cnt self.limit and failed_rate self.max_allowed_failed_rate保证一旦失败率超过 95%无论成功次数是否达标攻击都会立即终止避免拿着失效的密钥做无用功。多进程流水线与进度回传机制单线程逐条发送太慢smsBomb 用multiprocessing.Pool开了并发的传送带。start()的开头pool multiprocessing.Pool(processesself.process_num)进程数默认 5-p与--process冲突注意进程数参数是--processCLI 里还会做一层保护args.process_num min(args.process_num, args.times)防止攻击次数比进程数还少造成资源浪费。每个子进程执行的是worker函数它只做一件事——把对象 方法名 参数通过getattr反射调用def worker(*args, **kwargs): obj, method_name args[:2] logging.debug( {obj}-{method_name}({args},{kwargs}).format(objtype(obj).__name__, method_namemethod_name, argsargs[2:], kwargskwargs)) return getattr(obj, method_name)(*args[2:], **kwargs)主循环里这样派发任务success pool.apply(worker, args(cls, send, self.target), kwdspayloads)pool.apply是同步阻塞调用当前循环等待这个子进程返回后才继续。这与apply_async的区别在于代码因此能精确地拿到每次发送的成败结果用于上一节的降权与计数——同步换取的是调度准确性这正是传送带式设计的关键取舍。每次发送结束主循环都会调用进度回调cbcb cb if cb else self.progress_info ... cb(success_cnt, failed_cnt, self.limit)progress_info是默认回调用DEBUG级别输出实时进度self.logger.debug(攻击进度(成功数/期望攻击次数): %d/%d %.2f%%, 实际攻击目标次数(含失败): %d(失败%d次, 失败率: %.2f%%), success_cnt, limit, success_cnt * 100 / limit, success_cnt failed_cnt, failed_cnt, failed_rate * 100)这个cb参数也是 GUI 与 CLI 共用内核的桥梁——GUI 只要传入自己的回调就能把进度画成进度条详见后面的双前端章节。插件即插即用十分钟看懂一个短信服务商插件插件机制是 smsBomb 的另一大亮点。load_plugins()通过pkgutil.iter_modules自动扫描plugins/目录这意味着新增一家服务商只需放一个 .py 文件无需改动任何主逻辑。扫描得到的插件名形如smsBomb.plugins.aliyun主循环据此拼出类名cls current_config.get(product).title() Plugin obj self.plugins.get(key) if not obj or not hasattr(obj, cls): self.logger.warning(无此插件:%s,跳过 % cls) continue比如配置里product: aliyun就会去smsBomb.plugins.aliyun模块里找AliyunPlugin类。配置驱动插件选择这是整套架构的松耦合关键。所有插件继承自SmsPlugin基类自动获得requests会话、随机数nonce、时间戳curtime等公共能力。各家差异集中在send()方法里举三个典型阿里云插件plugins/aliyun.py需要实现 HMAC-SHA1 签名先把参数排序拼接再算签名、拼请求体plain_text POST%2F canonicalize(**params) sign self.checksum(plain_text) body Signature{}{}.format(sign, stringify(**params)) self.logger.debug(拼接完成请求体: %s, body) resp self._req.post(self.api, headersheaders, databody.encode(utf-8)).json() self.logger.info(resp) return resp[Code] OK网易云插件plugins/netease.py的鉴权是AppKey 时间戳 随机数 SHA1 校验和四件套每次请求都要现算def checksum(self, nonce, curtime): plain_text {0}{1}{2}.format( self.auth[app_secret], nonce, curtime).encode(utf-8) return hashlib.sha1(plain_text).hexdigest()腾讯云插件plugins/tencent.py更聪明——如果配置里没给模版内容它甚至会调用get_one_tpl()主动查询账号下的短信模版随机挑一条来用if not self.tpl_content: self.tpl_content self.get_one_tpl() self.logger.debug(没有默认的模版消息,随机获取:%s, self.tpl_content)而最通用的plugins/normal.py则是兜底大法不实现任何签名只做模板占位符替换。它把配置 payload 里的{{mobile}}换成目标手机号、{{content}}换成自定义消息内容然后直接 GET/POST 发出去for (k, v) in payloads.items(): if not isinstance(v, str): continue v v.replace({{mobile}}, str(target)) v v.replace({{content}}, {0}{1}.format( kwargs.get(sign_name, ), self.get_msg_content(kwargs, msg)))这套基类统一 子类差异化实现的设计让接入新渠道的成本降到了最低找到泄漏的密钥、照着官方文档写一个send()、在config/sms.json加一条配置完事。双前端CLI 与 GUI 如何共用同一套内核smsBomb 提供两套操作界面但底层逻辑完全复用SmsBomb类。CLI 版由cli.py驱动适合脚本化和调试GUI 版由gui.py基于 Kivy 框架实现适合快速上手。GUI 的妙处在于用回调函数完成前后端解耦。界面上的攻击按钮触发SmsBomber.attack()它收集表单数据后把refresh_progress_bar作为回调传给SmsBomb.start()并且放在独立线程里运行避免卡死 UIthreading.Thread(targetapp.start, kwargs{cb: self.refresh_progress_bar}).start()进度回调里Kivy 的属性绑定机制会自动把数值变化反映到进度条上def refresh_progress_bar(self, success, failed, limit, force_finishedFalse): self.current_attacked_cnt success self.attack_cnt limit if force_finished: self.attack_cnt self.current_attacked_cntGUI 界面的布局目标手机号、消息体、攻击次数、产品选择、进程数、代理、进度条由smsbomb.kv描述文件定义值得留意的是 GUI 传参里的一个小细节attack()中构造SmsBomb时传的键是proxy和times而SmsBomb.__init__读取的是proxy和limit——CLI 用limit传次数GUI 用times传次数。这正是 README 里Kivy 程序并没有经过严格的测试,慎用这句提醒的来源也是排查 GUI 版次数不生效问题时最值得检查的点。常见坑位与三招排错法根据代码注释与 README 已知 BUG 列表实战中最常踩的坑集中在三处坑一配置为空。如果config/sms.json里没有匹配-p指定产品的节点load_config返回空列表cli.py直接报错退出if not config: logger.error(短信轰炸机配置不可为空) return排错法先用python -m smsBomb -p aliyun -t 13800138000 -n 1 -vvv跑一次日志会明确告诉你加载了哪些配置、哪个插件缺失无此插件:xxx,跳过。坑二日志级别不够看不到细节。默认级别下进度是DEBUG根本不会输出。setup_logger里一行level max(5 - verbose_count, 0) * 10决定了-v是 INFO40、-vv是 DEBUG30、-vvv是最细的调试级别。排错先加-vvv看请求体是否拼对、签名是否被服务商拒绝。坑三接口时序与系统时间。腾讯云要求请求时间与服务器时间差不超过 10 分钟send()里的time: int(ts)若因本机时间漂移导致校验失败会返回非 0 的result。排错法核对日志中的Timestamp与CurTime是否合理必要时校准系统时钟。另外代码中两处已知 BUG 也在提示边界Ctrl C在多进程下尚未优雅处理中断可能留下僵尸子进程Mac 上 requests 会卡在代理检查SmsPlugin.__init__里特意用trust_env False规避——如果你在 macOS 上发现请求异常先怀疑代理设置。写在最后给读者的可执行要点清单回到开头的问题smsBomb 凭什么能用一堆捡来的密钥稳定轰炸答案藏在它三层调度设计里——加权随机让流量分散到多家渠道失败降权让失效节点自动退出竞争失败率熔断避免无意义的空转而插件化 进度回调则让 CLI/GUI、十一家服务商共用一套内核。这套配置驱动 自动容错的架构即便放在今天的生产级调用系统中也毫不过时。如果你打算亲自上手可以按下面清单行动入门克隆仓库地址https://gitcode.com/gh_mirrors/sms/smsBomb执行pip install -r requirements.txt用python -m smsBomb -t 你的手机号 -n 3 -vv观察完整攻击流程️实操打开config/sms.json尝试新增或修改一个节点的auth与weight感受加权随机对命中概率的影响用-p aliyun指定单渠道再配合-vvv观察签名过程进阶对照plugins/下的现有插件为你熟悉的短信平台写一个send()方法放入目录即可被自动加载——这是理解插件机制最好的练习监控想掌握进度与成功率-v是底线配置自定义进度处理可仿照 GUI 的回调写法把cb接进自己的日志或看板系统⚠️红线提醒项目仅供学习研究攻击他人手机号涉嫌违法请务必在自有号码或测试环境中验证。smsBomb 的项目结构一目了然cli.py是入口、gui.py是另一个前端、smsBomb.py装着一整颗调度内核、plugins/是即插即用的渠道库、config/sms.json是唯一需要维护的数据源。理解了本文的调度链路你对这个项目乃至同类多源并发调用系统的理解就已经超过了 90% 的使用者。【免费下载链接】smsBomb短信炸项目地址: https://gitcode.com/gh_mirrors/sms/smsBomb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价