|
|
@@ -0,0 +1,328 @@
|
|
|
+package com.example.modifier;
|
|
|
+
|
|
|
+import android.content.Intent;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.os.Handler;
|
|
|
+import android.os.Looper;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.View;
|
|
|
+import android.widget.Toast;
|
|
|
+
|
|
|
+import androidx.activity.EdgeToEdge;
|
|
|
+import androidx.appcompat.app.AppCompatActivity;
|
|
|
+import androidx.core.graphics.Insets;
|
|
|
+import androidx.core.view.ViewCompat;
|
|
|
+import androidx.core.view.WindowInsetsCompat;
|
|
|
+
|
|
|
+import com.example.modifier.databinding.ActivityMainBinding;
|
|
|
+import com.google.gson.Gson;
|
|
|
+
|
|
|
+import org.apache.commons.lang3.RandomStringUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.DataOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileReader;
|
|
|
+import java.io.FileWriter;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+public class MainActivity extends AppCompatActivity {
|
|
|
+ private static final String TAG = "SpooferModule";
|
|
|
+ ActivityMainBinding mBinding;
|
|
|
+ ExecutorService executor = Executors.newFixedThreadPool(8);
|
|
|
+ Handler handler = new Handler(Looper.getMainLooper());
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onCreate(Bundle savedInstanceState) {
|
|
|
+ super.onCreate(savedInstanceState);
|
|
|
+ EdgeToEdge.enable(this);
|
|
|
+ mBinding = ActivityMainBinding.inflate(getLayoutInflater());
|
|
|
+ setContentView(mBinding.getRoot());
|
|
|
+ ViewCompat.setOnApplyWindowInsetsListener(mBinding.main, (v, insets) -> {
|
|
|
+ Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
|
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
|
|
+ return insets;
|
|
|
+ });
|
|
|
+
|
|
|
+ mBinding.tlIccid.setEndIconOnClickListener(v -> {
|
|
|
+ mBinding.etIccid.setText(RandomStringUtils.randomNumeric(20));
|
|
|
+ });
|
|
|
+ mBinding.tlImsi.setEndIconOnClickListener(v -> {
|
|
|
+ String mcc = mBinding.etMcc.getText().toString();
|
|
|
+ String mnc = mBinding.etMnc.getText().toString();
|
|
|
+ if (StringUtils.isEmpty(mcc) || StringUtils.isEmpty(mnc)) {
|
|
|
+ Toast.makeText(this, "MCC and MNC are required", Toast.LENGTH_SHORT).show();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ mBinding.etImsi.setText(mcc + mnc + RandomStringUtils.randomNumeric(15 - mcc.length() - mnc.length()));
|
|
|
+ });
|
|
|
+ mBinding.tlImei.setEndIconOnClickListener(v -> {
|
|
|
+ mBinding.etImei.setText(generateIMEI());
|
|
|
+ });
|
|
|
+ Gson gson = new Gson();
|
|
|
+ try {
|
|
|
+ File file = new File(getDataDir(), "config.json");
|
|
|
+ if (file.exists()) {
|
|
|
+ FileReader reader = new FileReader(file);
|
|
|
+ Config config = gson.fromJson(reader, Config.class);
|
|
|
+ mBinding.etNumber.setText(config.getNumber());
|
|
|
+ mBinding.etMcc.setText(config.getMcc());
|
|
|
+ mBinding.etMnc.setText(config.getMnc());
|
|
|
+ mBinding.etIccid.setText(config.getIccid());
|
|
|
+ mBinding.etImsi.setText(config.getImsi());
|
|
|
+ mBinding.etImei.setText(config.getImei());
|
|
|
+ mBinding.etCountry.setText(config.getCountry());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ mBinding.btnSave.setOnClickListener(v -> {
|
|
|
+ onSave();
|
|
|
+ });
|
|
|
+ mBinding.btnClear.setOnClickListener(v -> {
|
|
|
+ onClear();
|
|
|
+ });
|
|
|
+ mBinding.btnStop.setOnClickListener(v -> {
|
|
|
+ onStopClick();
|
|
|
+ });
|
|
|
+ mBinding.btnSend.setOnClickListener(v -> {
|
|
|
+ String otp = mBinding.etOtp.getText().toString();
|
|
|
+ Intent intent = new Intent();
|
|
|
+ intent.setAction("com.example.modifier.sms");
|
|
|
+ intent.putExtra("sender", "3538");
|
|
|
+ intent.putExtra("message", "Your Messenger verification code is G-" + otp);
|
|
|
+ sendBroadcast(intent);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void onSave() {
|
|
|
+ mBinding.btnSave.setVisibility(View.GONE);
|
|
|
+ mBinding.progressSave.setVisibility(View.VISIBLE);
|
|
|
+ executor.execute(() -> {
|
|
|
+ save();
|
|
|
+ handler.post(() -> {
|
|
|
+ mBinding.btnSave.setVisibility(View.VISIBLE);
|
|
|
+ mBinding.progressSave.setVisibility(View.GONE);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void save() {
|
|
|
+ try {
|
|
|
+ Config config = new Config(mBinding.etNumber.getText().toString(),
|
|
|
+ mBinding.etMcc.getText().toString(),
|
|
|
+ mBinding.etMnc.getText().toString(),
|
|
|
+ mBinding.etIccid.getText().toString(),
|
|
|
+ mBinding.etImsi.getText().toString(),
|
|
|
+ mBinding.etImei.getText().toString(),
|
|
|
+ mBinding.etCountry.getText().toString());
|
|
|
+ File file = new File(getDataDir(), "config.json");
|
|
|
+ Gson gson = new Gson();
|
|
|
+ String json = gson.toJson(config);
|
|
|
+
|
|
|
+ try {
|
|
|
+ FileWriter writer = new FileWriter(file);
|
|
|
+ writer.write(json);
|
|
|
+ writer.close();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ runAsRoot(
|
|
|
+ "cp " + file.getPath() + " /data/data/com.google.android.gms/rcsConfig.json",
|
|
|
+ "echo 'copied to gms'",
|
|
|
+ "chmod 777 /data/data/com.google.android.gms/rcsConfig.json",
|
|
|
+ "cp " + file.getPath() + " /data/data/com.google.android.apps.messaging/rcsConfig.json",
|
|
|
+ "echo 'copied to sms'",
|
|
|
+ "chmod 777 /data/data/com.google.android.apps.messaging/rcsConfig.json",
|
|
|
+ "cp " + file.getPath() + " /data/data/com.kee.SIMdeviceinfo/rcsConfig.json",
|
|
|
+ "echo 'copied to siminfo'",
|
|
|
+ "chmod 777 /data/data/com.kee.SIMdeviceinfo/rcsConfig.json");
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void onClear() {
|
|
|
+ mBinding.llBtn.setVisibility(View.GONE);
|
|
|
+ mBinding.progressClear.setVisibility(View.VISIBLE);
|
|
|
+ executor.execute(() -> {
|
|
|
+ clear();
|
|
|
+ save();
|
|
|
+ stop();
|
|
|
+ handler.post(() -> {
|
|
|
+ mBinding.llBtn.setVisibility(View.VISIBLE);
|
|
|
+ mBinding.progressClear.setVisibility(View.GONE);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void clear() {
|
|
|
+ try {
|
|
|
+ boolean gms = mBinding.cbGms.isChecked();
|
|
|
+ boolean sms = mBinding.cbGms.isChecked();
|
|
|
+ boolean gsf = mBinding.cbGsf.isChecked();
|
|
|
+ List<String> cmds = new ArrayList<>();
|
|
|
+ if (gsf) {
|
|
|
+ cmds.add("pm clear com.google.android.gsf");
|
|
|
+ cmds.add("echo 'cleared gsf'");
|
|
|
+ }
|
|
|
+ if (gms) {
|
|
|
+ cmds.add("pm clear com.google.android.gms");
|
|
|
+ cmds.add("echo 'cleared gms'");
|
|
|
+ }
|
|
|
+ if (sms) {
|
|
|
+ cmds.add("pm clear com.google.android.apps.messaging");
|
|
|
+ cmds.add("echo 'cleared sms'");
|
|
|
+ }
|
|
|
+ runAsRoot(cmds.toArray(new String[0]));
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void onStopClick() {
|
|
|
+ mBinding.llBtn.setVisibility(View.GONE);
|
|
|
+ mBinding.progressClear.setVisibility(View.VISIBLE);
|
|
|
+
|
|
|
+ executor.execute(() -> {
|
|
|
+ stop();
|
|
|
+ handler.post(() -> {
|
|
|
+ mBinding.llBtn.setVisibility(View.VISIBLE);
|
|
|
+ mBinding.progressClear.setVisibility(View.GONE);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void stop() {
|
|
|
+ try {
|
|
|
+ boolean gms = mBinding.cbGms.isChecked();
|
|
|
+ boolean sms = mBinding.cbGms.isChecked();
|
|
|
+ boolean gsf = mBinding.cbGsf.isChecked();
|
|
|
+
|
|
|
+ List<String> cmds = new ArrayList<>();
|
|
|
+ if (gsf) {
|
|
|
+ cmds.add("am force-stop com.google.android.gsf");
|
|
|
+ cmds.add("echo 'stopped gsf'");
|
|
|
+ }
|
|
|
+ if (gms) {
|
|
|
+ cmds.add("am force-stop com.google.android.gms");
|
|
|
+ cmds.add("echo 'stopped gms'");
|
|
|
+ }
|
|
|
+ if (sms) {
|
|
|
+ cmds.add("am force-stop com.google.android.apps.messaging");
|
|
|
+ cmds.add("echo 'stopped sms'");
|
|
|
+ }
|
|
|
+ runAsRoot(cmds.toArray(new String[0]));
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void runAsRoot(String... cmds) throws IOException, InterruptedException {
|
|
|
+ Process p = Runtime.getRuntime().exec("su");
|
|
|
+ executor.execute(new StreamLogger(p.getInputStream()));
|
|
|
+ executor.execute(new StreamLogger(p.getErrorStream()));
|
|
|
+ DataOutputStream outputStream = new DataOutputStream(p.getOutputStream());
|
|
|
+ outputStream.writeBytes("su\n");
|
|
|
+ outputStream.flush();
|
|
|
+ for (String cmd : cmds) {
|
|
|
+ outputStream.writeBytes(cmd + "\n");
|
|
|
+ outputStream.flush();
|
|
|
+ Log.i(TAG, "Running command: " + cmd);
|
|
|
+ }
|
|
|
+ outputStream.writeBytes("exit\n");
|
|
|
+ outputStream.flush();
|
|
|
+ p.waitFor(5, TimeUnit.SECONDS);
|
|
|
+ Log.i(TAG, "Command executed");
|
|
|
+ }
|
|
|
+
|
|
|
+ String generateIMEI() {
|
|
|
+ int pos;
|
|
|
+ int[] str = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
+ int sum = 0;
|
|
|
+ int final_digit;
|
|
|
+ int t;
|
|
|
+ int len_offset;
|
|
|
+ int len = 15;
|
|
|
+ String imei = "";
|
|
|
+
|
|
|
+ String[] rbi = new String[]{"01", "10", "30", "33", "35", "44", "45", "49", "50", "51", "52", "53", "54", "86", "91", "98", "99"};
|
|
|
+ String[] arr = rbi[(int) Math.floor(Math.random() * rbi.length)].split("");
|
|
|
+ str[0] = Integer.parseInt(arr[0]);
|
|
|
+ str[1] = Integer.parseInt(arr[1]);
|
|
|
+ pos = 2;
|
|
|
+
|
|
|
+ while (pos < len - 1) {
|
|
|
+ str[pos++] = (int) (Math.floor(Math.random() * 10) % 10);
|
|
|
+ }
|
|
|
+
|
|
|
+ len_offset = (len + 1) % 2;
|
|
|
+ for (pos = 0; pos < len - 1; pos++) {
|
|
|
+ if ((pos + len_offset) % 2 != 0) {
|
|
|
+ t = str[pos] * 2;
|
|
|
+ if (t > 9) {
|
|
|
+ t -= 9;
|
|
|
+ }
|
|
|
+ sum += t;
|
|
|
+ } else {
|
|
|
+ sum += str[pos];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ final_digit = (10 - (sum % 10)) % 10;
|
|
|
+ str[len - 1] = final_digit;
|
|
|
+
|
|
|
+ for (int d : str) {
|
|
|
+ imei += String.valueOf(d);
|
|
|
+ }
|
|
|
+
|
|
|
+ return imei;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ class StreamLogger implements Runnable {
|
|
|
+ private final InputStream is;
|
|
|
+
|
|
|
+ public StreamLogger(InputStream is) {
|
|
|
+ this.is = is;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ try {
|
|
|
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
|
|
+ String line = null;
|
|
|
+ while ((line = br.readLine()) != null) {
|
|
|
+ Log.i(TAG, "Cmd Output: " + line);
|
|
|
+ try {
|
|
|
+ Thread.sleep(500);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ is.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|