| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- package com.example.modifier.ui.utils
- import android.os.Bundle
- import android.util.Log
- import android.view.LayoutInflater
- import android.view.View
- import android.view.ViewGroup
- import android.widget.Toast
- import androidx.appcompat.app.AlertDialog
- import androidx.fragment.app.Fragment
- import androidx.lifecycle.lifecycleScope
- import com.example.modifier.Frida
- import com.example.modifier.R
- import com.example.modifier.Utils
- import com.example.modifier.baseTag
- import com.example.modifier.constants.PACKAGE_GMS
- import com.example.modifier.constants.PACKAGE_GSF
- import com.example.modifier.constants.PACKAGE_MESSAGING
- import com.example.modifier.data.AppPreferences
- import com.example.modifier.databinding.DialogUpdateBinding
- import com.example.modifier.databinding.FragmentUtilsBinding
- import com.example.modifier.extension.kill
- import com.example.modifier.http.ktorClient
- import com.example.modifier.http.api.SysConfigApi
- import com.example.modifier.http.response.SysConfigResponse
- import com.example.modifier.utils.clear
- import com.example.modifier.utils.clearConv
- import com.example.modifier.utils.killPhoneProcess
- import com.example.modifier.utils.resetAll
- import com.example.modifier.utils.resumePackage
- import com.example.modifier.utils.shellRun
- import com.example.modifier.utils.injectOTP
- import com.example.modifier.utils.suspendPackage
- import com.example.modifier.utils.syncTime
- import com.google.android.material.dialog.MaterialAlertDialogBuilder
- import io.ktor.client.call.body
- import io.ktor.client.plugins.resources.get
- import io.ktor.client.request.prepareGet
- import io.ktor.http.contentLength
- import io.ktor.utils.io.ByteReadChannel
- import io.ktor.utils.io.core.isEmpty
- import io.ktor.utils.io.core.readBytes
- import kotlinx.coroutines.CoroutineScope
- import kotlinx.coroutines.Dispatchers
- import kotlinx.coroutines.Job
- import kotlinx.coroutines.delay
- import kotlinx.coroutines.flow.StateFlow
- import kotlinx.coroutines.launch
- import kotlinx.coroutines.withContext
- import java.io.File
- class UtilsFragment : Fragment() {
- private val tag = "$baseTag/UtilsFragment"
- private lateinit var binding: FragmentUtilsBinding
- private lateinit var appPreferences: StateFlow<AppPreferences>
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- }
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- if (this::binding.isInitialized) {
- return binding.root
- }
- binding = FragmentUtilsBinding.inflate(inflater, container, false)
- binding.btnClear.setOnClickListener {
- onClear()
- }
- binding.btnStop.setOnClickListener {
- onStopClick()
- }
- binding.btnSend.setOnClickListener {
- Utils.makeLoadingButton(context, binding.btnSend)
- lifecycleScope.launch {
- delay(1000L)
- val otp = binding.etOtp.text.toString()
- withContext(Dispatchers.IO) {
- injectOTP(otp)
- }
- binding.btnSend.setIconResource(R.drawable.ic_done)
- binding.btnSend.text = "OK"
- delay(1500L)
- binding.btnSend.isEnabled = true
- binding.btnSend.icon = null
- binding.btnSend.text = "Send"
- }
- }
- binding.btnClearConv.setOnClickListener {
- binding.btnClearConv.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnClearConv)
- lifecycleScope.launch {
- clearConv()
- withContext(Dispatchers.Main) {
- binding.btnClearConv.setIconResource(R.drawable.ic_done)
- binding.btnClearConv.text = "OK"
- delay(1500L)
- binding.btnClearConv.isEnabled = true
- binding.btnClearConv.icon = null
- binding.btnClearConv.text = "Clear Msg"
- }
- }
- }
- binding.btnSuspend.setOnClickListener {
- binding.btnSuspend.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnSuspend)
- lifecycleScope.launch {
- val packages = mutableListOf<String>()
- if (binding.cbGsf.isChecked) {
- packages.add(PACKAGE_GSF)
- }
- if (binding.cbGms.isChecked) {
- packages.add(PACKAGE_GMS)
- }
- if (binding.cbSms.isChecked) {
- packages.add(PACKAGE_MESSAGING)
- }
- withContext(Dispatchers.IO) {
- suspendPackage(*packages.toTypedArray())
- }
- binding.btnSuspend.setIconResource(R.drawable.ic_done)
- binding.btnSuspend.text = "OK"
- delay(1500)
- binding.btnSuspend.isEnabled = true
- binding.btnSuspend.icon = null
- binding.btnSuspend.text = "Suspend"
- }
- }
- binding.btnUnsuspend.setOnClickListener {
- binding.btnUnsuspend.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnUnsuspend)
- lifecycleScope.launch {
- val packages = mutableListOf<String>()
- if (binding.cbGsf.isChecked) {
- packages.add(PACKAGE_GSF)
- }
- if (binding.cbGms.isChecked) {
- packages.add(PACKAGE_GMS)
- }
- if (binding.cbSms.isChecked) {
- packages.add(PACKAGE_MESSAGING)
- }
- withContext(Dispatchers.IO) {
- resumePackage(*packages.toTypedArray())
- }
- binding.btnUnsuspend.setIconResource(R.drawable.ic_done)
- binding.btnUnsuspend.text = "OK"
- delay(1500)
- binding.btnUnsuspend.isEnabled = true
- binding.btnUnsuspend.icon = null
- binding.btnUnsuspend.text = "Unsuspend"
- }
- }
- binding.btnStartFrida.setOnClickListener {
- lifecycleScope.launch {
- withContext(Dispatchers.IO) {
- Frida.start()
- }
- }
- Toast.makeText(context, "Frida started", Toast.LENGTH_SHORT).show()
- }
- binding.btnStopFrida.setOnClickListener {
- lifecycleScope.launch {
- withContext(Dispatchers.IO) {
- Frida.stop()
- }
- }
- Toast.makeText(context, "Frida stopped", Toast.LENGTH_SHORT).show()
- }
- binding.btnKillPhone.setOnClickListener {
- binding.btnKillPhone.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnKillPhone)
- lifecycleScope.launch {
- val success = withContext(Dispatchers.IO) {
- killPhoneProcess(force = true)
- }
- if (success) {
- binding.btnKillPhone.setIconResource(R.drawable.ic_done)
- binding.btnKillPhone.text = "OK"
- } else {
- binding.btnKillPhone.setIconResource(R.drawable.ic_error)
- binding.btnKillPhone.text = "Fail"
- }
- delay(1500L)
- binding.btnKillPhone.isEnabled = true
- binding.btnKillPhone.icon = null
- binding.btnKillPhone.text = "Kill Phone"
- }
- }
- binding.btnSyncTime.setOnClickListener {
- binding.btnSyncTime.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnSyncTime)
- lifecycleScope.launch {
- withContext(Dispatchers.IO) {
- syncTime()
- }
- binding.btnSyncTime.setIconResource(R.drawable.ic_done)
- binding.btnSyncTime.text = "OK"
- delay(1500L)
- binding.btnSyncTime.isEnabled = true
- binding.btnSyncTime.icon = null
- binding.btnSyncTime.text = "Sync Time"
- }
- }
- binding.btnUpdateModifier.setOnClickListener {
- lifecycleScope.launch {
- try {
- val config = ktorClient.get(
- SysConfigApi.Id(
- SysConfigApi(),
- "modifier_apk"
- )
- )
- .body<SysConfigResponse>()
- installApk(config.value)
- } catch (e: Exception) {
- Log.e(tag, "Failed to get message apk", e)
- }
- }
- }
- binding.btnUpdateMessage.setOnClickListener {
- lifecycleScope.launch {
- try {
- val config = ktorClient.get(
- SysConfigApi.Id(
- SysConfigApi(),
- "message_apk"
- )
- )
- .body<SysConfigResponse>()
- installApk(config.value)
- } catch (e: Exception) {
- Log.e(tag, "Failed to get message apk", e)
- }
- }
- }
- binding.btnUpdateGms.setOnClickListener {
- lifecycleScope.launch {
- try {
- val config = ktorClient.get(
- SysConfigApi.Id(
- SysConfigApi(),
- "gms_apk"
- )
- )
- .body<SysConfigResponse>()
- installApk(config.value)
- } catch (e: Exception) {
- Log.e(tag, "Failed to get gms apk", e)
- }
- }
- }
- return binding.root
- }
- private fun onClear() {
- binding.btnClear.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnClear)
- val all = binding.cbAll.isChecked
- val gsf = binding.cbGsf.isChecked
- val gms = binding.cbGms.isChecked
- val sms = binding.cbSms.isChecked
- lifecycleScope.launch {
- withContext(Dispatchers.IO) {
- if (all) {
- resetAll()
- } else {
- clear(gsf, gms, sms)
- }
- }
- binding.btnClear.setIconResource(R.drawable.ic_done)
- binding.btnClear.text = "OK"
- delay(1500)
- binding.btnClear.isEnabled = true
- binding.btnClear.icon = null
- binding.btnClear.text = "Clear"
- }
- }
- private fun onStopClick() {
- binding.btnStop.isEnabled = false
- Utils.makeLoadingButton(context, binding.btnStop)
- lifecycleScope.launch {
- withContext(Dispatchers.IO) {
- val packages = mutableListOf<String>()
- if (binding.cbGsf.isChecked) {
- packages.add(PACKAGE_GSF)
- }
- if (binding.cbGms.isChecked) {
- packages.add(PACKAGE_GMS)
- }
- if (binding.cbSms.isChecked) {
- packages.add(PACKAGE_MESSAGING)
- }
- packages.forEach {
- shellRun(it.kill())
- }
- }
- binding.btnStop.setIconResource(R.drawable.ic_done)
- binding.btnStop.text = "OK"
- delay(1500)
- binding.btnStop.isEnabled = true
- binding.btnStop.icon = null
- binding.btnStop.text = "Stop"
- }
- }
- private suspend fun installApk(url: String) {
- if (url.isEmpty()) {
- Toast.makeText(context, "URL is empty", Toast.LENGTH_SHORT).show()
- return
- }
- if (!url.endsWith(".apk")) {
- Toast.makeText(context, "URL is not an APK", Toast.LENGTH_SHORT).show()
- return
- }
- if (!url.startsWith("http")) {
- Toast.makeText(context, "URL is not valid", Toast.LENGTH_SHORT).show()
- return
- }
- var job: Job? = null
- lateinit var dialogBinding: DialogUpdateBinding
- lateinit var dialog: AlertDialog
- withContext(Dispatchers.Main) {
- dialogBinding = DialogUpdateBinding.inflate(layoutInflater)
- dialog = MaterialAlertDialogBuilder(requireContext())
- .setTitle("Installing...")
- .setView(dialogBinding.root)
- .setCancelable(false)
- .setNegativeButton("Cancel") { _, _ ->
- job?.cancel()
- }
- .create()
- dialog.show()
- }
- job = CoroutineScope(Dispatchers.IO).launch {
- try {
- val file = File.createTempFile("files", ".apk")
- ktorClient.prepareGet(url)
- .execute { httpResponse ->
- val channel: ByteReadChannel = httpResponse.body()
- while (!channel.isClosedForRead) {
- val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
- while (!packet.isEmpty) {
- val bytes = packet.readBytes()
- file.appendBytes(bytes)
- withContext(
- Dispatchers.Main
- ) {
- dialogBinding.progressBar.isIndeterminate = false
- dialogBinding.progressBar.progress =
- (file.length() * 100 / httpResponse.contentLength()!!).toInt()
- }
- }
- }
- }
- Log.i(tag, "A file saved to ${file.path}")
- shellRun("pm install -d -r ${file.path}")
- } catch (e: Exception) {
- Log.e(tag, "Failed to download apk", e)
- }
- withContext(Dispatchers.Main) {
- dialog.dismiss()
- }
- }
- }
- }
|