You've already forked TrickyStore
mirror of
https://github.com/5ec1cff/TrickyStore.git
synced 2025-09-06 06:37:07 +00:00
investigate
This commit is contained in:
163
module/src/main/cpp/binder/include/binder/IServiceManager.h
Normal file
163
module/src/main/cpp/binder/include/binder/IServiceManager.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2005 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <binder/Common.h>
|
||||
#include <binder/IInterface.h>
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/String16.h>
|
||||
#include <optional>
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Service manager for C++ services.
|
||||
*
|
||||
* IInterface is only for legacy ABI compatibility
|
||||
*/
|
||||
class LIBBINDER_EXPORTED IServiceManager : public IInterface {
|
||||
public:
|
||||
// for ABI compatibility
|
||||
virtual const String16 &getInterfaceDescriptor() const;
|
||||
|
||||
IServiceManager();
|
||||
|
||||
virtual ~IServiceManager();
|
||||
|
||||
/**
|
||||
* Must match values in IServiceManager.aidl
|
||||
*/
|
||||
/* Allows services to dump sections according to priorities. */
|
||||
static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
|
||||
static const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
|
||||
static const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
|
||||
/**
|
||||
* Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
|
||||
* same priority as NORMAL priority but the services are not called with dump priority
|
||||
* arguments.
|
||||
*/
|
||||
static const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
|
||||
static const int DUMP_FLAG_PRIORITY_ALL = DUMP_FLAG_PRIORITY_CRITICAL |
|
||||
DUMP_FLAG_PRIORITY_HIGH |
|
||||
DUMP_FLAG_PRIORITY_NORMAL |
|
||||
DUMP_FLAG_PRIORITY_DEFAULT;
|
||||
static const int DUMP_FLAG_PROTO = 1 << 4;
|
||||
|
||||
/**
|
||||
* Retrieve an existing service, blocking for a few seconds if it doesn't yet exist. This
|
||||
* does polling. A more efficient way to make sure you unblock as soon as the service is
|
||||
* available is to use waitForService or to use service notifications.
|
||||
*
|
||||
* Warning: when using this API, typically, you should call it in a loop. It's dangerous to
|
||||
* assume that nullptr could mean that the service is not available. The service could just
|
||||
* be starting. Generally, whether a service exists, this information should be declared
|
||||
* externally (for instance, an Android feature might imply the existence of a service,
|
||||
* a system property, or in the case of services in the VINTF manifest, it can be checked
|
||||
* with isDeclared).
|
||||
*/
|
||||
[[deprecated("this polls for 5s, prefer waitForService or checkService")]]
|
||||
virtual sp<IBinder> getService(const String16 &name) const = 0;
|
||||
|
||||
/**
|
||||
* Retrieve an existing service, non-blocking.
|
||||
*/
|
||||
virtual sp<IBinder> checkService(const String16 &name) const = 0;
|
||||
|
||||
/**
|
||||
* Register a service.
|
||||
*/
|
||||
// NOLINTNEXTLINE(google-default-arguments)
|
||||
virtual status_t addService(const String16 &name, const sp<IBinder> &service,
|
||||
bool allowIsolated = false,
|
||||
int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
|
||||
|
||||
/**
|
||||
* Return list of all existing services.
|
||||
*/
|
||||
// NOLINTNEXTLINE(google-default-arguments)
|
||||
virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
|
||||
|
||||
/**
|
||||
* Efficiently wait for a service.
|
||||
*
|
||||
* Returns nullptr only for permission problem or fatal error.
|
||||
*/
|
||||
virtual sp<IBinder> waitForService(const String16 &name) = 0;
|
||||
|
||||
/**
|
||||
* Check if a service is declared (e.g. VINTF manifest).
|
||||
*
|
||||
* If this returns true, waitForService should always be able to return the
|
||||
* service.
|
||||
*/
|
||||
virtual bool isDeclared(const String16 &name) = 0;
|
||||
|
||||
/**
|
||||
* Get all instances of a service as declared in the VINTF manifest
|
||||
*/
|
||||
virtual Vector<String16> getDeclaredInstances(const String16 &interface) = 0;
|
||||
|
||||
/**
|
||||
* If this instance is updatable via an APEX, returns the APEX with which
|
||||
* this can be updated.
|
||||
*/
|
||||
virtual std::optional<String16> updatableViaApex(const String16 &name) = 0;
|
||||
|
||||
/**
|
||||
* Returns all instances which are updatable via the APEX. Instance names are fully qualified
|
||||
* like `pack.age.IFoo/default`.
|
||||
*/
|
||||
virtual Vector<String16> getUpdatableNames(const String16 &apexName) = 0;
|
||||
|
||||
/**
|
||||
* If this instance has declared remote connection information, returns
|
||||
* the ConnectionInfo.
|
||||
*/
|
||||
struct ConnectionInfo {
|
||||
std::string ipAddress;
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
virtual std::optional<ConnectionInfo> getConnectionInfo(const String16 &name) = 0;
|
||||
|
||||
struct LocalRegistrationCallback : public virtual RefBase {
|
||||
virtual void
|
||||
onServiceRegistration(const String16 &instance, const sp<IBinder> &binder) = 0;
|
||||
|
||||
virtual ~LocalRegistrationCallback() {}
|
||||
};
|
||||
|
||||
virtual status_t registerForNotifications(const String16 &name,
|
||||
const sp<LocalRegistrationCallback> &callback) = 0;
|
||||
|
||||
virtual status_t unregisterForNotifications(const String16 &name,
|
||||
const sp<LocalRegistrationCallback> &callback) = 0;
|
||||
|
||||
struct ServiceDebugInfo {
|
||||
std::string name;
|
||||
int pid;
|
||||
};
|
||||
|
||||
virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0;
|
||||
};
|
||||
|
||||
LIBBINDER_EXPORTED sp<IServiceManager> defaultServiceManager();
|
||||
|
||||
LIBBINDER_EXPORTED void setDefaultServiceManager(const sp<IServiceManager> &sm);
|
||||
} // namespace android
|
||||
@@ -1,6 +1,40 @@
|
||||
#pragma once
|
||||
/*
|
||||
* Copyright (C) 2005 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_STRING16_H
|
||||
#define ANDROID_STRING16_H
|
||||
|
||||
// TODO
|
||||
namespace android {
|
||||
class String16 {};
|
||||
}
|
||||
class String16 {
|
||||
public:
|
||||
String16();
|
||||
|
||||
String16(const String16 &o);
|
||||
|
||||
String16(String16 &&o) noexcept;
|
||||
|
||||
explicit String16(const char *o);
|
||||
|
||||
~String16();
|
||||
|
||||
private:
|
||||
const char16_t *mString;
|
||||
};
|
||||
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_STRING16_H
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "binder/IPCThreadState.h"
|
||||
#include "binder/Parcel.h"
|
||||
#include "binder/IInterface.h"
|
||||
#include "binder/IServiceManager.h"
|
||||
|
||||
namespace android {
|
||||
// IBinder.h
|
||||
@@ -148,4 +149,17 @@ namespace android {
|
||||
|
||||
int32_t Parcel::readExceptionCode() const { return 0; }
|
||||
int Parcel::readFileDescriptor() const { return 0; }
|
||||
|
||||
// IServiceManager.h
|
||||
const String16 &IServiceManager::getInterfaceDescriptor() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
IServiceManager::IServiceManager() {}
|
||||
|
||||
IServiceManager::~IServiceManager() {}
|
||||
|
||||
sp<IServiceManager> defaultServiceManager() { return nullptr; }
|
||||
|
||||
void setDefaultServiceManager(const sp<IServiceManager> &sm) {}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "utils/StrongPointer.h"
|
||||
#include "utils/RefBase.h"
|
||||
#include "utils/String16.h"
|
||||
|
||||
namespace android {
|
||||
void RefBase::incStrong(const void *id) const {
|
||||
@@ -49,4 +50,14 @@ namespace android {
|
||||
bool RefBase::weakref_type::attemptIncWeak(const void* id) { return false; }
|
||||
|
||||
void sp_report_race() {}
|
||||
|
||||
String16::String16() {}
|
||||
|
||||
String16::String16(const String16 &o) {}
|
||||
|
||||
String16::String16(String16 &&o) noexcept {}
|
||||
|
||||
String16::String16(const char *o) {}
|
||||
|
||||
String16::~String16() {}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <binder/Binder.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <binder/Common.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
|
||||
#include <utility>
|
||||
#include <map>
|
||||
@@ -63,7 +64,7 @@ CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
LOGD("transact: binder=%p code=%d", thiz, code);
|
||||
if (IPCThreadState::self()->getCallingUid() == 0 && reply != nullptr &&
|
||||
thiz != gBinderInterceptor) [[unlikely]] {
|
||||
if (code == 0xdeadbeef) {
|
||||
if (code == 0xadbeef) {
|
||||
LOGD("request binder interceptor");
|
||||
reply->writeStrongBinder(gBinderInterceptor);
|
||||
return OK;
|
||||
@@ -268,6 +269,38 @@ bool hookBinder() {
|
||||
}
|
||||
LOGI("hook success!");
|
||||
gBinderInterceptor = sp<BinderInterceptor>::make();
|
||||
auto transactSym = handler.get_symbol("_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j");
|
||||
auto &img = handler.img;
|
||||
auto [vtSym, vtSize] = img.getSymInfo("_ZTVN7android7BBinderE");
|
||||
auto sm = defaultServiceManager();
|
||||
if (sm == nullptr) {
|
||||
LOGE("service manager is null!");
|
||||
return false;
|
||||
} else {
|
||||
int transactPos = -1;
|
||||
auto svc = sm->checkService(String16("android.system.keystore2.IKeystoreService/default"));
|
||||
if (svc != nullptr) {
|
||||
for (int i = 0; i < vtSize / sizeof(uintptr_t); i++) {
|
||||
auto val = *((uintptr_t *) vtSym + i);
|
||||
auto name = img.findSymbolNameForAddr(val);
|
||||
LOGI("vtable %i: %p %s", i, val, name.c_str());
|
||||
if (val == (uintptr_t) transactSym) {
|
||||
transactPos = i - 3;
|
||||
LOGI("transact pos %d", transactPos);
|
||||
}
|
||||
}
|
||||
if (transactPos >= 0) {
|
||||
auto svcTransactAddr = *(*reinterpret_cast<void ***>(svc.get()) + transactPos);
|
||||
LOGI("transact of svc %p: %p", svc.get(), svcTransactAddr);
|
||||
} else {
|
||||
LOGE("transactPos not found!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOGE("IKeystoreService not found!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,12 +88,18 @@ object KeystoreInterceptor : BinderInterceptor() {
|
||||
return Skip
|
||||
}
|
||||
|
||||
private var tried = false
|
||||
|
||||
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
|
||||
if (tried) {
|
||||
Logger.e("inject tried but still has no backdoor, exit")
|
||||
exitProcess(1)
|
||||
}
|
||||
Logger.i("trying to inject keystore ...")
|
||||
val p = Runtime.getRuntime().exec(
|
||||
arrayOf(
|
||||
@@ -108,6 +114,7 @@ object KeystoreInterceptor : BinderInterceptor() {
|
||||
Logger.e("failed to inject! daemon exit")
|
||||
exitProcess(1)
|
||||
}
|
||||
tried = true
|
||||
return false
|
||||
}
|
||||
val ks = IKeystoreService.Stub.asInterface(b)
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.github.a13e300.tricky_store.binder
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.os.Parcel
|
||||
import io.github.a13e300.tricky_store.Logger
|
||||
|
||||
open class BinderInterceptor : Binder() {
|
||||
sealed class Result
|
||||
@@ -16,9 +17,14 @@ open class BinderInterceptor : Binder() {
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
try {
|
||||
b.transact(0xdeadbeef.toInt(), data, reply, 0)
|
||||
if (!b.transact(0xadbeef, data, reply, 0)) {
|
||||
Logger.e("remote return false!")
|
||||
return null
|
||||
}
|
||||
Logger.d("remote return true!")
|
||||
return reply.readStrongBinder()
|
||||
} catch (ignored: Throwable) {
|
||||
} catch (t: Throwable) {
|
||||
Logger.e("failed to read binder", t)
|
||||
return null
|
||||
} finally {
|
||||
data.recycle()
|
||||
|
||||
Reference in New Issue
Block a user