You've already forked TrickyStore
mirror of
https://github.com/5ec1cff/TrickyStore.git
synced 2025-09-06 06:37:07 +00:00
Refactor
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package io.github.a13e300.tricky_store
|
||||
|
||||
import android.os.FileObserver
|
||||
import io.github.a13e300.tricky_store.keystore.CertHack
|
||||
import java.io.File
|
||||
|
||||
object Config {
|
||||
val targetPackages = mutableSetOf<String>()
|
||||
private val DEFAULT_TARGET_PACKAGES = listOf(
|
||||
"com.google.android.gms",
|
||||
"icu.nullptr.nativetest",
|
||||
"io.github.vvb2060.mahoshojo",
|
||||
"io.github.vvb2060.keyattestation"
|
||||
)
|
||||
|
||||
private fun updateTargetPackages(f: File?) = runCatching {
|
||||
targetPackages.clear()
|
||||
f?.readLines()?.mapNotNullTo(targetPackages) {
|
||||
if (it.isNotBlank() && !it.startsWith("#")) it else null
|
||||
}
|
||||
Logger.i("update target packages: $targetPackages")
|
||||
}.onFailure {
|
||||
Logger.e("failed to update target files", it)
|
||||
}
|
||||
|
||||
private fun updateKeyBox(f: File?) = runCatching {
|
||||
CertHack.readFromXml(f?.readText())
|
||||
}.onFailure {
|
||||
Logger.e("failed to update keybox", it)
|
||||
}
|
||||
|
||||
private const val CONFIG_PATH = "/data/adb/tricky_store"
|
||||
private const val TARGET_FILE = "target.txt"
|
||||
private const val KEYBOX_FILE = "keybox.xml"
|
||||
private val root = File(CONFIG_PATH)
|
||||
|
||||
object ConfigObserver : FileObserver(root, CLOSE_WRITE or DELETE) {
|
||||
override fun onEvent(event: Int, path: String?) {
|
||||
path ?: return
|
||||
val f = when (event) {
|
||||
CLOSE_WRITE -> File(root, path)
|
||||
DELETE -> null
|
||||
else -> return
|
||||
}
|
||||
when (path) {
|
||||
TARGET_FILE -> updateTargetPackages(f)
|
||||
KEYBOX_FILE -> updateKeyBox(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
root.mkdirs()
|
||||
val target = File(root, TARGET_FILE)
|
||||
if (!target.exists()) {
|
||||
target.createNewFile()
|
||||
target.writeText(DEFAULT_TARGET_PACKAGES.joinToString("\n"))
|
||||
}
|
||||
updateTargetPackages(target)
|
||||
val keybox = File(root, KEYBOX_FILE)
|
||||
if (!keybox.exists()) {
|
||||
Logger.e("keybox file not found, please put it to $keybox !")
|
||||
} else {
|
||||
updateKeyBox(keybox)
|
||||
}
|
||||
ConfigObserver.startWatching()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package io.github.a13e300.tricky_store
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.IPackageManager
|
||||
import android.os.IBinder
|
||||
import android.os.Parcel
|
||||
import android.os.ServiceManager
|
||||
import android.system.keystore2.IKeystoreService
|
||||
import android.system.keystore2.KeyEntryResponse
|
||||
import io.github.a13e300.tricky_store.binder.BinderInterceptor
|
||||
import io.github.a13e300.tricky_store.keystore.CertHack
|
||||
import io.github.a13e300.tricky_store.keystore.Utils
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@SuppressLint("BlockedPrivateApi")
|
||||
object KeystoreInterceptor : BinderInterceptor() {
|
||||
private val targetTransaction = IKeystoreService.Stub::class.java.getDeclaredField("TRANSACTION_getKeyEntry").apply { isAccessible = true }.getInt(null) // 2
|
||||
|
||||
private var iPm: IPackageManager? = null
|
||||
|
||||
private fun getPm(): IPackageManager? {
|
||||
if (iPm == null) {
|
||||
iPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"))
|
||||
}
|
||||
return iPm
|
||||
}
|
||||
|
||||
override fun onPreTransact(
|
||||
target: IBinder,
|
||||
code: Int,
|
||||
flags: Int,
|
||||
callingUid: Int,
|
||||
callingPid: Int,
|
||||
data: Parcel
|
||||
): Result {
|
||||
if (code == targetTransaction) {
|
||||
Logger.d("intercept pre $target uid=$callingUid pid=$callingPid dataSz=${data.dataSize()}")
|
||||
kotlin.runCatching {
|
||||
val ps = getPm()?.getPackagesForUid(callingUid)
|
||||
if (ps?.any { it in Config.targetPackages } == true) return Continue
|
||||
}.onFailure { Logger.e("failed to get packages", it) }
|
||||
}
|
||||
return Skip
|
||||
}
|
||||
|
||||
override fun onPostTransact(
|
||||
target: IBinder,
|
||||
code: Int,
|
||||
flags: Int,
|
||||
callingUid: Int,
|
||||
callingPid: Int,
|
||||
data: Parcel,
|
||||
reply: Parcel?,
|
||||
resultCode: Int
|
||||
): Result {
|
||||
if (code != targetTransaction || reply == null) return Skip
|
||||
val p = Parcel.obtain()
|
||||
Logger.d("intercept post $target uid=$callingUid pid=$callingPid dataSz=${data.dataSize()} replySz=${reply.dataSize()}")
|
||||
try {
|
||||
reply.readException()
|
||||
val response = reply.readTypedObject(KeyEntryResponse.CREATOR)
|
||||
val chain = Utils.getCertificateChain(response)
|
||||
if (chain != null) {
|
||||
val newChain = CertHack.engineGetCertificateChain(chain)
|
||||
Utils.putCertificateChain(response, newChain)
|
||||
p.writeNoException()
|
||||
p.writeTypedObject(response, 0)
|
||||
return OverrideReply(0, p)
|
||||
} else {
|
||||
p.recycle()
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
Logger.e("failed to hack certificate chain of uid=$callingUid pid=$callingPid!", t)
|
||||
p.recycle()
|
||||
}
|
||||
return Skip
|
||||
}
|
||||
|
||||
fun tryRunKeystoreInterceptor(): Boolean {
|
||||
Logger.i("trying to register keystore interceptor ...")
|
||||
val b = ServiceManager.getService("android.system.keystore2.IKeystoreService/default") ?: return false
|
||||
val bd = getBinderBackdoor(b)
|
||||
if (bd == null) {
|
||||
// no binder hook, try inject
|
||||
Logger.i("trying to inject keystore ...")
|
||||
val p = Runtime.getRuntime().exec(
|
||||
arrayOf(
|
||||
"/system/bin/sh",
|
||||
"-c",
|
||||
"exec ./inject `pidof keystore2` libtricky_store.so entry"
|
||||
)
|
||||
)
|
||||
// logD(p.inputStream.readBytes().decodeToString())
|
||||
// logD(p.errorStream.readBytes().decodeToString())
|
||||
if (p.waitFor() != 0) {
|
||||
Logger.e("failed to inject! daemon exit")
|
||||
exitProcess(1)
|
||||
}
|
||||
return false
|
||||
}
|
||||
registerBinderInterceptor(bd, b, this)
|
||||
b.linkToDeath({
|
||||
Logger.d("keystore exit, daemon restart")
|
||||
exitProcess(0)
|
||||
}, 0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,264 +1,15 @@
|
||||
package io.github.a13e300.tricky_store
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.IPackageManager
|
||||
import android.os.Binder
|
||||
import android.os.FileObserver
|
||||
import android.os.IBinder
|
||||
import android.os.Looper
|
||||
import android.os.Parcel
|
||||
import android.os.ServiceManager
|
||||
import android.system.keystore2.IKeystoreService
|
||||
import android.system.keystore2.KeyEntryResponse
|
||||
import android.util.Log
|
||||
import io.github.a13e300.tricky_store.fwpatch.Android
|
||||
import io.github.a13e300.tricky_store.fwpatch.Utils
|
||||
import java.io.File
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
open class BinderInterceptor : Binder() {
|
||||
sealed class Result
|
||||
data object Skip : Result()
|
||||
data object Continue : Result()
|
||||
data class OverrideData(val data: Parcel) : Result()
|
||||
data class OverrideReply(val code: Int = 0, val reply: Parcel) : Result()
|
||||
|
||||
open fun onPreTransact(target: IBinder, code: Int, flags: Int, callingUid: Int, callingPid: Int, data: Parcel): Result = Skip
|
||||
open fun onPostTransact(target: IBinder, code: Int, flags: Int, callingUid: Int, callingPid: Int, data: Parcel, reply: Parcel?, resultCode: Int): Result = Skip
|
||||
|
||||
override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
|
||||
val result = when (code) {
|
||||
1 -> { // PRE_TRANSACT
|
||||
val target = data.readStrongBinder()
|
||||
val theCode = data.readInt()
|
||||
val theFlags = data.readInt()
|
||||
val callingUid = data.readInt()
|
||||
val callingPid = data.readInt()
|
||||
val sz = data.readLong()
|
||||
val theData = Parcel.obtain()
|
||||
try {
|
||||
theData.appendFrom(data, data.dataPosition(), sz.toInt())
|
||||
theData.setDataPosition(0)
|
||||
onPreTransact(target, theCode, theFlags, callingUid, callingPid, theData)
|
||||
} finally {
|
||||
theData.recycle()
|
||||
}
|
||||
}
|
||||
2 -> { // POST_TRANSACT
|
||||
val target = data.readStrongBinder()
|
||||
val theCode = data.readInt()
|
||||
val theFlags = data.readInt()
|
||||
val callingUid = data.readInt()
|
||||
val callingPid = data.readInt()
|
||||
val resultCode = data.readInt()
|
||||
val theData = Parcel.obtain()
|
||||
val theReply = Parcel.obtain()
|
||||
try {
|
||||
val sz = data.readLong().toInt()
|
||||
theData.appendFrom(data, data.dataPosition(), sz)
|
||||
theData.setDataPosition(0)
|
||||
data.setDataPosition(data.dataPosition() + sz)
|
||||
val sz2 = data.readLong().toInt()
|
||||
if (sz2 != 0) {
|
||||
theReply.appendFrom(data, data.dataPosition(), sz2)
|
||||
theReply.setDataPosition(0)
|
||||
}
|
||||
onPostTransact(target, theCode, theFlags, callingUid, callingPid, theData, if (sz2 == 0) null else theReply, resultCode)
|
||||
} finally {
|
||||
theData.recycle()
|
||||
theReply.recycle()
|
||||
}
|
||||
}
|
||||
else -> return super.onTransact(code, data, reply, flags)
|
||||
}
|
||||
when (result) {
|
||||
Skip -> reply!!.writeInt(1)
|
||||
Continue -> reply!!.writeInt(2)
|
||||
is OverrideReply -> {
|
||||
reply!!.writeInt(3)
|
||||
reply.writeInt(result.code)
|
||||
reply.writeLong(result.reply.dataSize().toLong())
|
||||
println("override reply code=${result.code} size=${result.reply.dataSize()}")
|
||||
reply.appendFrom(result.reply, 0, result.reply.dataSize())
|
||||
result.reply.recycle()
|
||||
}
|
||||
is OverrideData -> {
|
||||
reply!!.writeInt(4)
|
||||
reply.writeLong(result.data.dataSize().toLong())
|
||||
reply.appendFrom(result.data, 0, result.data.dataSize())
|
||||
result.data.recycle()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
fun getBinderBackdoor(b: IBinder): IBinder? {
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
try {
|
||||
b.transact(0xdeadbeef.toInt(), data, reply, 0)
|
||||
return reply.readStrongBinder()
|
||||
} catch (ignored: Throwable) {
|
||||
return null
|
||||
} finally {
|
||||
data.recycle()
|
||||
reply.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
fun registerBinderInterceptor(backdoor: IBinder, target: IBinder, interceptor: BinderInterceptor) {
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
data.writeStrongBinder(target)
|
||||
data.writeStrongBinder(interceptor)
|
||||
backdoor.transact(1, data, reply, 0)
|
||||
}
|
||||
|
||||
val targetPackages = mutableSetOf<String>()
|
||||
val DEFAULT_TARGET_PACKAGES = listOf("com.google.android.gms", "icu.nullptr.nativetest", "io.github.vvb2060.mahoshojo", "io.github.vvb2060.keyattestation")
|
||||
|
||||
var iPm: IPackageManager? = null
|
||||
|
||||
fun getPm(): IPackageManager? {
|
||||
if (iPm == null) {
|
||||
iPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"))
|
||||
}
|
||||
return iPm
|
||||
}
|
||||
|
||||
fun updateTargetPackages(f: File) = runCatching {
|
||||
targetPackages.clear()
|
||||
f.readLines().mapNotNullTo(targetPackages) {
|
||||
if (it.isNotBlank() && !it.startsWith("#")) it else null
|
||||
}
|
||||
Logger.d("update target packages: $targetPackages")
|
||||
}.onFailure {
|
||||
Logger.e("failed to update target files", it)
|
||||
}
|
||||
|
||||
fun updateKeyBox(f: File) = runCatching {
|
||||
Android.readFromXml(f.readText())
|
||||
}.onFailure {
|
||||
Logger.e("failed to update keybox", it)
|
||||
}
|
||||
|
||||
const val CONFIG_PATH = "/data/adb/tricky_store"
|
||||
const val TARGET_FILE = "target.txt"
|
||||
const val KEYBOX_FILE = "keybox.xml"
|
||||
|
||||
class ConfigObserver : FileObserver(CONFIG_PATH, CLOSE_WRITE) {
|
||||
private val root = File(CONFIG_PATH)
|
||||
override fun onEvent(event: Int, path: String?) {
|
||||
path ?: return
|
||||
if (event == CLOSE_WRITE) {
|
||||
val f = File(root, path)
|
||||
when (f.name) {
|
||||
TARGET_FILE -> updateTargetPackages(f)
|
||||
KEYBOX_FILE -> updateKeyBox(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("BlockedPrivateApi")
|
||||
fun tryRunKeystoreInterceptor(): Boolean {
|
||||
val b = ServiceManager.getService("android.system.keystore2.IKeystoreService/default") ?: return false
|
||||
b.linkToDeath({
|
||||
Logger.d("keystore exit, daemon exit")
|
||||
exitProcess(0)
|
||||
}, 0)
|
||||
val bd = getBinderBackdoor(b) ?: return true
|
||||
val targetTransaction = IKeystoreService.Stub::class.java.getDeclaredField("TRANSACTION_getKeyEntry").apply { isAccessible = true }.getInt(null) // 2
|
||||
val interceptor = object : BinderInterceptor() {
|
||||
override fun onPreTransact(
|
||||
target: IBinder,
|
||||
code: Int,
|
||||
flags: Int,
|
||||
callingUid: Int,
|
||||
callingPid: Int,
|
||||
data: Parcel
|
||||
): Result {
|
||||
if (code == targetTransaction) {
|
||||
Logger.d("intercept pre $target uid=$callingUid pid=$callingPid dataSz=${data.dataSize()}")
|
||||
kotlin.runCatching {
|
||||
val ps = getPm()?.getPackagesForUid(callingUid)
|
||||
if (ps?.any { it in targetPackages } == true) return Continue
|
||||
}.onFailure { Logger.e("failed to get packages", it) }
|
||||
}
|
||||
return Skip
|
||||
}
|
||||
|
||||
override fun onPostTransact(
|
||||
target: IBinder,
|
||||
code: Int,
|
||||
flags: Int,
|
||||
callingUid: Int,
|
||||
callingPid: Int,
|
||||
data: Parcel,
|
||||
reply: Parcel?,
|
||||
resultCode: Int
|
||||
): Result {
|
||||
if (code != targetTransaction || reply == null) return Skip
|
||||
val p = Parcel.obtain()
|
||||
Logger.d("intercept post $target uid=$callingUid pid=$callingPid dataSz=${data.dataSize()} replySz=${reply.dataSize()}")
|
||||
try {
|
||||
reply.readException()
|
||||
val response = reply.readTypedObject(KeyEntryResponse.CREATOR)
|
||||
val chain = Utils.getCertificateChain(response)
|
||||
val newChain = Android.engineGetCertificateChain(chain)
|
||||
Utils.putCertificateChain(response, newChain)
|
||||
p.writeNoException()
|
||||
p.writeTypedObject(response, 0)
|
||||
return OverrideReply(0, p)
|
||||
} catch (t: Throwable) {
|
||||
Logger.e("failed to hack certificate chain!", t)
|
||||
p.recycle()
|
||||
}
|
||||
return Skip
|
||||
}
|
||||
}
|
||||
val path = File(CONFIG_PATH)
|
||||
path.mkdirs()
|
||||
val target = File(path, TARGET_FILE)
|
||||
if (!target.exists()) {
|
||||
target.createNewFile()
|
||||
target.writeText(DEFAULT_TARGET_PACKAGES.joinToString("\n"))
|
||||
}
|
||||
updateTargetPackages(target)
|
||||
val keybox = File(path, KEYBOX_FILE)
|
||||
if (!keybox.exists()) {
|
||||
Logger.e("keybox file not found, please put it to $keybox !")
|
||||
} else {
|
||||
updateKeyBox(keybox)
|
||||
}
|
||||
val monitor = ConfigObserver()
|
||||
monitor.startWatching()
|
||||
registerBinderInterceptor(bd, b, interceptor)
|
||||
while (true) {
|
||||
Thread.sleep(1000000)
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Logger.i("Welcome to TrickyStore!")
|
||||
while (true) {
|
||||
Thread.sleep(1000)
|
||||
// true -> can inject, false -> service not found, loop -> running
|
||||
if (!tryRunKeystoreInterceptor()) continue
|
||||
// no binder hook, try inject
|
||||
val p = Runtime.getRuntime().exec(
|
||||
arrayOf(
|
||||
"/system/bin/sh",
|
||||
"-c",
|
||||
"exec ./inject `pidof keystore2` libtricky_store.so entry"
|
||||
)
|
||||
)
|
||||
// logD(p.inputStream.readBytes().decodeToString())
|
||||
// logD(p.errorStream.readBytes().decodeToString())
|
||||
if (p.waitFor() != 0) {
|
||||
Logger.e("failed to inject! daemon exit")
|
||||
exitProcess(1)
|
||||
if (!KeystoreInterceptor.tryRunKeystoreInterceptor()) {
|
||||
Thread.sleep(1000)
|
||||
continue
|
||||
}
|
||||
Config.initialize()
|
||||
while (true) {
|
||||
Thread.sleep(1000000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package io.github.a13e300.tricky_store.binder
|
||||
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.os.Parcel
|
||||
|
||||
|
||||
open class BinderInterceptor : Binder() {
|
||||
sealed class Result
|
||||
data object Skip : Result()
|
||||
data object Continue : Result()
|
||||
data class OverrideData(val data: Parcel) : Result()
|
||||
data class OverrideReply(val code: Int = 0, val reply: Parcel) : Result()
|
||||
|
||||
companion object {
|
||||
fun getBinderBackdoor(b: IBinder): IBinder? {
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
try {
|
||||
b.transact(0xdeadbeef.toInt(), data, reply, 0)
|
||||
return reply.readStrongBinder()
|
||||
} catch (ignored: Throwable) {
|
||||
return null
|
||||
} finally {
|
||||
data.recycle()
|
||||
reply.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
fun registerBinderInterceptor(backdoor: IBinder, target: IBinder, interceptor: BinderInterceptor) {
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
data.writeStrongBinder(target)
|
||||
data.writeStrongBinder(interceptor)
|
||||
backdoor.transact(1, data, reply, 0)
|
||||
}
|
||||
}
|
||||
|
||||
open fun onPreTransact(target: IBinder, code: Int, flags: Int, callingUid: Int, callingPid: Int, data: Parcel): Result = Skip
|
||||
open fun onPostTransact(target: IBinder, code: Int, flags: Int, callingUid: Int, callingPid: Int, data: Parcel, reply: Parcel?, resultCode: Int): Result = Skip
|
||||
|
||||
override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
|
||||
val result = when (code) {
|
||||
1 -> { // PRE_TRANSACT
|
||||
val target = data.readStrongBinder()
|
||||
val theCode = data.readInt()
|
||||
val theFlags = data.readInt()
|
||||
val callingUid = data.readInt()
|
||||
val callingPid = data.readInt()
|
||||
val sz = data.readLong()
|
||||
val theData = Parcel.obtain()
|
||||
try {
|
||||
theData.appendFrom(data, data.dataPosition(), sz.toInt())
|
||||
theData.setDataPosition(0)
|
||||
onPreTransact(target, theCode, theFlags, callingUid, callingPid, theData)
|
||||
} finally {
|
||||
theData.recycle()
|
||||
}
|
||||
}
|
||||
2 -> { // POST_TRANSACT
|
||||
val target = data.readStrongBinder()
|
||||
val theCode = data.readInt()
|
||||
val theFlags = data.readInt()
|
||||
val callingUid = data.readInt()
|
||||
val callingPid = data.readInt()
|
||||
val resultCode = data.readInt()
|
||||
val theData = Parcel.obtain()
|
||||
val theReply = Parcel.obtain()
|
||||
try {
|
||||
val sz = data.readLong().toInt()
|
||||
theData.appendFrom(data, data.dataPosition(), sz)
|
||||
theData.setDataPosition(0)
|
||||
data.setDataPosition(data.dataPosition() + sz)
|
||||
val sz2 = data.readLong().toInt()
|
||||
if (sz2 != 0) {
|
||||
theReply.appendFrom(data, data.dataPosition(), sz2)
|
||||
theReply.setDataPosition(0)
|
||||
}
|
||||
onPostTransact(target, theCode, theFlags, callingUid, callingPid, theData, if (sz2 == 0) null else theReply, resultCode)
|
||||
} finally {
|
||||
theData.recycle()
|
||||
theReply.recycle()
|
||||
}
|
||||
}
|
||||
else -> return super.onTransact(code, data, reply, flags)
|
||||
}
|
||||
when (result) {
|
||||
Skip -> reply!!.writeInt(1)
|
||||
Continue -> reply!!.writeInt(2)
|
||||
is OverrideReply -> {
|
||||
reply!!.writeInt(3)
|
||||
reply.writeInt(result.code)
|
||||
reply.writeLong(result.reply.dataSize().toLong())
|
||||
println("override reply code=${result.code} size=${result.reply.dataSize()}")
|
||||
reply.appendFrom(result.reply, 0, result.reply.dataSize())
|
||||
result.reply.recycle()
|
||||
}
|
||||
is OverrideData -> {
|
||||
reply!!.writeInt(4)
|
||||
reply.writeLong(result.data.dataSize().toLong())
|
||||
reply.appendFrom(result.data, 0, result.data.dataSize())
|
||||
result.data.recycle()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package io.github.a13e300.tricky_store.fwpatch;
|
||||
package io.github.a13e300.tricky_store.keystore;
|
||||
|
||||
import android.os.Build;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
@@ -28,11 +26,9 @@ import org.bouncycastle.util.io.pem.PemReader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -42,8 +38,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import io.github.a13e300.tricky_store.Logger;
|
||||
|
||||
public final class Android {
|
||||
private static final String TAG = "chiteroman";
|
||||
public final class CertHack {
|
||||
private static final ASN1ObjectIdentifier OID = new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.17");
|
||||
|
||||
record KeyBox(PEMKeyPair privateKey, List<Certificate> certificates) {}
|
||||
@@ -55,13 +50,17 @@ public final class Android {
|
||||
try {
|
||||
certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, t.toString());
|
||||
Logger.e("", t);
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public static void readFromXml(String data) {
|
||||
keyboxes.clear();
|
||||
if (data == null) {
|
||||
Logger.i("clear all keyboxes");
|
||||
return;
|
||||
}
|
||||
XMLParser xmlParser = new XMLParser(data);
|
||||
|
||||
try {
|
||||
@@ -90,7 +89,7 @@ public final class Android {
|
||||
}
|
||||
keyboxes.put(algo, new KeyBox(parseKeyPair(privateKey), certificateChain));
|
||||
}
|
||||
Logger.d("update " + numberOfKeyboxes + " keyboxes");
|
||||
Logger.i("update " + numberOfKeyboxes + " keyboxes");
|
||||
} catch (Throwable t) {
|
||||
Logger.e("Error loading xml file: " + t);
|
||||
}
|
||||
@@ -183,7 +182,7 @@ public final class Android {
|
||||
return certificates.toArray(new Certificate[0]);
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, t.toString());
|
||||
Logger.e("", t);
|
||||
}
|
||||
return caList;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.github.a13e300.tricky_store.fwpatch;
|
||||
package io.github.a13e300.tricky_store.keystore;
|
||||
|
||||
import android.system.keystore2.KeyEntryResponse;
|
||||
import android.util.Log;
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.github.a13e300.tricky_store.fwpatch;
|
||||
package io.github.a13e300.tricky_store.keystore;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
Reference in New Issue
Block a user