Compare commits

..

8 Commits

Author SHA1 Message Date
Administrator 940929a50b 留存文件恢复 2025-08-06 14:43:32 +08:00
Administrator 2e26323913 不检查更新 2025-08-02 11:12:54 +08:00
Administrator 4e5287047f log修改 2025-07-30 18:31:53 +08:00
Administrator 5a0aa60061 log修改 2025-07-30 15:23:08 +08:00
Administrator a69be9ced5 data recover 2025-07-30 15:04:12 +08:00
Administrator 1250e0150b aflog data 2025-07-29 16:47:47 +08:00
Administrator 72168ba702 sign config 2025-07-18 18:57:32 +08:00
Administrator 20e07e4f2b key 2025-07-18 18:52:18 +08:00
16 changed files with 220 additions and 452 deletions

View File

@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-07-07T06:37:35.266033300Z">
<DropdownSelection timestamp="2025-08-02T03:09:35.609697900Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="Default" identifier="serial=8.217.74.194:8924;connection=1af33e42" />
<DeviceId pluginId="Default" identifier="serial=8.217.74.194:8924;connection=5f91b786" />
</handle>
</Target>
</DropdownSelection>

View File

@ -1,3 +1,4 @@
import com.android.build.gradle.internal.api.ApkVariantOutputImpl
plugins {
alias(libs.plugins.android.application)
@ -9,7 +10,7 @@ android {
compileSdk = 35
signingConfigs {
getByName("release") {
create("release") {
storeFile = file("key.jks")
storePassword = "androidgrape"
keyAlias = "key0"
@ -29,6 +30,7 @@ android {
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
@ -48,6 +50,19 @@ android {
viewBinding = true
buildConfig = true
}
applicationVariants.all {
val variant = this
variant.outputs.all {
val versionName = variant.versionName
val versionCode = variant.versionCode
val outputFileName = "app-${variant.applicationId}-v${versionName}-${versionCode}.apk"
if (this is ApkVariantOutputImpl) {
this.outputFileName = outputFileName
}
}
}
}
dependencies {

BIN
app/key.jks Normal file

Binary file not shown.

View File

@ -3,6 +3,7 @@ package com.android.grape
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
@ -10,16 +11,21 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.android.grape.databinding.ActivityMainBinding
import com.android.grape.job.MonitorService
import com.android.grape.util.BackupUtils
import com.android.grape.util.BackupUtils.killRecordProcess
import com.android.grape.util.ClashUtil
import com.android.grape.util.FileUtils
import com.android.grape.util.MockTools
import com.android.grape.util.NotificationPermissionHandler
import com.android.grape.util.ScriptUtils.registerScriptResultReceiver
import com.android.grape.util.ScriptUtils.unregisterScriptResultReceiver
import com.android.grape.util.ShellUtil
import com.android.grape.util.StoragePermissionHelper
import com.android.grape.util.TaskUtils
import kotlinx.coroutines.launch
/**
* public class MainActivity extends AppCompatActivity
@ -75,6 +81,10 @@ class MainActivity : AppCompatActivity() {
}
viewBinding.stop.setOnClickListener {
killRecordProcess(this, packageName)
// lifecycleScope.launch {
// BackupUtils.backUp(this@MainActivity, "com.policybazaar")
// BackupUtils.recoverRecordData(this@MainActivity)
// }
}
}

View File

@ -31,7 +31,9 @@ class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
instance = this
LogUtils.getConfig().setLog2FileSwitch(true)
LogUtils.getConfig()
.setBorderSwitch(false)
.setLog2FileSwitch(true)
initEvn()
}

View File

@ -24,23 +24,15 @@ class OpenAppService : JobIntentService() {
override fun onHandleWork(intent: Intent) {
println("IOSTQ:isCanAuto() == " + isCanAuto)
println("IOSTQ:getCanAutoLc() == " + canAutoLc)
recordPackageName?.let {
ServiceUtils.setEnableApp(it, true)
}
ServiceUtils.setEnableApp("org.mozilla.firefox", true)
ServiceUtils.setEnableApp("com.google.android.webview", true)
ServiceUtils.setEnableApp("com.android.chrome", true)
ServiceUtils.setEnableApp("com.UCMobile", true)
try {
ChangeDeviceInfoUtil.changeDevice(callBack = object : ChangeCallBack {
override fun changeSuccess() {
runCatching {
if (isCanAuto && canAutoLc.isNotEmpty()) {
val deviceInfo = DeviceDataAccessor.getDeviceInfo(applicationContext, DeviceInfoHelper.getDeviceId())
FileUtils.writePackageName(recordPackageName?:"")
// FileUtils.writePackageName(recordPackageName?:"")
FileUtils.writeDevice(recordPackageName?:"", deviceInfo?: "")
FileUtils.runPlugin(recordPackageName?:"")
MockTools.exec("pm grant ${AUTO_JSPACKAGENAME} android.permission.READ_EXTERNAL_STORAGE") //sdcard权限
MockTools.exec("pm grant ${AUTO_JSPACKAGENAME} android.permission.SYSTEM_ALERT_WINDOW") //悬浮窗权限
MockTools.exec("settings put secure enabled_accessibility_services ${AUTO_JSPACKAGENAME}/${AUTO_JSPACKAGENAME}.core.accessibility.AccessibilityService")
doScript(this@OpenAppService, AUTO_JSPACKAGENAME) //autojs

View File

@ -2,6 +2,7 @@ package com.android.grape.job
import android.content.Context
import android.content.Intent
import android.os.Environment
import android.os.Handler
import android.os.Looper
import androidx.core.app.JobIntentService
@ -24,11 +25,13 @@ import com.android.grape.data.AppState.lastUpdateTime
import com.android.grape.data.AppState.logBuffer
import com.android.grape.data.AppState.preClickRecordId
import com.android.grape.data.AppState.recordId
import com.android.grape.data.AppState.recordPackageName
import com.android.grape.data.AppState.reloginRecordId
import com.android.grape.net.AfClient.postData
import com.android.grape.util.AppUtils.getAppAfVer
import com.android.grape.util.DeviceUtils.getMainUserAndGroup
import com.android.grape.util.InstallUtils.isInstallRet
import com.android.grape.util.MockTools
import com.android.grape.util.MyPost
import com.android.grape.util.ShellUtils.chownSh
import com.android.grape.util.ShellUtils.delFileSh
@ -68,6 +71,7 @@ class SendCallbackJobService : JobIntentService() {
} else {
sendLogEvent()
}
MockTools.exec("rm -rf ${Environment.getExternalStorageDirectory()}/script/${recordPackageName}/afLog.txt")
}
setFinish(this@SendCallbackJobService)
}
@ -116,7 +120,7 @@ class SendCallbackJobService : JobIntentService() {
// logInfoJo.put("setConfLog", Util.getParamsJson());
paramsJo.put("logInfo", logInfoJo)
var params: String? = null
params = paramsJo?.toString() ?: "error"
params = paramsJo.toString()
var nRetryCount = 0
do {
@ -179,7 +183,7 @@ class SendCallbackJobService : JobIntentService() {
paramsJo.put("backUpFiles", backupResult)
}
var params: String? = null
params = paramsJo?.toString() ?: "error"
params = paramsJo.toString()
var nRetryCount = 0
do {
@ -239,7 +243,7 @@ class SendCallbackJobService : JobIntentService() {
}
chownSh(fileName, getMainUserAndGroup(this))
var url = "http://39.103.73.250/tt/ddj/backup.do"
var url = "http://47.83.1.116/tt/ddj/backup.do"
// if (Util.backUpServerIp != "") {
// url = "http://" + Util.backUpServerIp + "/tt/ddj/backup.do"
// }

View File

@ -35,7 +35,6 @@ import com.android.grape.data.AppState.isNeedRestored
import com.android.grape.data.AppState.keepOpen
import com.android.grape.data.AppState.lang
import com.android.grape.data.AppState.logBuffer
import com.android.grape.data.AppState.paramsJson
import com.android.grape.data.AppState.proxyCountry
import com.android.grape.data.AppState.proxyIp
import com.android.grape.data.AppState.proxyPort
@ -93,7 +92,6 @@ object ConfigManager {
isNeedRestored = false
taskJson = null
installRet = false
paramsJson = null
recordPackageName = null
recordFileName = null
recordExtraFileName = null

View File

@ -1,23 +1,7 @@
package com.android.grape.net
import android.content.Context
import android.util.Log
import com.android.grape.data.AppState
import com.android.grape.data.AppState.clickServerTimeFromGP
import com.android.grape.data.AppState.clickTime
import com.android.grape.data.AppState.instalTimeFromGp
import com.android.grape.data.AppState.installTime
import com.android.grape.data.AppState.lastUpdateTime
import com.android.grape.data.AppState.paramsJson
import com.android.grape.data.AppState.recordPackageName
import com.android.grape.data.AppState.referer
import com.android.grape.data.AppState.taskJson
import com.android.grape.manager.TrackingManager.genInstallTimeFromGP
import com.android.grape.util.DeviceUtils.getGoogleAdId
import com.android.grape.util.FileUtils
import com.android.grape.util.ServiceUtils
import com.android.grape.util.TaskUtils
import com.blankj.utilcode.util.LogUtils
import java.io.BufferedInputStream
import java.io.ByteArrayOutputStream
import java.io.File
@ -28,7 +12,6 @@ import java.io.OutputStream
import java.io.UnsupportedEncodingException
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLDecoder
/**
* @Time: 2025-07-16 16:07
@ -39,90 +22,6 @@ import java.net.URLDecoder
*/
object AfClient {
@Throws(IOException::class)
fun setInfo(context: Context): Boolean {
val url = "http://127.0.0.1:8090/ctl/setinfo"
//安装时间
try {
clickTime = taskJson!!.getLong("clickTime")
val deviceJo = paramsJson!!.getJSONObject("device")
// installTimeFromGP = (long) (clickTime / 1000) + (clickTime % 7) + 3;
installTime = System.currentTimeMillis()
Thread.sleep(2000)
Log.d("IOSTQ:installTime == ", installTime.toString() + "")
Log.d("IOSTQ:clickTime == ", clickTime.toString() + "")
val time = genInstallTimeFromGP(clickTime, installTime)
// installTimeFromGP = firstInstallTime / 1000;
installTime = System.currentTimeMillis()
lastUpdateTime = installTime
LogUtils.d("IOSTQ:lastUpdateTime ", lastUpdateTime.toString() + "")
deviceJo.put("firstInstallTime", installTime)
deviceJo.put("lastUpdateTime", lastUpdateTime)
deviceJo.put("installTimeFromGP", instalTimeFromGp)
val installServerTimeFromGP = time[1] // + (installTimeFromGP % 2) + 1;
deviceJo.put("installServerTimeFromGP", installServerTimeFromGP)
val clickTimeToGp = (clickTime / 1000)
deviceJo.put("clickTimeToGP", clickTimeToGp)
val clickServerTimeToGP = time[0] / 1000 // + (clickTimeToGp % 2) + 1;
deviceJo.put("clickServerTimeToGP", clickServerTimeToGP)
AppState.installServerTimeFromGP = installServerTimeFromGP
clickServerTimeFromGP = clickServerTimeToGP
if (taskJson!!.has("clickData")) {
val clickdata = taskJson!!.getJSONObject("clickData")
if (clickdata.has("referer") && clickdata.getString("referer").length > 10) {
referer = clickdata.getString("referer")
}
} else {
referer = ""
}
if (referer != null && referer!!.length > 10) {
deviceJo.put("referrerFromGP", URLDecoder.decode(referer, "UTF-8"))
} else {
deviceJo.put("referrerFromGP", "utm_source=google-play&utm_medium=organic")
deviceJo.put("clickServerTimeToGP", 0)
deviceJo.put("clickTimeToGP", 0)
deviceJo.put("installTimeFromGP", 0)
deviceJo.put("installServerTimeFromGP", 0)
}
//JSONObject proxyJo = paramsJson.getJSONObject("proxy");
//proxyJo.put("forwardIp", Util.getDelegateIp());
Log.d("IOSTQ", "firstInstalTime == " + installTime)
Log.d("IOSTQ", "paramsJson == " + paramsJson)
val origin_gaid: String = getGoogleAdId(context) ?: ""
deviceJo.put("origin_gaid", origin_gaid)
paramsJson!!.put("device", deviceJo)
val params = paramsJson.toString()
ServiceUtils.setEnableApp(recordPackageName ?: "", true)
ServiceUtils.setEnableApp("org.mozilla.firefox", true)
ServiceUtils.setEnableApp("com.google.android.webview", true)
ServiceUtils.setEnableApp("com.android.chrome", true)
ServiceUtils.writeFile("/data/system/device.txt", params)
Log.d("IOSTQ:param == ", params)
// paramsJson.put("proxy", proxyJo);
} catch (e: Exception) {
Log.d("IOSTQ", e.message!!)
e.printStackTrace()
}
// printStr("execSetJson params:"+params);
// writeFileToSDCard(params);
try {
// String ret = new MyPost().PostData(context, params.getBytes("utf-8"), url);
// Log.i("TaskUtils", "set info ret : " + ret);
} catch (e: Exception) {
e.printStackTrace()
}
return true
}
fun downloadFile(httpUrl: String, fileName: String): Boolean {
Log.i(
"AfClient",

View File

@ -42,7 +42,9 @@ import com.android.grape.util.ContextUtils.getBaseFilesDir
import com.android.grape.util.ContextUtils.getRecordDataDirName
import com.android.grape.util.ContextUtils.getRecordDataFileName
import com.android.grape.util.ContextUtils.getRecordExtraFileName
import com.android.grape.util.ContextUtils.getRecordListTxtFileName
import com.android.grape.util.ContextUtils.getRecordSdcardApkVerFileName
import com.android.grape.util.ContextUtils.getRecordTxtFileName
import com.android.grape.util.ContextUtils.getSessionTxtFileName
import com.android.grape.util.DeviceUtils.getUserAndGroupSh
import com.android.grape.util.FileUtils.forceMakeDir
@ -211,7 +213,7 @@ object AppUtils {
fun installRecord(context: Context): Boolean {
var installRet = false
startInstallTime = System.currentTimeMillis()
if (CheckAppNeedUpgrade(context) || !checkAppInstalled(
if (!checkAppInstalled(
context,
recordPackageName
)
@ -220,20 +222,17 @@ object AppUtils {
val file = File(getRecordSdcardApkVerFileName(context))
var extraFile: File? = null
if (recordExtraFileName?.isNotEmpty() == true) {
extraFile = File(ContextUtils.getRecordExtraFileName(context))
extraFile = File(getRecordExtraFileName(context))
}
installRet = installApk(context, file, extraFile) && AppUtils.checkAppInstalled(
installRet = installApk(context, file, extraFile) && checkAppInstalled(
context,
recordPackageName
)
if (installRet && !videoProxy.contains("123.56.44.45")) {
//检查是否有新版本
if (!CheckAppNeedUpgrade(context)) {
file.delete()
extraFile?.delete()
}
file.delete()
extraFile?.delete()
}
} catch (e: Exception) {
e.printStackTrace()
@ -397,8 +396,8 @@ object AppUtils {
fun installObb(context: Context, extraFile: File) {
val userAndGroup = getUserAndGroupSh(
context,
context.packageName,
getBaseFilesDir(context) + "/" + monitorDir + "/" + apkDir + "/" + context.packageName + ".txt"
recordPackageName,
getRecordTxtFileName( context)
)
val destExtraFile = File(
@ -602,10 +601,7 @@ object AppUtils {
try {
var url = "http://39.103.73.250/tt/upload/ddj/$recordFileName"
var ret = false
ret = if (checkAppInstalled(
context,
recordPackageName
) || !CheckAppNeedUpgrade(context)
ret = if (checkAppInstalled(context, recordPackageName)
) {
true
} else {
@ -620,17 +616,12 @@ object AppUtils {
ret = downloadFile(extraUrl, getRecordExtraFileName(context))
}
if (isNeedRestored) {
println("IOSTQ:开始下载留存文件")
Log.i("AppUtils","IOSTQ:开始下载留存文件")
taskJson?.let {
if (it.has("BackupFileUrl1") && it.getString("BackupFileUrl1")
.isNotEmpty()
) {
var restored_zip =
"http://192.168.1.111/tt/" + it.getString("BackupFileUrl1")
if (backUpServerIp.isNotEmpty()) {
restored_zip =
"http://" + backUpServerIp + "/tt/" + it.getString("BackupFileUrl1")
}
var restored_zip = "http://47.83.1.116/tt/" + it.getString("BackupFileUrl1")
ret = downloadFile(restored_zip, getRecordDataFileName(context))
}
}

View File

@ -16,6 +16,7 @@ import com.android.grape.util.ContextUtils.getMonitorDir
import com.android.grape.util.ContextUtils.getRecordDataDirName
import com.android.grape.util.ContextUtils.getRecordDataFileName
import com.android.grape.util.ContextUtils.getRecordListTxtFileName
import com.android.grape.util.ContextUtils.getRecordTxtFileName
import com.android.grape.util.DeviceUtils.getMainUserAndGroup
import com.android.grape.util.DeviceUtils.getUserAndGroupSh
import com.android.grape.util.FileUtils.forceMakeDir
@ -55,8 +56,7 @@ object BackupUtils {
}
try {
val zipDirName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName
val zipFileName =
getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName + ".zip"
val zipFileName = getBaseFilesDir(context) + "/" + monitorDir + "/" + packageName + ".zip"
Log.i(
"BackupUtils",
"backupDataFile-> zipDirName:$zipDirName ; zipFileName:$zipFileName"
@ -86,18 +86,16 @@ object BackupUtils {
}
val uid = getUserAndGroupSh(
context.applicationContext,
context.packageName,
getBaseFilesDir(context) + "/" + monitorDir + "/" + apkDir + "/" + context.packageName + ".txt"
recordPackageName,
getRecordTxtFileName(context)
)
chownSh(getMonitorDir(context), uid)
val copySucc = File(zipDirName).exists()
Log.d("TAG", "backupDataFile: ------------------>")
val copySucc = FileUtils.copyFolderSh(apkDataPath,zipDirName)
Log.i("BackupUtils", "copyFolder($apkDataPath,$zipDirName) = $copySucc")
//TODO将apk包所在的文件夹备份到DownLoad文件夹下
//TODO将新生成的文件夹进行压缩
if (copySucc) {
FileUtils.writeAfLog()
chownSh(zipDirName, getMainUserAndGroup(context))
val afFile = File("$zipDirName/AFPOST.txt")
zipSh(zipDirName, zipFileName)
delFileSh(zipDirName)
@ -346,18 +344,21 @@ object BackupUtils {
if (reloginDataDir == null) {
return false
}
unZipFileSh(zipFile, dataDir)
val dataFile = File("$dataDir$recordPackageName")
if (!dataFile.exists()) {
dataFile.mkdir()
}
unZipFileSh(zipFile, dataFile.absolutePath)
val userAnGroup = getUserAndGroupSh(
context,
context.packageName,
getBaseFilesDir(context) + "/" + monitorDir + "/" + apkDir + "/" + context.packageName + ".txt"
recordPackageName ?: return false,
getRecordTxtFileName( context)
)
Log.i("BackupUtils", "recoverRecordData->userAndGroup:$userAnGroup")
File(reloginDataDir).parentFile?.absolutePath?.let {
copyFolderSh(
"$dataDir/$recordPackageName",
"$dataDir$recordPackageName",
it
)
}

View File

@ -135,17 +135,18 @@ object FileUtils {
public fun forceMakeDir(file: File) {
if (!file.exists()) {
val parent = file.parentFile
parent?.exists()?.let {
if (!it) {
MockTools.exec("mkdir $parent")
forceMakeDir(parent)
// file.mkdirs();
} else {
MockTools.exec("mkdir $file")
}
}
file.mkdirs()
// val parent = file.parentFile
//
// parent?.exists()?.let {
// if (!it) {
// MockTools.exec("mkdir $parent")
// forceMakeDir(parent)
// // file.mkdirs();
// } else {
// MockTools.exec("mkdir $file")
// }
// }
}
}
@ -278,12 +279,9 @@ object FileUtils {
"start zipSh : $zipDirName ; $zipFileName"
)
try {
val zipDir = File(zipDirName)
val zipFile = File(zipFileName)
var cmd = "cd " + (zipDir.parentFile?.absolutePath ?: "") + "|"
cmd += "tar -zcvf " + zipFile.name + " " + zipDir.name
Log.i("FileUtils", "zipSh-> cmd:$cmd")
MockTools.exec(cmd)
val cmdString = "tar -zcvf $zipFileName -C $zipDirName ."
Log.i("FileUtils", "zipSh-> cmd:$cmdString")
MockTools.exec(cmdString)
} catch (e: Exception) {
e.printStackTrace()
}
@ -379,30 +377,7 @@ object FileUtils {
* @return 返回内容
*/
fun getString(filePath: String, filename: String): String {
var inputStream: FileInputStream? = null
try {
inputStream = FileInputStream(File(filePath + filename))
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
var inputStreamReader: InputStreamReader? = null
try {
inputStreamReader = InputStreamReader(inputStream, "UTF-8")
} catch (e1: UnsupportedEncodingException) {
e1.printStackTrace()
}
val reader = BufferedReader(inputStreamReader)
val sb = StringBuffer("")
var line: String?
try {
while ((reader.readLine().also { line = it }) != null) {
sb.append(line)
sb.append("\n")
}
} catch (e: IOException) {
e.printStackTrace()
}
return sb.toString()
return File(filePath, filename).takeIf { it.exists() }?.readText() ?: ""
}
/**
@ -598,6 +573,36 @@ object FileUtils {
}
}
fun writeAfLog() {
val filePath = "/data/data/${recordPackageName}/log.txt"
ShellUtil.execRootCmdAndGetResult("chmod 777 $filePath")
val afLog = ShellUtil.execRootCmdAndGetResult("cat $filePath")
val file = File(
Environment.getExternalStorageDirectory(),
"script/${recordPackageName}/afLog.txt"
)
val parentDir = file.getParentFile()
if (parentDir != null && !parentDir.exists()) {
val dirsCreated = parentDir.mkdirs()
if (!dirsCreated) {
Log.e("FileWrite", "Failed to create directories: $parentDir")
return
}
}
LogUtils.d("FileUtils", "afLog: $afLog", null)
try {
BufferedOutputStream(
FileOutputStream(file)
).use { bos ->
bos.write(afLog.toByteArray(StandardCharsets.UTF_8))
bos.flush() // 确保数据写入磁盘
}
} catch (e: IOException) {
Log.e("FileWrite", "Failed to write afLog: $afLog", e)
// 6. 可以考虑添加重试机制或通知用户
}
}
fun writeDevice(packageName: String, device: String) {
LogUtils.d("FileUtils", "writeDevice: $device")
val base64Content: String =
@ -605,21 +610,20 @@ object FileUtils {
// 构造安全命令
val filePath = "/data/data/$packageName/device.txt"
val cmd = "sh -c 'printf %s '\''" + base64Content + "'\'' > " + filePath + "'"
val result = ShellUtils.execRootCmdAndGetResult(cmd)
ShellUtils.execRootCmdAndGetResult("chmod 777 $filePath")
LogUtils.d("FileUtils", "writeDevice: $result")
val result = ShellUtil.execRootCmdAndGetResult(cmd)
ShellUtil.execRootCmdAndGetResult("chmod 777 $filePath")
}
fun runPlugin(packageName: String) {
val cmd =
"apmt patch add -n ArmCloudAF -p $packageName -f /sdcard/Download/ArmCloudAF_lo.apk"
val result = ShellUtils.execRootCmdAndGetResult(cmd)
val result = ShellUtil.execRootCmdAndGetResult(cmd)
LogUtils.d("FileUtils", "runPlugin: $result")
}
fun deletePlugin() {
val cmd = "apmt patch del -n ArmCloudAF"
val result = ShellUtils.execRootCmdAndGetResult(cmd)
val result = ShellUtil.execRootCmdAndGetResult(cmd)
LogUtils.d("FileUtils", "deletePlugin: $result")
}
@ -692,4 +696,63 @@ object FileUtils {
return ""
}
fun copyFolderSh(oldPath: String, newPath: String): Boolean {
Log.i("TaskUtil", "start copyFolderSh : $oldPath ; $newPath")
try {
// 使用 File API 确保路径处理正确
val src = File(oldPath)
val dst = File(newPath)
// 构造命令(注意 shell 特殊字符的转义)
val safeOldPath = src.absolutePath.replace(" ", "\\ ").replace("\"", "\\\"")
val safeNewPath = dst.absolutePath.replace(" ", "\\ ").replace("\"", "\\\"")
val cmd = "cp -r -f \"$safeOldPath\"/* \"$safeNewPath\""
Log.i("TaskUtil", "copyFolderSh cmd: $cmd")
// 调用 MockTools 执行
val result: String = ShellUtils.execRootCmdAndGetResult(cmd)
// val chmod = "chmod 777 \"$safeNewPath\""
// val chmodResult: String? = ShellUtils.execRootCmdAndGetResult(chmod)
// recursiveChmod777(dst)
Log.i("TaskUtil", "Command executed successfully: $result")
return true
} catch (e: java.lang.Exception) {
LogUtils.d(
Log.ERROR,
"TaskUtil",
"Error occurred during copyFolderSh operation",
e
)
return false
}
}
fun recursiveChmod777(dir: File?) {
if (dir == null || !dir.exists()) {
Log.e("Chmod", "目录不存在或为null")
return
}
// 先修改当前目录权限
val currentPath = dir.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\"")
var chmodCmd = "chmod 777 \"$currentPath\""
ShellUtils.execRootCmdAndGetResult(chmodCmd)
// 递归处理子项
val children = dir.listFiles()
if (children != null) {
for (child in children) {
if (child.isDirectory()) {
recursiveChmod777(child) // 递归处理子目录
} else {
val filePath = child.getAbsolutePath().replace(" ", "\\ ").replace("\"", "\\\"")
chmodCmd = "chmod 777 \"$filePath\""
ShellUtils.execRootCmdAndGetResult(chmodCmd)
}
}
}
}
}

View File

@ -5,26 +5,17 @@ import android.util.Log
import com.android.grape.data.AppState.appVersion
import com.android.grape.data.AppState.appVersionCode
import com.android.grape.data.AppState.backUpServerIp
import com.android.grape.data.AppState.cacheJson
import com.android.grape.data.AppState.canAutoLc
import com.android.grape.data.AppState.clickServerTimeFromGP
import com.android.grape.data.AppState.clickTime
import com.android.grape.data.AppState.ctit
import com.android.grape.data.AppState.defaultPRoxyJo
import com.android.grape.data.AppState.forwardIp
import com.android.grape.data.AppState.fuzzy_domain
import com.android.grape.data.AppState.fuzzy_proxy
import com.android.grape.data.AppState.instalTimeFromGp
import com.android.grape.data.AppState.installServerTimeFromGP
import com.android.grape.data.AppState.installTime
import com.android.grape.data.AppState.isCanAuto
import com.android.grape.data.AppState.isNeedBackup
import com.android.grape.data.AppState.isNeedReg
import com.android.grape.data.AppState.isNeedRestored
import com.android.grape.data.AppState.keepOpen
import com.android.grape.data.AppState.lang
import com.android.grape.data.AppState.lastUpdateTime
import com.android.grape.data.AppState.paramsJson
import com.android.grape.data.AppState.preClickRecordId
import com.android.grape.data.AppState.proxyCountry
import com.android.grape.data.AppState.proxyIp
@ -32,27 +23,15 @@ import com.android.grape.data.AppState.proxyPort
import com.android.grape.data.AppState.recordFileName
import com.android.grape.data.AppState.recordId
import com.android.grape.data.AppState.recordPackageName
import com.android.grape.data.AppState.referer
import com.android.grape.data.AppState.regEmailJson
import com.android.grape.data.AppState.reloginRecordId
import com.android.grape.data.AppState.scriptOpenApp
import com.android.grape.data.AppState.taskJson
import com.android.grape.data.AppState.trackingLink
import com.android.grape.data.AppState.ua
import com.android.grape.data.AppState.videoProxy
import com.android.grape.net.AfClient.postData
import com.android.grape.util.DeviceUtils.getGoogleAdId
import com.android.grape.util.FileUtils.forceMakeDir
import com.android.grape.util.ServiceUtils.WriteFile
import com.android.grape.util.TaskUtils.execRecord
import com.android.grape.util.TaskUtils.getReferer
import com.android.grape.util.TaskUtils.setFinish
import com.android.grape.util.TaskUtils.setRecordExtraFileName
import com.blankj.utilcode.util.LogUtils
import org.json.JSONObject
import java.io.File
import java.io.IOException
import java.net.URLDecoder
/**
* @Time: 2025-20-16 17:20
@ -207,166 +186,6 @@ object JsonUtils {
}
}
/**
* 通过处理任务 JSON 对象并向参数 JSON 对象添加各种属性来初始化操作所需的 JSON 参数
* 处理设备优惠和其他相关数据以准备完整的 JSON 结构
*
* @param context 用于执行各种操作的应用程序上下文例如在初始化期间写入文件和发送事件
* 例如在初始化期间写入文件和发送事件
* @return 如果 JSON 参数初始化成功则返回 true否则返回 false
*/
fun initParamsJson(context: Context): Boolean {
paramsJson = JSONObject().apply {
try {
taskJson?.let {
val deviceJo = it.getJSONObject("device")
LogUtils.e("deviceJo:$deviceJo")
LogUtils.e("deviceJo sensor:${deviceJo.optJSONArray("sensor")}")
val deviceParamJo: JSONObject = DeviceConvertUtil.MGConvert(deviceJo)
if (it.has("isCollectURL")) {
deviceJo.put("isCollectURL", true)
} else {
deviceJo.put("isCollectURL", false)
}
if (it.has("regInfo")) {
val regInfo = it.getJSONObject("regInfo")
var apks = File("/sdcard/Download/GoogleAccount.txt")
if (!apks.exists()) {
forceMakeDir(File("/sdcard/Download"))
apks = File("/sdcard/Download/GoogleAccount.txt")
}
WriteFile(apks.toString(), regInfo.toString())
sendRegEvent(context)
}
//add 20210409
val offerJo = it.getJSONObject("offer")
val apkprop = it.getJSONObject("apkProp")
val thirdDetect = offerJo.getString("thirdDetect")
if ("appsflyer".equals(thirdDetect, ignoreCase = true)) {
deviceParamJo.put("afVersion", offerJo.getString("thirdVer"))
}
deviceParamJo.put("installVersionFromGP", offerJo.getString("apkVer"))
put("device", deviceParamJo)
if (it.has("expand")) {
put("expand", it.getJSONObject("expand"))
}
put("offer", offerJo)
val proxyJo = defaultPRoxyJo
}
} catch (e: Exception) {
e.printStackTrace()
Log.i("JsonUtils", "initParamsJson error : " + e.message)
setFinish(context)
return false
}
}
return true
}
@Throws(IOException::class)
fun setRrInfo(context: Context): Boolean {
try {
clickTime = taskJson!!.getLong("clickTime")
val deviceJo = paramsJson!!.getJSONObject("device")
if (isNeedRestored) {
if (cacheJson != null) {
installTime =
cacheJson.getLong("firstInstallTime")
lastUpdateTime =
cacheJson.getLong("lastUpdateTime")
installServerTimeFromGP =
cacheJson.getLong("installServerTimeFromGP")
clickServerTimeFromGP =
cacheJson.getLong("clickServerTimeToGP")
instalTimeFromGp =
cacheJson.getLong("installTimeFromGP")
}
}
deviceJo.put("firstInstallTime", installTime)
deviceJo.put("lastUpdateTime", lastUpdateTime)
deviceJo.put("installTimeFromGP", instalTimeFromGp)
val installServerTimeFromGP = installServerTimeFromGP
deviceJo.put("installServerTimeFromGP", installServerTimeFromGP)
val clickTimeToGp = (clickTime / 1000)
deviceJo.put("clickTimeToGP", clickTimeToGp)
val clickServerTimeToGP = clickServerTimeFromGP
deviceJo.put("clickServerTimeToGP", clickServerTimeToGP)
if (taskJson!!.has("clickData")) {
val clickdata = taskJson!!.getJSONObject("clickData")
if (clickdata.has("referer")) {
referer = clickdata.getString("referer")
}
}
if (getReferer() != null) {
deviceJo.put("referrerFromGP", URLDecoder.decode(getReferer(), "UTF-8"))
} else {
deviceJo.put("referrerFromGP", "utm_source=google-play&utm_medium=organic")
deviceJo.put("clickServerTimeToGP", 0)
deviceJo.put("clickTimeToGP", 0)
deviceJo.put("installTimeFromGP", 0)
deviceJo.put("installServerTimeFromGP", 0)
}
val origin_gaid: String = getGoogleAdId(context) ?: ""
deviceJo.put("origin_gaid", origin_gaid)
paramsJson!!.put("device", deviceJo)
val params = paramsJson.toString()
ServiceUtils.setEnableApp(recordPackageName ?: "", true)
ServiceUtils.setEnableApp("org.mozilla.firefox", true)
ServiceUtils.setEnableApp("com.google.android.webview", true)
ServiceUtils.setEnableApp("com.android.chrome", true)
ServiceUtils.writeFile("/data/system/device.txt", params)
Log.d("IOSTQ:param == ", params)
return true
// paramsJson.put("proxy", proxyJo);
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* 通过向指定的服务器URL提出邮政请求来发送注册事件
*
* @param上下文调用该方法的上下文用于执行网络操作
* @return True如果已成功处理注册事件错误如果操作期间发生错误
*/
private fun sendRegEvent(context: Context): Boolean {
val url = "http://123.56.44.45/tt/ddj/reg.do?recordId=$recordId"
Log.i("JsonUtils", "url:$url")
try {
val ret: String? = postData("".toByteArray(), url)
Log.i("JsonUtils", "ret:$ret")
val jo = JSONObject(ret ?: "")
if (jo.getInt("code") == 1) {
regEmailJson = jo.getJSONObject("emailInfo")
}
return true
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* 在JSON配置上执行一组操作它删除了特定的日志文件处理JSON参数
* 并记录所需的数据如果例外它会记录错误并执行清理
@ -377,11 +196,8 @@ object JsonUtils {
@Throws(Exception::class)
fun execSetJson(context: Context) {
try {
MockTools.exec("rm -rf /data/system/Logs.txt")
JsonUtils.afterJson()
if (JsonUtils.initParamsJson(context)) {
execRecord(context)
}
afterJson()
execRecord(context)
} catch (e: Exception) {
e.printStackTrace()
Log.i("TaskUtils", "execSetJson error : " + e.message)

View File

@ -20,6 +20,7 @@ import com.android.grape.util.ShellUtils.delFileSh
import com.android.grape.util.ShellUtils.unzipAPkSh
import com.android.grape.util.ShellUtils.unzipScriptSh
import com.blankj.utilcode.util.LogUtils
import java.io.File
/**
* @Time: 2025-16-16 19:16
@ -46,8 +47,8 @@ object ScriptUtils {
fun execDownScript(): Boolean {
var isDownload = true
if (isCanAuto) {
Log.i("TaskUtils", "start to execDownScript")
val script_url = "http://39.103.73.250/tt/" + canAutoLc
Log.i("TaskUtils", "start to execDownScript $script_url")
isDownload = downloadFile(script_url, script_path)
if (!isDownload) {
Log.i("TaskUtils", "execDownScript isDownload : $isDownload")
@ -70,7 +71,14 @@ object ScriptUtils {
}
return
}
val scriptFile = File(src)
if (!scriptFile.exists()) {
LogUtils.e("AutoJsUtil", "Script file not found")
runOnUiThread {
Toast.makeText(context, "Script file not found", Toast.LENGTH_SHORT).show()
}
return
}
val intent = Intent()
intent.setClassName(
"org.autojs.autojs6",

View File

@ -208,9 +208,8 @@ object ShellUtils {
} catch (e: IOException) {
LogUtils.e(
Log.ERROR,
"ShellUtils",
"Error while reading process error stream: ${e.message}",
e
"cmd:$cmd",
"Error while reading process error stream: ${e.message}"
)
}
}
@ -478,8 +477,7 @@ object ShellUtils {
fun delFilesSh(dir: String, prefix: String?) {
try {
var cmd = "cd $dir|"
cmd += "rm -rf $prefix*"
var cmd = "rm -rf $dir$prefix*"
Log.i("ShellUtils", "delFilesSh-> cmd:$cmd")
MockTools.exec(cmd)
} catch (e: Exception) {
@ -514,10 +512,9 @@ object ShellUtils {
fun unZipFileSh(zipFileName: String, dataDir: String) {
try {
var cmd = "cd $dataDir|"
cmd += "tar -xvf " + File(zipFileName).name
Log.i("ShellUtils", "unZipFileSh-> cmd:$cmd")
MockTools.exec(cmd)
val cmdString = "tar -zxvf $zipFileName -C $dataDir"
Log.i("ShellUtils", "unZipFileSh-> cmd:$cmdString")
MockTools.exec(cmdString)
} catch (e: Exception) {
e.printStackTrace()
}

View File

@ -2,62 +2,50 @@ package com.android.grape.util
import android.R.attr.name
import android.content.Context
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.util.Log
import com.android.grape.net.AfClient.downloadFile
import com.android.grape.MainApplication
import com.android.grape.data.AppState
import com.android.grape.data.AppState.afLog
import com.android.grape.data.AppState.apkDir
import com.android.grape.data.AppState.apk_path
import com.android.grape.data.AppState.appDataUrl
import com.android.grape.data.AppState.baoming
import com.android.grape.data.AppState.canAutoLc
import com.android.grape.data.AppState.clickTime
import com.android.grape.data.AppState.installRet
import com.android.grape.data.AppState.isCanAuto
import com.android.grape.data.AppState.logBuffer
import com.android.grape.data.AppState.monitorDir
import com.android.grape.data.AppState.nRandom
import com.android.grape.data.AppState.paramsJson
import com.android.grape.data.AppState.recordExtraFileName
import com.android.grape.data.AppState.recordFileName
import com.android.grape.data.AppState.recordPackageName
import com.android.grape.data.AppState.referer
import com.android.grape.data.AppState.regEmailJson
import com.android.grape.data.AppState.scriptOpenApp
import com.android.grape.data.AppState.baoming
import com.android.grape.util.FileUtils.getName
import com.android.grape.data.AppState.zip_name
import com.android.grape.data.AppState.apk_path
import com.android.grape.net.AfClient.postData
import com.android.grape.util.ContextUtils.getRecordDataDirName
import com.android.grape.data.AppState.taskJson
import com.android.grape.data.AppState.zip_name
import com.android.grape.job.DownloadAppJobService
import com.android.grape.job.MonitorService
import com.android.grape.job.UnInstallService
import com.android.grape.manager.ConfigManager
import com.android.grape.manager.ConfigManager.initDefaultAppJo
import com.android.grape.manager.ConfigManager.initDefaultProxyJo
import com.android.grape.net.AfClient.downloadFile
import com.android.grape.net.AfClient.postData
import com.android.grape.util.AppUtils.execTargetApp
import com.android.grape.util.AppUtils.getApkPackageName
import com.android.grape.util.AppUtils.setTopApp
import com.android.grape.util.ContextUtils.getBaseFilesDir
import com.android.grape.util.ContextUtils.getRecordDataDirName
import com.android.grape.util.FileUtils.forceMakeDir
import com.android.grape.util.FileUtils.getName
import com.android.grape.util.FileUtils.getRecordDataFileName
import com.android.grape.util.JsonUtils.execSetJson
import com.blankj.utilcode.util.LogUtils
import org.json.JSONObject
import java.io.File
import java.io.IOException
import java.io.PrintWriter
import java.util.Locale
import kotlin.math.min
/**
@ -143,8 +131,13 @@ object TaskUtils {
}
fun getAfLog(): String {
//return Util.afLog;
return ServiceUtils.readFile("/data/system/Logs.txt")
File(
Environment.getExternalStorageDirectory(),
"script/${recordPackageName}/afLog.txt"
)
val afLog = FileUtils.getString("${Environment.getExternalStorageDirectory()}/script/${recordPackageName}", "afLog.txt")
Log.d("TaskUtils", "getAfLog: $afLog")
return afLog
}
@ -192,22 +185,18 @@ object TaskUtils {
" ".toByteArray(charset = Charsets.UTF_8),
"$url?$params"
)
LogUtils.e("IOSTQ:execReloginTask->result:$result")
LogUtils.d("IOSTQ:execReloginTask->result:$result")
if (result != null && result.isNotEmpty()) {
taskJson = JSONObject(result).apply {
val code = getInt("code")
if (code == 1) {
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor")
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor/apks")
JsonUtils.execSetJson(context)
clickTime = 1
} else {
Log.i(
"TaskUtils",
"request result code invalid : $code"
)
setFinish(context)
}
taskJson = JSONObject(result)
val code = taskJson?.getInt("code")
if (code == 1) {
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor")
MockTools.exec("chmod 777 /data/data/com.android.grape/files/monitor/apks")
execSetJson(context)
clickTime = 1
} else {
Log.i("TaskUtils", "request result code invalid : $code")
setFinish(context)
}
} else {
Log.i("TaskUtils", "request result is null")
@ -240,7 +229,7 @@ object TaskUtils {
"$url?$params"
)
LogUtils.e("request result : $result")
LogUtils.d("request result : $result")
if (result != null && result.isNotEmpty()) {
taskJson = JSONObject(result)
@ -326,23 +315,6 @@ object TaskUtils {
return false
}
val paramString: String
get() = paramsJson.toString()
public fun notcl(context: Context) {
val url = "http://127.0.0.1:8090/ctl/notcl"
try {
val ret: String = postData("".toByteArray(charset("utf-8")), url) ?: ""
Log.i("TaskUtils", "notcl ret : $ret")
} catch (e: Exception) {
e.printStackTrace()
}
}
fun openRecordApp(context: Context) {
if (scriptOpenApp == 0) {
recordPackageName?.let {