siis / ic3

IC3: Inter-Component Communication Analysis in Android
http://siis.cse.psu.edu/ic3/
Apache License 2.0
36 stars 21 forks source link

Missing IPCs #27

Open ReyhanJB opened 7 years ago

ReyhanJB commented 7 years ago

Hi,

I'm using IC3 to perform an inter-component analysis on some real-world Android apps. However, it seems that IC3 is not able to find a subset of IPC communications between components. For example, one of my apps has a service that registers a broadcast receiver to monitor changes in the state of device's battery. Upon a change in the state of battery/charging, the app sends an intent in order to start a new activity.

public class BatteryService extends Service{

    public final static String EXTRA_MESSAGE = "edu.uci.seal.testapp.MESSAGE";

    private final BroadcastReceiver batteryStatus = new BroadcastReceiver() {

        @SuppressLint("InlinedApi")
        @Override
        public void onReceive(Context context, Intent intent) {
            Intent intent1 = new Intent(getApplicationContext(), DisplayMessageActivity.class); 
            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
            int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
            if(status == BatteryManager.BATTERY_STATUS_CHARGING){
                if(chargePlug == BatteryManager.BATTERY_PLUGGED_USB)
                    intent1.putExtra(EXTRA_MESSAGE, "Battery is charging thorugh usb");
                if(chargePlug == BatteryManager.BATTERY_PLUGGED_AC)
                    intent1.putExtra(EXTRA_MESSAGE, "Battery is charging thorugh AC");
                if(chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS)
                    intent1.putExtra(EXTRA_MESSAGE, "Battery is charging wireless");
            }
            if(status == BatteryManager.BATTERY_STATUS_DISCHARGING || status == BatteryManager.BATTERY_STATUS_NOT_CHARGING)
                intent1.putExtra(EXTRA_MESSAGE, "Battery is discharging");

            intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent1);
        }
    };
}

I generated IC3 analysis result using instructions in the website. Then I used the following code in order to get the components:

        File ipcResults = new File(mApp.getIpcProtoBuf());
        if (ipcResults.exists()) {
            InputStream stream = null;
            try {
                stream = new FileInputStream(mApp.getIpcProtoBuf());
                final Ic3Data.Application application = Ic3Data.Application.parseFrom(stream);
                mIpcComponents.addAll(application.getComponentsList());
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

Then for each component, I iterate over the components to get the exit-points of each, in order to perform an inter-component analysis. For this example, the exit-point list is empty.

I appreciate your help on fixing this issue.

ReyhanJB commented 7 years ago

@aegiryy @hvijay @docteau @rms5643 @npapernot

ReyhanJB commented 7 years ago

This is the output of the IC3 on my app: out.txt

This is the protobuf file generate by IC3 for my app: edu.uci.seal.testapp_1.txt

None of my classes are identified as phantom class and all the calls are reachable (I checked since these two are the main reasons of preventing IC3 to identify calls)

ReyhanJB commented 7 years ago

As another example, IC3 fails to find the following ICC communication:

private void contactSpinner(){
        Spinner spinner = (Spinner) findViewById(R.id.spinner_contact);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if(!parent.getItemAtPosition(position).toString().equals("Contact")){
                    Intent intent = new Intent(getApplicationContext(), DisplayContactActivity.class); 
                    intent.putExtra(EXTRA_MESSAGE, parent.getItemAtPosition(position).toString()); 
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }
            }
            @Override
            public void onNothingSelected(AdapterView<?> arg0) {        }
        });
    }

The method "contactSpinner" is called inside the "onCreate" method of an activity. Therefore, "DisplayContactActivity" should be listed as an exit-point for the activity that implements this method.

docteau commented 7 years ago

In your first example, it looks like you have a dynamically-registered broadcast receiver that is itself sending an intent. Have you actually registered it somewhere? Even if you have, I'm not sure that the initial call graph construction looks at the types of the receiver in registerReceiver instructions (so it might not have realized that the onReceive method is ever called). It is possible that you would need another iteration of the analysis to do this, after properly patching things. I don't remember the details of IccTA, but since it does connect components for you it might do what you need or part of it.

Regards, Damien

ReyhanJB commented 7 years ago

Thank you very much, @docteau.

Looking more closely to the call graph generated by soot, I can see that there is no corresponding node in the call graph corresponding to onCreate method of broadcast receiver in the first example, and onItemSelected method in the second example. So, if an entry point is missed in soot analysis, IC3 does not consider it for further analysis?

docteau commented 7 years ago

No, IC3 only considers whatever is part of the Soot call graph.