十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

技术逆向英语:从JS逆向到安卓逆向的实战路线与词汇指南

技术逆向英语:从JS逆向到安卓逆向的实战路线与词汇指南 这一期《技术逆向英语》的编号是202602008。先说个常见的误解一提到“逆向”两个字很多人第一反应是破解、盗版、黑客攻击好像这是只能在灰色地带偷偷摸摸做的事。但我干了这么多年安全和技术研究越来越觉得逆向工程其实是程序员理解世界的一种方式它跟正向开发一样是正规的技术分支有完整的理论基础、成熟的开源工具链和大量正经用途。这期内容我把逆向工程这个方向拆开来讲先聊它到底是什么再分别走一遍Web端JS逆向和安卓App逆向的核心步骤最后把逆向工程师日常绕不开的英文术语和英文资料阅读方法一并梳理出来因为“技术逆向英语”这个栏目的定位从来不只是讲技术还要把技术背后的语言门槛一起解决掉。如果你是做爬虫、前端安全、客户端分析或者只是好奇一段混淆过的代码是怎么被还原成可读逻辑的这篇内容应该能帮你省不少摸索时间。1. 逆向不是破解先搞懂“从结果推过程”的技术本质1.1 正向开发和逆向分析的分界线很多新手对逆向的第一印象来自电影黑客敲几行命令就把系统攻破了很酷。但实际工作中的逆向工程完全另一副样子。正向开发是拿着需求从零开始设计数据库、定接口、写代码、部署、迭代。逆向分析则是反过来——你面前只有一个最终产物可能是一个exe文件、一个APK安装包、一段混淆过的JavaScript脚本甚至只是一个二进制的文件格式你的任务是倒推出它内部是怎么组织的、关键算法是什么、数据格式是什么样。我经常用一个做饭的类比来解释这件事。正向开发好比厨师照着菜谱做菜所有配料和火候都是自己控制的。逆向工程则是端上一盘菜让你靠“吃”来判断里面放了什么、用了什么手法、腌制了多久。有时候你能一眼看出主料有时候味道层次复杂你得反复试还要做实验验证自己的猜测。这个类比能解释逆向工程为什么这么吸引人——它是一个不断提出假设、验证假设的过程。这项技术最常见的应用场景包括老系统丢失了源码但还需要维护那就要通过逆向来理解它的行为某些系统没有对外文档但你需要对接它的协议那也需要逆向分析安全研究里分析恶意软件样本更是一刻都离不开逆向。所以别把它想窄了逆向是一种通用能力不只是“破解”这么简单。1.2 黑盒、灰盒、白盒逆向常见的三种信息状态软件测试里有黑盒、白盒、灰盒的概念逆向工程也一样根据你能拿到的信息量来区分。白盒状态你拥有完整源码比如分析一个开源项目阅读代码本身就能理解逻辑严格来说这不算逆向但它是练习阅读能力的基础。黑盒状态你什么都没有只能通过输入输出观测来推断。比如一个加密算法你输入明文得到密文反复试探来猜测它的结构。灰盒状态介于两者之间你有部分信息。比如把一个APK解包后能看到DEX字节码但里面的so文件是加密的或者你在浏览器里能看到完整的JavaScript源码但它是被混淆过的。大多数真实逆向场景都是灰盒状态既有线索又不完整。理解这三种状态很重要因为它决定了你用什么策略。黑盒状态以黑盒测试为主靠输入输出猜测灰盒状态要静态分析和动态调试结合白盒状态反而接近于普通代码审计。新手常犯的错误是一上来就想找到“万能工具”其实工具只是辅助任何时候都要先搞清楚自己手里握着多少信息。1.3 不要只想到破解逆向还有更朴素的工程用法“逆向”这个词除了安全领域在其他工程场景也有很朴素的意思。比如CSS3动画里有一个animation-direction: reverse属性用于让动画反向播放配合animation-iteration-count可以控制动画的执行次数。这个场景下的“逆向”纯粹就是“反向、倒放”的意思没有任何攻击性。再比如一些开源软件解析DWG这类CAD格式早期没有官方SDK开发者只能自己研究二进制文件结构通过逐字节分析来识别里面的几何实体。这种做法本质上也是逆向工程——从成品文件反推格式定义。它既安全又合法但技术含量一点不低需要极强的耐心和细心。我提这两个例子的意思是逆向的思维模式是可以迁移的。你不需要给自己贴上“黑客”的标签才能学逆向把逆向当成一个通用的分析技能你会更容易进入状态。1.4 先说清楚边界授权永远是第一前提这个必须放在最前面讲清楚因为逆向工程的边界感太重要了。合法的学习场景很多分析你自己写的程序、做CTF靶场题、阅读开源项目和获得授权的协议分析这些都完全没问题。很多安全测试工作需要拿到书面授权才能动手这也是行业通行的规则。不建议做的事也很明确未经授权去分析和破解商业软件、绕过付费内容、攻击别人的系统。这不仅是执业风险问题更会毁掉一个技术人的职业前途。真正有本事的逆向工程师恰恰是最尊重边界的人因为技术能力越强越知道不受约束的后果有多严重。2. JS逆向实战拆解从断点下钩到补环境的关键节点2.1 为什么Web逆向的起点都在浏览器开发者工具如果你对Web端爬虫和前端安全感兴趣JS逆向是绕不开的主战场。现在绝大多数网站的核心逻辑都跑在浏览器里前端加密、登录签名、风控参数本质上都是一段JavaScript在浏览器里执行后生成的结果。所以你不需要去猜测加密算法藏在哪里它就在浏览器的内存和源码里问题只在于你怎么把它找出来。浏览器开发者工具就是这一切的观察窗口。Network面板能看到每个请求的URL、请求头、参数和返回值Sources面板能看到网页加载的所有JavaScript文件Console面板可以直接在当前页面环境里执行代码。这三个面板组合起来基本就能完成80%的JS逆向前期工作。我见过不少新手问“学JS逆向要先学什么”我的答案一直是先把浏览器开发者工具用熟。你不需要急着学什么高深的反混淆框架先在Network里看真实请求在Sources里定位可疑代码在Console里验证猜测这一套流程跑顺了后面的路自然就通了。2.2 登录接口签名参数定位抓包、搜索、断点、回溯我用一个最常见的场景来讲完整流程某个网站的登录接口除了账号密码还多了一个sign参数你想搞清楚这个参数是怎么生成的。第一步是抓包。打开开发者工具切到Network面板勾选Preserve log保留日志然后在页面上正常输入账号密码并点击登录。登录请求发出后在请求列表里找到login接口切换到Payload或者Headers就能看到请求里携带的所有参数。你会注意到有个参数看起来不是用户输入的长得像一段哈希或者加密字符串这就是切入点。第二步是搜索定位。把那个参数名复制下来比如叫sign切到Sources面板按CtrlShiftF调出全局搜索输入sign在所有JavaScript文件里搜索。搜索结果会列出所有出现这个参数名的位置优先看赋值语句因为参数在请求前必然有一次赋值。第三步是下断点。找到可能是生成签名的函数后在那一行的行号上点击设置一个断点。刷新页面或者重新触发登录当JavaScript执行到这一行时会自动暂停。这时候可以看右侧的Scope面板查看局部变量、闭包和全局变量确认这段代码的输入是什么。第四步是回溯调用栈。如果断点所在的位置不是生成签名的源头可以看Call Stack面板里面是从入口到当前暂停点的完整调用链。你沿着调用栈一层层往上点就能找到最初的入口函数以及数据是怎么一步步被加工成最终签名值的。这四步是整个JS逆向的基本功每一步都不难但组合起来就能解决绝大多数“参数不知道从哪里来”的问题。我实际带人的经验是能把这一套流程走顺再去接触混淆代码和反调试机制心态会稳很多。2.3 混淆与反调试技术对抗的三个常规思路真实场景里的代码当然没有这么友好。很多网站会把关键JavaScript代码混淆变量名变成a、b、c这种无意义字符字符串被编码拆分甚至使用控制流平坦化把逻辑打散成状态机。面对这种代码直接阅读几乎不可能需要先“还原”再分析。我处理混淆代码的思路一般是三层递进。第一层是先想办法跳过混淆本身用AST抽象语法树工具解析混淆后的脚本把变量名重命名、常量展开、无用代码删除让代码恢复到大致可读的状态。市面上有不少优秀的AST处理工具比如Babel可以用于JavaScript语法树分析配合插件就能做代码还原。第二层是动态观察不用非得读懂每一行直接运行它在关键位置Hook把输入输出记录下来往往比静态阅读效率高。第三层是修改代码拿到混淆脚本后把检测逻辑直接删掉或改掉形成一个本地可运行的版本再慢慢研究。反调试机制也是常见的障碍。有些网站会频繁执行debugger语句来让开发者工具暂停如果反复执行就会导致无法正常调试。还有一种检测思路是记录debugger执行前后的时间差如果页面被调试则执行某些逻辑时间会明显变长由此判断开发者工具是否打开。这里必须提醒一句对于5s盾这类以风控拦截为目标的反调试体系新手很容易一上来就碰壁这是正常的。我建议先用完全没有防护或者弱防护的授权靶场练手把断点、Hook、AST还原这些基础能力练到条件反射的程度再去看复杂的对抗场景。技术这件事靠的是积累不是头铁。2.4 补环境在Node.js里让浏览器代码跑起来的边界当你定位到了加密函数下一步往往是脱离浏览器环境运行它比如在Node.js里调用或者在Python里通过execjs执行方便后续脚本直接复用。但网页JavaScript通常依赖浏览器对象比如window、document、navigator在Node.js里直接运行会报错说某个变量未定义。这时候就需要“补环境”。原理很简单脚本缺什么对象你就给它构造一个假的挂到全局。比如它用到了document.getElementById你就定义一个最简单的document对象提供一个返回空元素的getElementById方法。补环境的核心原则是“缺什么补什么够用就行”不需要真的去实现一个完整的浏览器。我的经验是先运行一遍脚本根据报错按顺序补充缺失的全局变量和函数。这个过程有点繁琐但非常有价值它逼着你去了解网页代码到底依赖了什么反而能加深对代码逻辑的理解。如果在补环境上花的精力太多也可以换一个思路直接用浏览器自动化工具调用目标代码比如Puppeteer或Playwright在真实浏览器里执行JavaScript函数并返回结果。这样能规避大量补环境问题代价是性能和资源占用更高。两种方式没有优劣看你的具体场景来选。3. 安卓逆向路线APK解包、Smali定位与Frida Hook的配合3.1 从APK开始解包文件结构与关键目录安卓App逆向是另一个热门方向不管是分析App的加密算法、研究第三方SDK接入还是排查恶意应用都需要了解APK的基本结构。APK本质上就是一个ZIP压缩包所以首先可以用解压命令直接展开它。在Linux或macOS环境下一条命令就能完成unzip app.apk -d app_source解压之后你会看到几个关键目录。assets目录通常存放App的静态资源有时会包含一些配置文件甚至加密的脚本lib目录下面按CPU架构分目录存放的是各种.so动态库也就是native层代码classes.dex是所有Java层代码编译后的字节码文件这是静态分析的主要对象。还有一个AndroidManifest.xml但是它在打包时被编译成了二进制XML格式需要工具才能读出可读内容。理解APK结构的意义在于你能一眼判断一个App的复杂度。如果解压后只有一个classes.dex且没有太多so文件说明它主要逻辑都在Java层分析难度低适合新手练手。如果看到大量so库说明核心算法可能下放到native层难度会上去一个台阶。3.2 静态分析jadx还原Java代码Smali里找到那个关键函数拿到APK之后第一步通常是静态分析也就是在不运行App的情况下人肉阅读代码。最常用的工具是jadx它能把DEX字节码反编译成可读的Java代码。命令也很简单jadx -d output app.apk反编译完成后你会得到一个接近原始工程的Java源码目录虽然因为编译优化会有一些信息损失但整体可读性相当高。这时候的分析思路和看代码审计很像先看AndroidManifest.xml确定入口Activity再按业务功能定位关键代码。如果你想找的是加密函数可以直接在代码里搜索AES、MD5、RSA、base64、encrypt这些特征词或者搜你自己抓包时看到的参数名。遇到工具反编译出来仍然不清晰的代码就要去看Smali了。Smali是DEX字节码的反汇编表示语法比Java底层得多直接和寄存器操作对应。比如下面这段Smali代码调用了AesUtil类的aesEncrypt方法.method public static encode(Ljava/lang/String;)Ljava/lang/String; .locals 2 invoke-static {p0}, Lcom/example/AesUtil;-aesEncrypt(Ljava/lang/String;)Ljava/lang/String; move-result-object v0 return-object v0 .end method如果你能看懂Smali很多jadx反编译不出来的逻辑反而能看清楚比如某个方法的真实调用链、哪些字段被混淆过、异常分支怎么走的。对新手来说不必先去系统学Smali语法而是遇到问题再去查效率更高。3.3 动态分析Frida插桩与主动调用静态分析能帮你确定“代码的大致位置”但很多逻辑尤其是加密算法的密钥和完整输入只有在运行时才能看清这时候就要上动态分析工具。安卓逆向里最主流的动态分析框架是Frida。Frida的核心原理是插桩它在App运行时把JavaScript代码注入到进程里让你能Hook劫持特定的Java方法在方法调用前、调用后打印信息或者修改返回值。举个例子假设你已经定位到某个App调用了AesUtil.aesEncrypt方法对字符串加密你想知道加密前后的内容可以写一个这样的脚本Java.perform(function() { var AesUtil Java.use(com.example.AesUtil); AesUtil.aesEncrypt.implementation function(str) { console.log([input] str); var result this.aesEncrypt(str); console.log([output] result); return result; }; });把脚本保存成hook.js然后用Frida命令行附加到目标Appfrida -U -f com.example.app -l hook.js这样每次App调用aesEncrypt控制台就会输出输入和输出你就能在不打断业务流程的情况下把加密算法的入参和结果完整记录下来。除了HookFrida还支持主动调用。也就是说你可以不进App的实际业务页面直接在Frida的console里调用Java层的方法传入自己构造的参数快速验证算法逻辑。这个方法在分析某个加密工具类时极其高效它把“点击页面触发加密”变成了“在控制台调用函数”省去大量重复操作。3.4 加壳与native层新手最容易卡住的进阶点当你处理一些商业App时会发现用jadx反编译出来的代码看不到关键逻辑只看到一个壳的入口这就是“加壳”。加壳的原理是把真正的DEX加密后塞进App资源里运行时在内存中解密再加载。静态分析只能看到壳本身拿不到真正的业务代码。处理壳的思路是“脱壳”——在App运行起来、系统已经把解密后的DEX加载进内存之后把内存中的DEX dump出来。常用的工具包括frida-dexdump等配合Frida可以自动完成内存搜索和DEX导出。脱壳拿到的DEX再丢回jadx就能看到真实的业务代码。除了加壳native层的逆向是另一个门槛。很多App会把关键算法用C/C实现并编译成so文件只给Java层留一个native方法入口。分析native层需要把so文件拖进IDA Pro或Ghidra这类反汇编工具读汇编指令识别函数逻辑。这个方向的学习曲线非常陡需要掌握ARM汇编、ELF文件格式、函数调用约定等底层知识。给刚入门的读者一个很实际的建议不要一上来就挑战加壳App或高强度native层分析。我从带新人的经验来看先把无壳、纯Java层的App分析通Frida插桩能熟练使用再去碰native层会顺很多。逆向工程是透明的阶梯每一步都踩稳了后面的路才不至于断掉。4. 逆向工程师的英语词汇清单从disassembly到anti-debug4.1 为什么英语对逆向工程师特别重要做逆向这行英语不是加分项是硬门槛。我见过不少技术基础不错的人卡在“看不懂英文文档”这一步学起来事倍功半。原因很简单逆向领域最前沿的工具、最完整的文档、最活跃的讨论全都集中在英语世界里。Frida的官方文档是英文的Ghidra的官方教程是英文的GitHub上几乎每一个热门逆向项目的issue都是英文的。中文社区虽然有大量优质逆向内容但整体信息量和对新版本的跟进速度跟第一手英文资料还是有差距。更重要的是你遇到的报错信息、日志输出、工具的交互界面全都是英文。如果看到Failed to attach to process还要去网上搜中文翻译效率会非常低。逆向工程师必须建立“直接读英文”的能力而不是依赖翻译层。4.2 十个最高频的核心词汇含义与使用场景我梳理了逆向工作流里出现频率最高的十个英文词每个都是你马上就会碰到的。reverse engineering逆向工程整个领域的名词本身。decompile / disassemble反编译 / 反汇编。反编译通常指把字节码还原成高级语言比如DEX到Java反汇编指把机器码还原成汇编指令比如so文件的分析。breakpoint断点。调试器暂停程序运行的标记点。call stack调用栈。记录当前执行位置到函数入口的完整调用链调试时看它来确认代码是被谁调用的。hook钩子。拦截并修改某个函数行为的技术。patch补丁也可以作动词表示修改二进制或指令来改变程序行为。obfuscation / deobfuscation混淆 / 反混淆。混淆是让代码难读的技术反混淆是让混淆代码恢复可读。unpack / packer脱壳 / 加壳器。壳程序保护代码不被静态分析。dump导出通常指把内存或文件数据原样导出来比如内存中解密后的DEX。anti-debug反调试程序检测并阻止调试器附加的一类技术。这些词不仅仅是在文档里经常出现你调试时看到的变量名、函数名、日志标题也会大量使用这些英文单词。熟悉它们是建立基础语感的第一步。4.3 工具里最常见的英文提示逐句翻译使用工具时最怕的不是不会操作而是弹出一句英文提示你完全不知道它是什么意思也不知道该不该紧张。我列了一些最常见的提示并给出了真实含义英文提示中文含义出现场景Failed to attach to process附加到进程失败Frida或调试器无法连接目标App通常因为权限不足或进程未启动The call stack is empty调用栈为空断点命中时是原生入口或者栈信息被清空常见于native层Symbol not found符号未找到代码里引用的函数或类在当前程序中不存在常见于静态分析Unhandled exception: type error类型错误未处理异常Frida脚本语法或调用API出错需要检查代码类型Memory read failed内存读取失败读取指定地址时越界或没有权限Apk is not debuggableAPK不可调试目标App的AndroidManifest里debuggable为false需要重打包或用Frida的spawn方式启动这些提示本质上都很直白只要你在真实项目里碰到一次基本就能记住。关键是不要怕它们它们是工具在帮你缩小问题范围不是在刁难你。4.4 搜索时直接照抄的高价值英文关键词查资料时用对关键词能省一个晚上的时间。我把逆向学习里高价值的关键词按方向整理出来可以直接复制到搜索引擎或GitHub搜索框里通用方向reverse engineering tutorialmalware analysis basicsbinary exploitation。JS逆向方向javascript deobfuscationcaptcha reverse engineeringwebpack sign algorithm analysisdebugger detection bypass。安卓方向frida hook androidsmali patchandroid unpackingjadx usageintro to native android reversing。文件格式方向pe file formatelf file formatdwg file format reverse。用这些关键词去搜索你能找到的是经过多年沉淀的经典博客、工具文档和开源示例。说实话很多时候解决问题的最佳答案在英文搜索结果的前几页中文搜索反而找不到那么全。5. 用英语素材给自己补课一套可执行的逆向进阶路线5.1 官方文档是最高效的教材很多人觉得官方文档枯燥宁可去看视频教程但当你想真正掌握一个工具的时候官方文档一定是最权威的信息来源。以逆向工具链为例Frida的官方文档会把每一个API的用途、参数和返回值写得很清楚比任何二手教程都完整。Ghidra的官方文档则收录了从界面操作到脚本开发的整套入门材料。用文档的方式别想着从头到尾读完。我的方法是有问题才去查把文档当字典用。比如我需要了解Frida的Java.use怎么处理重载方法就直接在文档里定位那一节看示例代码。这样既高效又能在实际语境里记住用法。还有一点官方文档里的示例代码通常很简单适合直接复制运行。很多工具的坑其实都是文档没有提到或者示例代码不覆盖的这时候再去搜索错误信息往往会有意外的收获。搜索引擎、GitHub issue和Stack Overflow这三样是比任何付费教程都值钱的资源。5.2 如何用英语提问一个能直接复用的提问模板你会遇到的问题大部分别人也遇到过所以“搜”比“问”更优先。但有些问题确实需要提问在GitHub issue、技术论坛或安全社区提问的时候英语表达直接影响别人能不能快速帮你判断问题。我一般建议用下面这个结构来组织提问标题Tool one-line error比如“Frida: TypeError: Cannot read property use of undefined”。环境操作系统版本、工具版本、目标应用/系统的版本。操作步骤完整的最小复现步骤从打开工具到报错的每一步都写上。预期行为和实际行为我本期望怎么样实际却出现什么。日志贴出关键报错日志或截图。用这个模板写出来的提问任何人都能快速复现你的问题也最容易被别人认真回复。别小看这个能力在开源社区里一个清晰的问题描述本身就是对回答者的尊重能显著提高你获得高质量答案的概率。5.3 给自己定一个小型逆向项目用输出倒逼输入光看不练是肯定学不会逆向的我始终强调“用输出倒逼输入”。这里给你三个可执行的小型练习项目每一个都适合作为入门阶段的练手建议按顺序做一个。第一个项目选一个你自己写的、简单的网站登录功能给它加上一个自定义的加密参数然后在浏览器里用DevTools分析这个参数是怎么生成的。这个项目的目标是让你彻底掌握抓包、断点、调用栈回溯这套基本功。第二个项目用Frida Hook一个Demo级安卓App。你可以先写一个简单的安卓App里面放一个加密函数然后通过Frida Hook它观察输入输出并尝试在Frida console里主动调用。这个项目的目标是让你理解动态插桩的原理和流程。第三个项目选一个CTF逆向入门题目用静态分析和动态分析结合的方式找到它的解题逻辑。CTF题目的难度梯度很友好而且题解社区活跃卡住了能查到思路。不过要注意外部题解往往有很多种建议先自己独立尝试再对照题解找差距。每一个项目做完都建议用英文写一份README记录你的分析思路、关键步骤和最终结果。这有两个好处一是写作的过程会逼着你自己梳理逻辑二是这份英文文档本身就是你的项目作品无论是以后写简历还是与同行交流都能直接拿出来用。我带团队这几年见过太多人学逆向半途而废原因几乎都一样太急着找一个“大招”去破解复杂系统结果被混淆代码和反调试机制劝退。我个人的体会是逆向工程最值钱的不是某个神奇的破解手法而是你愿意静下心一层层看调用栈、一步步验证假设的能力。把未知变成已知这个过程的满足感远比“我破解成功了”这个结果更持久。想学的话别贪多花两周把一个小案例彻底吃透比刷几十个零散的教程管用得多。
返回列表