赞库小轩 赞库小轩
  • 夺锦之才
  • 学习日记
  • 摄影旅记
  • 赞库专题
  • 赞库广场
    • 天马星空
    • 动态圈子
    • 交个朋友
    • 网络链接
  • 浏览记录
  • 注册
  • 登录
首页 › 学习日记 › 源码丢失后的逆向还原:一次 Vue 三端项目反编译实录

源码丢失后的逆向还原:一次 Vue 三端项目反编译实录

Juzer
39 分前学习日记阅读 4

前情:源码没了,只剩线上跑着的编译产物

接手一个集装箱买卖销售系统的维护工作时,拿到的东西有点尴尬:系统在线上跑得好好的,但原始工程文件找不到了——没有 .vue 源文件、没有 package.json、没有构建配置,只剩一份编译产物。

这套系统是典型的三端结构:

  • 后台管理端(Vue)—— 用于内部运营管理
  • 员工端(uni-app)—— 现场业务人员使用
  • 用户端(Vue)—— 对外展示与下单

目标不是"凑合改压缩代码",而是把它还原成可编辑、可重新编译的源码工程。下面是完整的过程记录。

第一步:先给产物做体检

动手之前先搞清楚"还剩什么",这直接决定后面工作量的大小:

  • 有没有 source map?——有的话基本等于送分,能还原到接近原始代码;没有就只能硬啃。
  • webpack 还是 vite?——看 chunk 命名规则、runtime 特征与加载方式。
  • 压缩到哪一档?——是变量名单字母化,还是做了更激进的处理。
  • 有没有骨架文件?——入口文件、运行时文件能反推模块边界和依赖图。

体检结果:没有 source map,webpack 产物,业务代码变量名全被压成 a/b/c/d 这类单字母。纯人工读代码基本没戏,必须上工具链。

第二步:找到可读性最好的"那一版"产物

这是整个还原过程中性价比最高的一步。

压缩产物通常分两种形态:

  • minified:变量名被压缩,体积小,但可读性极差
  • unminified / dev 模式:变量名可读,只是没做体积优化

同一套源码在两套构建配置下,产出的"逻辑结构"是一样的——只是名字被改了。所以只要拿到未压缩版产物作为参照,还原难度会下降一个数量级。

做法是:在构建产物里找线索,反推它用的构建开关,再用等价配置重新产出两份可对照的版本(一份压缩、一份不压缩),拿不压缩的那份当作"字典"来对齐压缩版的结构。

第三步:模块与文件结构还原

从入口文件读起,顺着模块加载调用图往下走,可以把整个依赖关系画出来:

  • 业务代码与第三方库的边界在哪里
  • 哪些 chunk 是按路由懒加载拆分出来的
  • 每个模块导出了什么、被谁引用

再结合路由表反推,就能恢复出类似 src/views、src/components 的目录树。这一步做完,工程骨架就先立起来了。

第四步:变量名还原(最容易翻车的一步)

压缩后的代码长这样:

function a(b,c){var d=b.length;if(d>0){for(var e=0;e<d;e++){...}}}

最直觉的做法是"全局搜索替换",但这样必然撞车:a 在 A 模块里代表用户对象,在 B 模块里代表一个数组。全局替换成同一个名字,代码直接废掉。

正确做法是作用域感知的重命名(scope-aware rename):

  1. 先把代码解析成 AST;
  2. 建立完整的作用域树(函数作用域、块作用域、模块作用域);
  3. 只在每个变量的真实作用域内做替换——同一个名字在不同作用域里,可以分别还原成互不冲突的语义名;
  4. 根据使用特征推断语义(是数组?是 DOM 节点?是配置对象?是回调?)生成候选名;
  5. 回写代码,并保证替换前后 AST 结构等价。

这一步我们基于 Babel 写了一套重命名工具。但要强调:推断得对不对,不能靠感觉,必须靠验证器说话。

第五步:语义等价验证——不能只靠肉眼看

代码"看起来对了"和"真的等价"是两件事。所以在还原过程中同步写了一套验证器,每个阶段都跑一遍:

  • 压缩代码与还原代码的模块依赖关系是否一致;
  • 导出/导入的符号是否一一对应;
  • 关键业务逻辑的分支结构是否相同;
  • 变量重命名后,是否存在意外的引用覆盖或作用域泄漏。

三端各自维护了自己的验证脚本,输出"哪些文件通过了、哪些还有差异"。有差异就回到上一步查,直到清零。这套验证器是整个还原工程里最有价值的部分——它让"还原"变成一件可度量的事。

第六步:页面级验收——把每条路由都钉下来

代码层面等价还不够,还要证明页面表现一致。这里用 Playwright 把 SPA 的每条路由逐一访问:

  1. 驱动浏览器真实加载页面,等渲染完成;
  2. 把每个路由的渲染结果单独保存为一份独立 HTML;
  3. 与线上实际页面对比结构,确认没有缺块、错位、丢组件。

两个必须注意的坑:

  • 后端接口要真实打通——不然后端渲染的数据对不上,页面结构看起来"缺一块",会误判成还原失败。部分页面本身依赖远程服务,必须让它先可用。
  • CORS 要放行本地调试来源——不然本地打开一片空白,白折腾半天。

另外,我们最终选择不把页面打包成单文件 HTML。单文件捆绑看起来方便(双击就能开),但那是"存档"而不是"工程"——后续没法维护,也没法独立部署。我们要的是可以独立编辑、改完刷新即生效的多文件结构。

收尾:还原之后的工程形态

三端最终都还原成了可独立编译部署的工程:

  • 前端与后端解耦,前端可以单独打包(后续也可以打进 App);
  • 用户端单独部署在自有站点上,接口指向独立的后端服务;
  • 后续任何需求改动都在源码层完成,不再触碰编译产物。

经验清单

  1. 动手前先做产物体检——有没有 source map、什么构建工具,决定了三天还是三周。
  2. 优先找未压缩的那一版——可读性直接决定工作量。
  3. 重命名必须做作用域感知——全局字符串替换是纯粹的坑。
  4. 每一步都要有可执行的验证器——"我看着像对的"不算还原,能跑过验证才算。
  5. 交付形态选多文件源码工程——别交单文件捆绑,那是存档不是工程。
  6. 页面验收要打通真实接口——否则你验证的是"缺数据的假象"。

整个过程的核心其实就一句话:把"不可读"变成"可读",再把"可读"变成"可验证",最后把"可验证"变成"可维护"。

赞赏 赞(0) 收藏(0)
电视盒子 变常驻运行Ubuntu Ai开发的APK
上一篇
猜你喜欢
网页转为.EXE软件
转山转水-抚仙湖
《变形金刚6》剧情猜想
如何取某盟小程序的素材
Ubuntu自动维护脚本
2 月前
168 0
AI 视频分镜:生产级自动化探索
9 月前
914 0
记录一些Docker指令
1 年前
774 1
PVE虚拟机安装使用指南
1 年前
877 0
  • 0
Copyright © 2020-2026 赞库小轩
滇公网安备 53011102001050号 . 滇ICP备15000316号-9
  • 夺锦之才
  • 学习日记
  • 摄影旅记
  • 赞库专题
  • 赞库广场
    • 天马星空
    • 动态圈子
    • 交个朋友
    • 网络连接
  • 浏览记录
# 原创 # # 知识 # # 技术 # # 网络 # # 故事 #
Juzer
春水碧于天,画船听雨眠。
48
文章
0
评论
99
喜欢