移动安全开发工程师的校招笔试,和常规开发岗笔试完全是两种生物。开发岗给你一道算法题,刷过LeetCode基本就能应付;移动安全岗直接丢给你一个APK,你要是只懂Java基础,看到smali和so文件的第一眼就会发懵。网易杭研2023校招第一批笔试的移动安全开发工程师方向,恰好就是这么一场典型的“全链路”考察,覆盖了Android逆向、Native二进制、网络协议、风控场景设计和手写代码几个大块。这篇文章想把这次笔试背后的岗位逻辑拆开,再把每个模块的考察重点、典型题目怎么下手、哪些地方容易无声无息地丢分,一次性讲清楚。
文章适合两类人:一类是准备投移动安全校招岗位的同学,可以用它来对照自己的知识结构;另一类是在客户端或安全岗位工作了一段时间、想系统复盘校招笔试考察逻辑的从业者。下面直接进入正题。
1. 从岗位JD反推笔试设计逻辑
1.1 移动安全开发工程师在杭研到底做什么
想弄明白笔试为什么这样出题,先得搞清楚这个岗位日常在做什么。网易杭研的移动安全方向,工作内容大致可以归到四条线上。
第一条线是移动端安全SDK的研发和维护。这类SDK通常以aar、framework或动态库的形式集成进App,功能涵盖代码加固、字符串加密、设备指纹采集、风险环境检测等。它直接跑在线上业务里,对启动耗时、崩溃率、兼容性的要求极其严格。笔试里考算法、考开发基本功,就是因为写SDK和写业务代码是两种工程,你产出的东西要嵌入别人的工程,还不能干扰主流程的任何环节。
第二条线是客户端漏洞挖掘与修复。App上线前要做安全测试,包括Activity组件导出风险、WebView远程代码执行、本地数据明文存储、Native层缓冲区溢出这些常见问题。这部分内容在笔试里就体现为“从代码里找出安全问题并给出修复方案”的题目。
第三条线是攻防对抗类的安全运营。恶意样本分析、病毒查杀引擎的规则提取、黑产工具链的研判,全都要求你有逆向能力。笔试里的APK分析题和so算法还原题,本质上就是把这个工作场景压缩到几个小时里。
第四条线是合规与隐私保护。移动应用对个人信息收集的合规要求越来越高,SDK设计必须遵循最小化采集原则,数据不能乱传、不能明文落地。笔试里的风控场景设计题,往往就是从这里切入的。
1.2 笔试真正在筛选什么能力
把岗位职责摆出来,笔试的筛选逻辑就清楚了:它不是考你记住了多少个知识点,而是考你能不能走通一条完整的分析链路。
什么叫完整链路?给你一个APK,你不能只停留在“我知道smali是什么”的程度,而是要从入口Activity开始,通过AndroidManifest找到启动类,再追踪到关键函数,然后发现核心逻辑在Native层,接着用Ghidra或IDA打开so,识别出算法特征,最后写脚本还原出结果。这里面每一步都有对应的工具和知识点,但大多数人卡住的不是某一步的知识点,而是不知道下一步该做什么。
我带过的校招生里有个很典型的对比:一位科班出身、Java和算法都很强的同学,第一次做这类笔试题时直接卡在“DEX里的类结构要怎么找”这种最基础的一步上;另一位从CTF逆向组出来的同学,算法题写得一般,但拿到APK后不慌不忙,从AndroidManifest开始看,顺着调用链一步步走,很快就把题解出来了。这不是智商差异,而是有没有走通过完整链路的问题。
所以备考方向很明确:不要按教科书从前到后死背,而要按照“拿到一个样本,我第一步干什么、第二步干什么”这条主线去组织知识。
2. 笔试知识版图:六块内容不能瘸腿
移动安全方向的校招笔试,题目来源基本可以归纳成六个模块。每个模块的题型深度、分值占比和备考优先级不同,下面逐个拆开说。
2.1 Android逆向与静态分析
这是出现频率最高、分值占比最大的一块。考察范围主要有四个方面。
APK结构是地基。你需要清楚classes.dex、AndroidManifest.xml、res目录、assets目录、lib下的so各是什么,也知道为什么加固后的APK里classes.dex会变成壳或加密数据。第二个重点是Android四大组件和启动流程,尤其是Application类的执行时机。加固和风控SDK的初始化往往都放在这里,Java层分析入口经常要从它开始。第三个重点是smali语言基础,至少能读懂寄存器、类、方法和跳转指令。第四个重点是工具链,jadx、GDA、apktool要熟练,至少做到快速在jadx里搜索类名、方法名和字符串引用。
这类模块的典型题型是:给一个APK,提示“输入正确字符串后弹出成功Flag”,要求还原出正确的输入。笔试环境里大概率没时间让你跑真机,所以静态分析能力是第一位的。
2.2 Native层与二进制安全
如果笔试只考Java层,那移动安全岗和普通Android开发岗就没有区分度了。真实商业App的核心逻辑基本都在so里,加固保护、反调试、密钥存储、协议加解密,全是Native侧实现的。笔试对这块的考察包括:
ELF文件格式的基础认识,理解文件头、程序头、节头、动态符号表和重定位表的作用;ARM64汇编基础,至少认识MOV、LDR/STR、BL、RET这些常用指令,能配合Ghidra或IDA的F5反编译看懂伪代码;工具操作上,Ghidra和IDA Pro的函数列表、反编译窗口、交叉引用、字符串窗口必须熟练。
还有一类高频考点是识别常见加密算法在二进制里的特征:TEA家族有标志性的0x9E3779B9常量,AES有固定S盒和密钥扩展结构,CRC32通常伴随查表法出现,Base64有固定的字符表。这些特征在识别算法时比逐行读汇编快得多。
Native题的关键不是从零逆汇编,而是先在工具里找到关键函数,再通过字符串引用和交叉引用定位逻辑。一上来就对着汇编逐行翻译,效率极低,还容易把自己绕晕。
2.3 网络协议与数据安全
App的通信链路是攻防争夺最激烈的地方,抓包改包是黑产的基本手段,所以协议题几乎是必考项。这个模块的考察点包括:
HTTP/HTTPS的交互流程、请求头和响应体的常见字段、JSON和Protobuf格式的区别;TLS握手流程、客户端如何校验服务端证书、单向认证和双向认证的区别;AES-CBC、RSA-OAEP、ECDHE这类加密算法在协议中如何落地;防重放和防篡改的通用方案,比如时间戳加nonce、参数排序拼接签名。
典型题型是给一段抓包记录或一份客户端代码,要求找出协议安全问题并给出修复建议。这类题难度不高,但想拿高分必须答得完整,至少从传输加密、证书校验、防重放、防篡改四个层面展开。
2.4 iOS安全基础
网易杭研的移动安全团队同时覆盖Android和iOS两端,所以试卷里通常会有iOS相关题目。不过和Android逆向的深度不同,iOS部分一般以选择题、判断题或简答题出现。考察内容包括:
Mach-O文件结构和代码签名机制;越狱环境检测的常见手法;Keychain数据存储基本逻辑,以及iOS数据保护等级;Objective-C运行时基础,Method Swizzling和HOOK的原理;常见安全问题,比如反调试、明文存储、URL Scheme劫持。
如果你主攻Android,iOS部分不需要深入,但至少把上面几个概念弄清楚,能解释清楚“是什么、为什么、怎么防”,避免拿零分。
2.5 风控对抗与设备指纹
风控对抗是移动安全岗和普通开发岗拉开差距的地方。笔试里经常出现这样的场景大题:某App出现大量模拟器注册和批量刷红包行为,请设计一套移动端风控方案。这个模块要掌握三个层次:
设备指纹的构成。现在IMEI和MAC已经很难拿到,Android高版本对唯一标识符做了严格限制,实际方案是采集硬件序列号、传感器列表、系统属性、开机时间、屏幕分辨率等组合生成唯一ID。第二层是环境风险检测,包括模拟器检测、Hook框架检测、调试器检测、多开和分身检测。第三层是风控决策闭环,从客户端采集、加密上报,到服务端规则引擎和模型打分,再到处置动作。答题时要把这三个层次写完整,缺一个都容易被扣分。
2.6 编程能力与算法基础
移动安全岗不是不考算法,只是占比没有纯开发岗高。一般会有1-2道手写代码题,考察链表、二叉树、字符串处理这类基础数据结构,偶尔也有动态规划入门题。安全领域特有的编码题也很值得准备:手写Base64编解码、CRC32查表法、简单异或加解密、大小端转换、二进制协议解析。语言上推荐Python,笔试环境里写起来最快,调试成本也低。
下面用表格把六个模块的优先级、核心工具和典型题型汇总一下,方便对照备考。
| 模块 | 备考优先级 | 核心工具 | 典型题型 |
|---|---|---|---|
| Android逆向与静态分析 | 极高 | jadx、GDA、apktool | APK找flag、校验函数还原 |
| Native层与二进制安全 | 高 | Ghidra、IDA Pro、010 Editor | so算法识别、加固对抗分析 |
| 网络协议与数据安全 | 高 | Burp Suite、Wireshark、Fiddler | 接口漏洞分析、修复方案设计 |
| iOS安全基础 | 中 | MachOView、Hopper | 简答、选择、判断 |
| 风控对抗与设备指纹 | 中高 | 自研SDK、Frida | 风控场景设计题 |
| 编程与算法 | 中 | LeetCode、Python | 手写编码算法题 |
3. 三道典型题目演示完整解题路径
光说考什么不够,这里还原三道移动安全校招笔试里很常见的典型题目,把从读题到出答案的完整思考路径走一遍。题目不是任何一场考试的原题,但风格和考察点高度一致。
3.1 APK逆向题:从Java层一路跟到Native
题目描述:给定一个APK,运行后有一个输入框,输入正确字符串后弹出Success,要求还原出正确的输入。
第一步,用jadx打开APK,先看AndroidManifest.xml,找到android.intent.action.MAIN入口Activity。进入MainActivity后,定位点击按钮的事件处理,看到调用了checkInput方法,内部new了一个NativeUtil对象,然后调用nativeCheck(String input)返回boolean值。到这里,核心校验逻辑已经确定在Native层。
第二步,打开NativeUtil类,确认native方法声明和库加载代码,通常是System.loadLibrary("native-lib"),也就是说要分析的逻辑在libnative-lib.so里。
第三步,解包APK,取出lib/arm64-v8a/libnative-lib.so,拖进Ghidra,找到Java_com_xxx_NativeUtil_nativeCheck这个导出函数。看伪代码,会发现函数先用输入字符串的前4个字节初始化TEA密钥,然后对一段硬编码数据调用tea_decrypt,最后用strcmp比较解密结果和输入字符串。
第四步,识别TEA算法靠的是0x9E3779B9这个delta常量,它在TEA、XTEA、XXTEA里都会出现。确认算法后,把硬编码数据提取出来,写Python脚本解密:
def tea_decrypt(v, key): v0, v1 = v[0], v[1] s = 0xC6EF3720 delta = 0x9E3779B9 for _ in range(32): v1 -= ((v0 << 4) + key[2]) ^ (v0 + s) ^ ((v0 >> 5) + key[3]) v0 -= ((v1 << 4) + key[0]) ^ (v1 + s) ^ ((v1 >> 5) + key[1]) s -= delta v[0], v[1] = v0 & 0xFFFFFFFF, v1 & 0xFFFFFFFF return v跑完脚本得到的字符串就是flag。这道题真正的考点不是TEA本身,而是“入口Activity到native方法再到so算法识别,最后脚本还原”这条完整链路,任何一步没走过都会卡住。
3.2 协议分析题:识别加密参数并还原明文
题目描述:给定一个App登录接口的抓包样本和一小段客户端加密函数代码,要求解释请求里encrypted_data参数是怎么生成的,并还原给定的密文。
先看抓包内容,请求POST到/api/login,Body里有timestamp、nonce、encrypted_data三个字段。再看客户端代码,发现encrypted_data来自EncryptUtil.encrypt(userInput, timestamp + nonce)方法。跟进EncryptUtil,看到它用的是AES/CBC/PKCS5Padding,密钥来自so里的硬编码字符串,IV是固定的16字节。
漏洞点就在这里:IV固定、密钥硬编码,拿到客户端的人可以还原所有加密参数,伪造任意登录请求。
还原密文的思路很直接:先用jadx在so的字符串列表里找到硬编码的AES密钥,再把密文和固定的IV带入AES解密脚本,明文立刻出来。题目后半问通常是“如何修复”,标准的完整答案包含四条:
- 密钥不能写死在客户端,应通过服务端下发,或用非对称加密协商会话密钥;
- IV改为每次会话随机生成,并随密文一起传输;
- 增加时间戳和nonce防重放,服务端对超时请求直接拒绝;
- 对敏感接口绑定设备指纹,防止同一账号在大量设备上批量调用。
这类题考的是加密传输的整体设计思路,而不是某个单独算法。
3.3 风控场景设计题:模拟器羊毛党的识别与处置
题目描述:某电商App上线新用户注册领红包活动,一周后运营发现大量手机号来自模拟器环境,活动预算被严重透支,要求设计一套移动端风控方案。
这种设计题没有标准答案,但阅卷有明确的采分点,核心是从三个层面展开。
采集端:客户端SDK采集设备信息、软件环境、行为数据。设备信息包括设备型号、系统版本、传感器列表、屏幕分辨率、电池状态、开机时间、CPU信息。软件环境包括是否安装了异常Hook框架、是否有调试器连接、应用是否运行在多开或沙箱环境。行为数据包括注册耗时、输入速度、点击轨迹的随机性。采集完必须加密上报,不能明文传输。
识别端:规则和模型双管齐下。规则层面,检测Build.FINGERPRINT是否包含generic或sdk关键词;检测传感器列表是否只有虚拟传感器,真机的加速度计、陀螺仪数据会有正常的噪声波动,模拟器没有;检测GPU渲染器名称是否是SwiftShader这类模拟器常见值。模型层面,把设备特征和行为特征组合成向量,用异常检测或分类模型打分,识别出聚集性注册行为。
处置端:根据风险分做分层处置。高风险直接拦截,中风险弹出滑块或短信二次验证,低风险正常放行。判定结果回流到风控平台,持续优化规则和模型。
答题时三部分都要写完整,同时强调“客户端只做采集和上报,决策必须在服务端”,避免“本地就能绕过”的硬伤。
4. 笔试里看不见的隐形扣分点
笔试的坑从来不在考点本身,而在那些你以为自己会了、实际处理得不够好的地方。根据身边应届生的反馈,高频扣分点可以归成五类。
4.1 答案格式和题目要求没对齐
逆向题的输出格式一般有严格要求,有时要求flag{...},有时要求大写FLAG{...},大小写不对、顺序不对,结果就是零分。拿到题目先把要求读两遍,重点看输出格式、是否要求截图、是否要求写解题脚本。每年都有人卡在最后一步,把flag大小写搞错,或者多打了一个换行符,一个月的复习就白费了。
4.2 场景设计题只给结论不给细节
常见错误写法是“用AI识别风控风险”“用机器学习检测模拟器”,这种一句话答案等于没写。AI模型用什么特征做输入?训练数据从哪里来?误杀率怎么控制在可接受范围?答不出来,就不是合格的安全工程师。建议用采集端、决策端、处置端三层结构组织答案,每层写清楚技术方案、数据字段和预期效果,这既让逻辑清晰,也能让阅卷人快速找到采分点。
4.3 代码题时间不够就整题放弃
手写代码题如果时间不够,写不出完整可运行的代码,很多人干脆空着。实际上阅卷更看重思路,先把核心数据结构和主流程伪代码写出来,再补关键函数就行。比如实现一个Base64解码,你可以先写出查表、位运算、填充符处理这几个核心步骤,即使最后没有完整跑通,也能拿到大部分分数。伪代码和注释都能得分,空着一定没分。
4.4 死磕Java层而忽略Native入口
有一类题,Java层找到的函数只是转发壳,真正逻辑在so里。只盯着jadx的Java代码看,很容易以为已经拿到答案。这里我给一个条件反射式的建议:看到native方法,马上准备分析so;看到字符串比较,先判断字符串来自Java代码还是Native返回;看到加密相关常量,先在二进制里搜索特征值。养成这些习惯,就不会走偏。
4.5 工具不熟练造成时间黑洞
分析和逆向题是限时任务,工具熟练度直接决定得分。有人对jadx搜索快捷键不熟,一个小时全耗在手工翻目录上;有人对Ghidra的交叉引用跳转不熟,想在函数之间来回跟调用链,速度慢得让人着急。考前把jadx和Ghidra或IDA的常用快捷键、搜索操作、交叉引用跳转练成肌肉记忆,到考场上能省出大量时间,时间就是分数。
下面把常见的“错误答案”和“能拿分的答案”放在一起对比,直观感受一下:
| 题目类型 | 低分答案特征 | 高分答案特征 |
|---|---|---|
| 场景设计题 | 只写“用规则拦截” | 给出规则字段、模型特征、处置分层、数据回流闭环 |