|
| 1 | +# Write-up: Chasing a Lock |
| 2 | + |
| 3 | + |
| 4 | +## Description |
| 5 | + |
| 6 | +### My Story |
| 7 | +First I executed the app and this is it: |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +Each time you touch the lock, the counter at the bottom of the page will decrease by one; while the lock changes its position randomly every second. |
| 12 | + |
| 13 | +me: "So I should make the counter zero!" :D |
| 14 | + |
| 15 | +I got the point and opened JADX and found the source code without any obfuscation. This is the source code of MainActivity: |
| 16 | +``` |
| 17 | +package com.example.razictf_2; |
| 18 | +
|
| 19 | +import android.os.Bundle; |
| 20 | +import android.util.DisplayMetrics; |
| 21 | +import android.view.View; |
| 22 | +import android.view.View.OnClickListener; |
| 23 | +import android.widget.ImageButton; |
| 24 | +import android.widget.TextView; |
| 25 | +import androidx.appcompat.app.AppCompatActivity; |
| 26 | +import java.util.Random; |
| 27 | +import java.util.Timer; |
| 28 | +import java.util.TimerTask; |
| 29 | +
|
| 30 | +public class MainActivity extends AppCompatActivity { |
| 31 | + public void onCreate(Bundle bundle) { |
| 32 | + super.onCreate(bundle); |
| 33 | + setContentView((int) R.layout.activity_main); |
| 34 | + final ImageButton imageButton = (ImageButton) findViewById(R.id.my_button); |
| 35 | + final DisplayMetrics displayMetrics = new DisplayMetrics(); |
| 36 | + getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); |
| 37 | + new Timer().schedule(new TimerTask() { |
| 38 | + public void run() { |
| 39 | + MainActivity.this.runOnUiThread(new Runnable() { |
| 40 | + public void run() { |
| 41 | + Random random = new Random(); |
| 42 | + float nextFloat = random.nextFloat() * ((float) displayMetrics.widthPixels); |
| 43 | + float nextFloat2 = random.nextFloat() * ((float) displayMetrics.heightPixels); |
| 44 | + new Timer(); |
| 45 | + imageButton.animate().x(nextFloat).y(nextFloat2).setDuration(0).start(); |
| 46 | + } |
| 47 | + }); |
| 48 | + } |
| 49 | + }, 0, 1000); |
| 50 | + imageButton.setOnClickListener(new OnClickListener() { |
| 51 | + public void onClick(View view) { |
| 52 | + TextView textView = (TextView) MainActivity.this.findViewById(R.id.Num); |
| 53 | + int parseInt = Integer.parseInt(textView.getText().toString()); |
| 54 | + if (parseInt == 0 || parseInt < 0) { |
| 55 | + textView.setText("0"); |
| 56 | + return; |
| 57 | + } |
| 58 | + int i = parseInt - 1; |
| 59 | + String run = new switcher().run(i); |
| 60 | + if (run != null) { |
| 61 | + ((TextView) MainActivity.this.findViewById(R.id.Flag)).setText(run); |
| 62 | + } |
| 63 | + textView.setText(String.valueOf(i)); |
| 64 | + } |
| 65 | + }); |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +And this is the interesting point: |
| 71 | +``` |
| 72 | +String run = new switcher().run(i); |
| 73 | +``` |
| 74 | + |
| 75 | +It seems the magic part is inside the `switcher` class. This is the source code: |
| 76 | +``` |
| 77 | +package com.example.razictf_2; |
| 78 | +
|
| 79 | +public class switcher { |
| 80 | + public String run(int i) { |
| 81 | + if (i != 0) { |
| 82 | + return null; |
| 83 | + } |
| 84 | + a1 a1Var = new a1(); |
| 85 | + StringBuilder sb = new StringBuilder(); |
| 86 | + sb.append(" "); |
| 87 | + sb.append(a1Var.run(i)); |
| 88 | + String sb2 = sb.toString(); |
| 89 | + a2 a2Var = new a2(); |
| 90 | + System.out.println(a2Var.run(i)); |
| 91 | + StringBuilder sb3 = new StringBuilder(); |
| 92 | + sb3.append(sb2); |
| 93 | + sb3.append(a2Var.run(i)); |
| 94 | + String sb4 = sb3.toString(); |
| 95 | + a3 a3Var = new a3(); |
| 96 | + StringBuilder sb5 = new StringBuilder(); |
| 97 | + sb5.append(sb4); |
| 98 | + sb5.append(a3Var.run(i)); |
| 99 | + String sb6 = sb5.toString(); |
| 100 | + a4 a4Var = new a4(); |
| 101 | + StringBuilder sb7 = new StringBuilder(); |
| 102 | + sb7.append(sb6); |
| 103 | + sb7.append(a4Var.run(i)); |
| 104 | + String sb8 = sb7.toString(); |
| 105 | + a5 a5Var = new a5(); |
| 106 | + StringBuilder sb9 = new StringBuilder(); |
| 107 | + sb9.append(sb8); |
| 108 | + sb9.append(a5Var.run(i)); |
| 109 | + return sb9.toString(); |
| 110 | + } |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +### Exploit Time |
| 115 | +So the only thing I need to do is hooking the `run` method and rewrite the value of `i` argument to zero. It's really easy using Frida. |
| 116 | +I wrote [loader.py](./loader.py) and [script.js](./script.js). |
| 117 | + |
| 118 | +### Flag |
| 119 | +And this is the result: |
| 120 | + |
0 commit comments