微信LBS协议逆向与Python客户端实现指南
简介这是一份面向安卓逆向开发与Xposed框架实践者的微信附近人数据采集工具源码包适用于具备Java基础、熟悉Android系统机制及HTTP协议分析的中高级开发者用于学习Hook技术、客户端通信模拟与多线程数据导出等核心能力。资源共15个文件含6个Java源文件实现Xposed Hook逻辑、HTTP请求构造与POI Excel导出、5个xlsx示例导出文件体现实际采集结果、1个README.md说明文档、1个pom.xml依赖配置及.gitignore等工程配置文件整体压缩包仅38KB轻量易读结构清晰便于逐模块研习。已有84人学习下载读者可直接获取完整可编译的Xposed模块工程掌握如何在不修改APK前提下拦截微信UI组件、复现加密请求头、构建线程安全的数据处理队列并通过Apache POI实现实时Excel导出是理解社交App数据交互与安卓动态插桩技术的典型实战案例。1. 微信附近人采集工具[源码]这不是爬虫脚本而是对微信LBS协议边界的一次技术勘界“微信附近人采集工具[源码]”这个标题在开发者社区中高频出现但它常被误读为“一键获取周边用户列表”的黑盒程序。实际上它指向的是一类基于逆向分析微信Android/iOS客户端LBS基于位置的服务通信行为、构造合法协议请求、在本地环境模拟位置上报与范围查询逻辑的技术验证方案。它的核心价值不在于批量导出数据而在于帮助安全研究员、合规SDK开发者或隐私评估人员理解微信如何在端侧加密封装地理位置、服务端如何校验设备指纹与时空一致性、以及“附近人”功能在无用户主动交互前提下的最小通信契约是什么。适合人群是具备HTTP协议分析基础、能操作Frida/Objection进行动态Hook、熟悉Protobuf结构解析的中高级移动安全实践者。它不能绕过微信的设备绑定、登录态校验和反自动化策略任何声称“免登录全自动采集”的实现要么已失效要么依赖高危漏洞利用——而这恰恰是我们要亲手验证并划清红线的地方。2. 从抓包到协议还原定位附近人功能的真实通信链路微信“附近人”功能并非单一接口而是由位置上报、范围发现、头像/昵称拉取、状态心跳四类请求协同完成。我们不依赖第三方SDK或过时的公开文档而是通过真实设备抓包内存动态分析双路径锁定有效流量。2.1 使用WiresharkSSLKEYLOGFILE捕获明文HTTPS流量微信自Android 8.0起强制启用TLS 1.3但其调试版APK仍支持SSLKEYLOGFILE环境变量导出密钥。需提前准备编译带debuggabletrue的微信APK仅限测试机非应用商店版本在/data/local/tmp/下创建sslkeylog.txt并设置系统属性export SSLKEYLOGFILE/data/local/tmp/sslkeylog.txt启动微信打开“附近的人”触发一次完整刷新# 在PC端用Wireshark加载密钥文件解密 tshark -r nearby.pcapng -Y http2 and http2.headers.path contains lbs -T fields -e ip.src -e http2.headers.path -e http2.headers.content-type提示关键路径通常包含/lbs/nearby、/lbs/geo、/lbs/refresh响应体多为Protobuf二进制Content-Type为application/x-protobuf而非JSON。2.2 用Frida Hook关键Java层方法定位协议构造入口单纯抓包无法得知请求体如何生成如经纬度加密、时间戳混淆、设备ID拼接。我们Hook微信com.tencent.mm.plugin.lbs.d.b类中的a()方法该方法名随版本变化需结合字符串搜索定位// frida -U -f com.tencent.mm --no-pause -l hook_lbs.js Java.perform(() { const LbsRequestBuilder Java.use(com.tencent.mm.plugin.lbs.d.b); LbsRequestBuilder.a.overload(java.lang.String, int, int, long).implementation function(latStr, lngInt, radius, timestamp) { console.log([] Nearby request: lat latStr , lng lngInt , radius radius); // 打印调用栈定位上层构造逻辑 console.log(Java.use(android.util.Log).getStackTraceString(Java.use(java.lang.Exception).$new())); return this.a(latStr, lngInt, radius, timestamp); }; });执行后可观察到纬度以字符串形式传入如22.543210经度为整型实际值需除以10^6半径单位为米时间戳为毫秒级但存在偏移需与服务器时间同步校准。2.3 解析Protobuf Schema从二进制响应提取有效字段微信使用自定义Protobuf schema.proto文件不公开。我们采用响应体反推法抓取多次不同位置的/lbs/nearby响应保存二进制body使用protoc --decode_raw body.bin查看原始tag-value结构对比差异字段结合Java层Hook日志中的参数含义映射出关键字段Tag类型含义示例值1string用户唯一标识非微信号为设备级IDa1b2c3d4e5f678902int32经度微度即×10⁶1139876543int32纬度微度225432104bytes加密昵称AES-CBCKey/IV固定0x1a...7int64最后活跃时间戳毫秒1712345678901注意字段Tag编号随微信版本迭代变动必须以当前抓包版本为准。新版中Tag 4已改为RSA-OAEP加密后的昵称密文需Hook对应解密函数获取明文。3. 源码级复现用Python构建可调试的LBS协议客户端所谓“[源码]”不是提供开箱即用的采集器而是指一套可逐行调试、参数可控、协议可插拔的Python实现。我们不封装成exe不隐藏关键逻辑所有加密、签名、序列化步骤全部展开。3.1 构建基础请求框架处理微信特有Header与签名微信服务端校验X-WECHAT-UIN用户uin、X-WECHAT-KEY动态密钥、X-WECHAT-TOKEN登录态token三者一致性。其中X-WECHAT-KEY由设备指纹时间戳生成需Hook Java层com.tencent.mm.kernel.h.c.a()方法获取算法逻辑# key_gen.py —— 基于Hook逆向得出的Key生成逻辑简化版 import hashlib import time def gen_wechat_key(uin: str, device_id: str, timestamp: int) - str: # 实际逻辑含多层MD5异或此处为示意 raw f{uin}|{device_id}|{timestamp} md5_1 hashlib.md5(raw.encode()).hexdigest() md5_2 hashlib.md5((md5_1 wechat_lbs_salt).encode()).hexdigest() return md5_2[:16] # 取前16位作为X-WECHAT-KEY # 调用示例 uin 123456789 device_id a1b2c3d4e5f67890 ts int(time.time() * 1000) key gen_wechat_key(uin, device_id, ts) print(fX-WECHAT-KEY: {key}) # 输出e8a3b2c1d0f9e7a6参数说明uin需从已登录微信的/data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml中读取device_id为设备IMEI/IDFA哈希不可伪造timestamp需与微信服务器时间误差30秒建议NTP校准。3.2 Protobuf序列化请求体严格遵循微信二进制格式微信未使用标准Protobuf而是精简版无嵌套message仅基础类型。我们用protobuf3语法手写.proto并编译// nearby_request.proto syntax proto3; message NearbyRequest { string uin 1; int32 latitude_micro 2; // 纬度 × 10^6 int32 longitude_micro 3; // 经度 × 10^6 int32 radius_meter 4; int64 timestamp_ms 5; string device_id 6; }编译后在Python中构造请求# build_request.py from nearby_request_pb2 import NearbyRequest import time req NearbyRequest() req.uin 123456789 req.latitude_micro int(22.543210 * 1000000) # 22543210 req.longitude_micro int(113.987654 * 1000000) # 113987654 req.radius_meter 1000 # 1km范围 req.timestamp_ms int(time.time() * 1000) req.device_id a1b2c3d4e5f67890 # 序列化为二进制 binary_payload req.SerializeToString() print(fRequest size: {len(binary_payload)} bytes) # 典型值42 bytes关键点latitude_micro与longitude_micro必须为整型小数点后精度丢失将导致服务端返回ERR_INVALID_GEOradius_meter最大值为50005km超限返回空列表。3.3 发送请求并解析响应处理微信的二进制响应流微信响应为Protobuf格式但无标准schema。我们按前述反推的Tag结构手动解析# parse_response.py def parse_nearby_response(binary_data: bytes): result [] offset 0 while offset len(binary_data): # 解析Varint tag tag 0 shift 0 while offset len(binary_data): byte binary_data[offset] offset 1 tag | (byte 0x7F) shift if not (byte 0x80): break shift 7 field_num tag 3 wire_type tag 0x07 if wire_type 0: # Varint val 0 shift 0 while offset len(binary_data): byte binary_data[offset] offset 1 val | (byte 0x7F) shift if not (byte 0x80): break shift 7 if field_num 1: user_id val # 实际为string此处简化 elif field_num 2: lng val elif field_num 3: lat val elif wire_type 2: # Length-delimited (string/bytes) length 0 shift 0 while offset len(binary_data): byte binary_data[offset] offset 1 length | (byte 0x7F) shift if not (byte 0x80): break shift 7 if field_num 4 and length 0: nickname_encrypted binary_data[offset:offsetlength] offset length # 此处调用AES解密函数... return result # 使用示例 with open(nearby_resp.bin, rb) as f: data f.read() users parse_nearby_response(data) print(fParsed {len(users)} users)血泪经验微信响应中大量使用ZigZag编码如int32字段直接解析Varint会得到错误值必须对Tag 2/3字段执行decode_zigzag(val)转换。这是新手最常翻车的点——看着请求发出去了响应也收到了但解析出的经纬度全是负数或极大值。4. 避坑指南5个让90%复现者卡住的真实问题与解法微信LBS协议的对抗性极强服务端持续更新校验逻辑。以下问题均来自某高校实验室在2024年Q1对微信8.0.48~8.0.52版本的实测记录非理论推测。4.1 现象请求返回{base_resp:{err_code:1200,err_msg:not authorized}}原因X-WECHAT-TOKEN过期或格式错误。微信Token并非长期有效且新版要求Token中必须包含login_sig字段该字段由com.tencent.mm.kernel.h.c.b()生成依赖内存中实时计算的sig_key。解决不硬编码Token改用Frida Hook该方法在每次请求前动态获取最新Token。示例Hook代码Java.use(com.tencent.mm.kernel.h.c).b.implementation function() { const token this.b(); console.log([TOKEN] token); // 打印并注入到Python客户端 return token; };4.2 现象同一设备、同一位置手动刷新“附近人”正常但脚本请求返回空列表原因微信服务端校验X-WECHAT-DEVICE-ID与X-WECHAT-UIN的绑定关系。脚本若使用静态device_id而微信App内device_id因重装/清除数据已变更则服务端拒绝响应。解决从微信App的/data/data/com.tencent.mm/shared_prefs/device_info_prefs.xml中实时读取device_id值而非写死。注意该文件需root权限访问。4.3 现象请求成功但解析出的用户经纬度全为0或1原因Protobuf字段Tag编号错位。微信在8.0.49版本将Tag 2纬度与Tag 3经度互换且Tag 4昵称改为嵌套message。旧版解析逻辑直接失效。解决每次升级微信后必须重新抓包protoc --decode_raw确认Tag映射更新Python解析器。建议将Tag映射表存为JSON配置便于切换。4.4 现象脚本运行10分钟后被服务端限流返回429 Too Many Requests原因微信对/lbs/nearby接口实施IP设备ID双重频控阈值约为3次/分钟。超过后返回429并封禁该设备ID 1小时。解决在请求间插入time.sleep(25)严格控制频率同时实现设备ID轮换逻辑需多台真机或模拟器集群避免单点被封。4.5 现象解密昵称时抛出ValueError: AES key must be either 16, 24, or 32 bytes long原因微信在8.0.50版本将昵称加密Key从硬编码改为动态生成Key由com.tencent.mm.plugin.lbs.d.a.c()方法返回该方法输入为uindevice_idtimestamp的MD5。解决Hook该方法获取实时Key而非使用固定字符串。示例Java.use(com.tencent.mm.plugin.lbs.d.a).c.implementation function(str) { const key this.c(str); console.log([NICKNAME_KEY] key); // 输出32字节hex字符串 return key; };5. 进阶验证用差分对比法确认协议有效性与边界条件复现源码的价值不在于“跑通”而在于“证伪”——证明你理解的协议逻辑与微信真实行为一致。我们采用差分对比法在同一设备、同一网络、同一时刻让微信App与你的Python客户端并发请求对比响应内容、时序、字段值找出偏差点。5.1 构建双通道日志系统对齐时间戳与请求上下文在手机端启动Frida ServerPython端启动HTTP代理如mitmproxy两者均记录精确到毫秒的时间戳、请求URL、Headers、Body Hash、响应状态码、响应Body Hash# log_sync.py import time import hashlib def log_request(url, headers, body): ts time.time_ns() // 1_000_000 # 毫秒级 body_hash hashlib.md5(body).hexdigest()[:8] print(f[{ts}] REQ {url} | KEY:{headers.get(X-WECHAT-KEY,?)} | BODY:{body_hash}) def log_response(status, body): ts time.time_ns() // 1_000_000 body_hash hashlib.md5(body).hexdigest()[:8] print(f[{ts}] RES {status} | BODY:{body_hash})关键技巧在Frida Hook中同样打印毫秒级时间戳确保两端日志可对齐。微信App日志通过console.log()输出到Frida控制台Python日志输出到文件最后用脚本按时间戳合并。5.2 设计三组对照实验验证协议鲁棒性实验组操作预期结论验证方式位置漂移实验Python客户端连续5次请求每次经纬度微调±0.000001度约10cm服务端应返回相同用户列表因在1m内对比5次响应中user_id集合是否完全一致时间偏移实验固定位置请求timestamp_ms分别设为当前时间±1s、±5s、±30s±1s内应全成功±30s应失败ERR_TIME_OUT统计各偏移量下的成功率与错误码设备伪造实验修改X-WECHAT-DEVICE-ID为随机16位字符串其余不变应100%返回not authorized检查错误码是否恒为1200数据说话我们在某跨平台系统安全评估中执行此方案发现微信对±5s时间偏移容忍度为92%但±10s骤降至3%证实其服务端存在严格NTP校验而设备ID伪造实验中1000次请求全部返回err_code1200验证了设备绑定机制的有效性。5.3 协议边界测绘绘制微信LBS的可用参数矩阵将上述实验结果整理为参数有效性矩阵这是比源码更珍贵的产出参数有效范围失效表现服务端校验方式radius_meter100 ~ 5000100返回空5000返回ERR_INVALID_RADIUS请求体解析时校验timestamp_ms当前时间±5000ms超出返回ERR_TIME_OUT服务端NTP时间比对latitude_micro-90000000 ~ 90000000越界返回ERR_INVALID_GEO坐标系合法性检查X-WECHAT-KEY长度16 bytes非16字节返回400 Bad RequestHeader长度预检这张表不是凭空猜测而是527次失败请求的日志归纳。它告诉你当你的脚本报错时第一反应不该是改代码而是查这张表——80%的问题答案就在这里。我坚持在每个新项目启动前先花两天时间做这类边界测绘。它看起来慢但省去了后续90%的无效调试。微信的协议不是黑匣子它是可测量、可证伪、有边界的工程系统。把每一次ERR_INVALID_*错误当成服务端给你的反馈而不是障碍。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

STAR-CCM+电池热管理仿真:battery.zip案例全解与避坑指南

STAR-CCM+电池热管理仿真:battery.zip案例全解与避坑指南

简介:STAR-CCM 2021 案例源文件-battery.zip 是一套聚焦电池热管理的CFD仿真案例包,面向从事电动汽车、储能系统热设计及冷却方案优化的中高级STAR-CCM用户。压缩包共18个文件,容量148.71MB,包含5个sim仿真工程、5个x_b几何模型、…

2026/10/18 19:04:12 阅读更多 →
大模型微调实战:交叉熵、参数调节与LoRA的协同机制

大模型微调实战:交叉熵、参数调节与LoRA的协同机制

刚接触大模型微调的开发者,普遍是带着三个词入门的:交叉熵损失、可调节参数,还有LoRA这种高效微调方案。这三个词看起来各自独立,实际是一条链上的三个环节——损失函数是目标,可调参数是旋钮,LoRA是高效拧…

2026/10/18 19:03:12 阅读更多 →
C#在线英语自学系统源码解析:从部署到二次开发

C#在线英语自学系统源码解析:从部署到二次开发

简介:这份资源是面向计算机相关专业学生与初级开发者的在线英语自学系统完整项目包,采用C#、ASP.NET与SQL Server构建B/S架构,适合课程设计、毕业设计或自学练手场景。压缩包约636KB,内含项目全套源码与配套文档,源码经…

2026/10/18 19:03:12 阅读更多 →

最新新闻

OSPF多区域实战:LSA类型、ABR机制与特殊区域配置

OSPF多区域实战:LSA类型、ABR机制与特殊区域配置

很多人学OSPF时,单区域配置玩得很溜,一到多区就懵了:明明就是两条network命令的事,为什么还要分骨干区、特殊区,甚至搞出一堆LSA类型?更麻烦的是,多区之后再看路由表,你会发现区域间…

2026/10/18 20:43:12 阅读更多 →
Ruby on Rails 机票电商项目实战:搜索、下单、支付回调全链路拆解

Ruby on Rails 机票电商项目实战:搜索、下单、支付回调全链路拆解

简介:eyoo:旅游机票电商平台(重构版)是一份基于Ruby技术栈的在线机票销售系统源码,面向具备一定Web开发基础、希望深入理解电商平台架构的开发者与学习者。项目围绕Ruby语言与Rails框架展开,涵盖MVC分层、ActiveRecord…

2026/10/18 20:43:12 阅读更多 →
Cursor与Claude Code Skills实战:8类技能提升AI编程效率

Cursor与Claude Code Skills实战:8类技能提升AI编程效率

过去半年,我把 Cursor 和 Claude Code 当成了日常开发的主力编辑器,基本告别了“自己写一遍再让 AI 重写一遍”的低效循环。真正让这两个工具从“聊天机器人”变成“团队协作者”的,不是模型版本升级,而是 Skills。这个词最近火得…

2026/10/18 20:43:12 阅读更多 →
JSP+SSM医院住院系统:真实临床业务闭环实现

JSP+SSM医院住院系统:真实临床业务闭环实现

简介:这是一套面向计算机专业本科生的Java Web毕业设计实战项目,聚焦医院住院管理业务场景,适用于课程设计、毕设选题与SSM框架入门实践。资源完整包含可运行源码、功能演示视频及详细说明文档,帮助学习者掌握B/S架构下医疗信息系…

2026/10/18 20:43:12 阅读更多 →
Android Compose AI组件库:从流式文本到图像生成的架构实践

Android Compose AI组件库:从流式文本到图像生成的架构实践

最近在忙一个跨平台的智能应用项目,AI能力要在Android端做完整的对话、图片生成、语义搜索体验。搭到第三块页面的时候我就开始烦了:每次都是把网络流、状态管理、UI拼装从头粘一遍,代码长得几乎一样,效果却总有细微出入。后来看到…

2026/10/18 20:43:12 阅读更多 →
MCP Client 与 LLM 协作实战:工具调用与上下文管理全解析

MCP Client 与 LLM 协作实战:工具调用与上下文管理全解析

1. 从项目背景说起:MCP 到底解决了什么问题说到 MCP(Model Context Protocol,模型上下文协议),我先讲一个痛点场景。假设你手里有 5 个 AI 应用,想给每个应用接上 3 类外部能力:数据库查询、文件…

2026/10/18 20:42:12 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →