[Main] Implement downloading bundle using ktor

This commit is contained in:
Beef 2023-05-08 23:42:02 +01:00
parent 5ca2008f7c
commit 123b0c1af9
7 changed files with 59 additions and 7 deletions

View file

@ -12,6 +12,6 @@
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-05-05T19:41:23.828568900Z" />
<timeTargetWasSelectedWithDropDown value="2023-05-08T22:05:30.827281100Z" />
</component>
</project>

4
.idea/gradle.xml generated
View file

@ -4,8 +4,10 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

View file

@ -21,5 +21,10 @@
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

2
.idea/misc.xml generated
View file

@ -1,6 +1,6 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -38,4 +38,6 @@ android {
dependencies {
compileOnly("de.robv.android.xposed:api:82")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
implementation("io.ktor:ktor-client-core:2.3.0")
implementation("io.ktor:ktor-client-cio:2.3.0")
}

View file

@ -1,5 +1,11 @@
package dev.beefers.vendetta.xposed
// Java
import java.io.File
// Kotlin
import kotlinx.coroutines.runBlocking
// Android
import android.content.res.AssetManager
import android.content.res.XModuleResources
@ -12,6 +18,19 @@ import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.callbacks.XC_LoadPackage
// Ktor
import io.ktor.client.*
import io.ktor.client.call.body
import io.ktor.client.engine.cio.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.client.plugins.*
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.http.isSuccess
import io.ktor.utils.io.reader
import java.lang.Exception
class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
private lateinit var resources: XModuleResources
@ -28,16 +47,31 @@ class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
val loadScriptFromAssets = catalystInstance.getDeclaredMethod("jniLoadScriptFromAssets", AssetManager::class.java, String::class.java, Boolean::class.javaPrimitiveType)
val loadScriptFromFile = catalystInstance.getDeclaredMethod("jniLoadScriptFromFile", String::class.java, String::class.java, Boolean::class.javaPrimitiveType)
// TODO: bundle (down)loading with etag
// val cache = File(appInfo.dataDir, "cache").also { it.mkdirs() }
// val bundle = File(cache, "vendetta.js")
val cache = File(appInfo.dataDir, "cache").also { it.mkdirs() }
val bundle = File(cache, "vendetta.js")
val etag = File(cache, "vendetta_etag.txt")
// TODO: loader config
// TODO: make fast.
val hook = object : XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam) {
override fun beforeHookedMethod(param: MethodHookParam): Unit = runBlocking {
Log.i("Vendetta", "beforeHookedMethod called")
try {
val client = HttpClient(CIO) { install(HttpTimeout) { requestTimeoutMillis = 3000 } }
val response: HttpResponse = client.get("https://raw.githubusercontent.com/vendetta-mod/builds/master/vendetta.js") {
headers { if (etag.exists() && bundle.exists()) append(HttpHeaders.IfNoneMatch, etag.readText()) }
}
if (response.status.isSuccess()) {
bundle.writeText(response.bodyAsText())
if (response.headers.contains("Etag")) etag.writeText(response.headers["Etag"] as String)
}
} catch (e: Exception) {
Log.e("Vendetta", "Failed to download Vendetta")
}
Log.i("Vendetta", "Exfiltrating Metro modules")
XposedBridge.invokeOriginalMethod(loadScriptFromAssets,param.thisObject, arrayOf(resources.assets, "assets://js/modules.js", true))
Log.i("Vendetta", "Executing identity snippet")
@ -46,6 +80,11 @@ class Main : IXposedHookZygoteInit, IXposedHookLoadPackage {
override fun afterHookedMethod(param: MethodHookParam) {
Log.i("Vendetta", "afterHookedMethod called")
try {
Log.i("Vendetta", "Executing Vendetta")
XposedBridge.invokeOriginalMethod(loadScriptFromFile, param.thisObject, arrayOf(bundle.absolutePath, bundle.absolutePath, param.args[2]))
} catch(_: Exception) {}
}
}

View file

@ -2,6 +2,8 @@
buildscript {
repositories {
google()
mavenCentral()
// We need jcenter for the Xposed API...
jcenter()
}
dependencies {
@ -16,6 +18,8 @@ buildscript {
allprojects {
repositories {
google()
mavenCentral()
// See comment in buildscript repos
jcenter()
}
}