You've already forked TrickyStore
mirror of
https://github.com/5ec1cff/TrickyStore.git
synced 2025-09-06 06:37:07 +00:00
new way to hook
This commit is contained in:
239
module/src/main/cpp/binder/include/kernel/binder.h
Normal file
239
module/src/main/cpp/binder/include/kernel/binder.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* This file is auto-generated. Modifications will be lost.
|
||||
*
|
||||
* See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
|
||||
* for more information.
|
||||
*/
|
||||
#ifndef _UAPI_LINUX_BINDER_H
|
||||
#define _UAPI_LINUX_BINDER_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define B_PACK_CHARS(c1, c2, c3, c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4))
|
||||
#define B_TYPE_LARGE 0x85
|
||||
enum {
|
||||
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
|
||||
BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
|
||||
BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
|
||||
};
|
||||
enum flat_binder_object_shifts {
|
||||
FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT = 9,
|
||||
};
|
||||
enum flat_binder_object_flags {
|
||||
FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
|
||||
FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
|
||||
FLAT_BINDER_FLAG_SCHED_POLICY_MASK = 3U << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT,
|
||||
FLAT_BINDER_FLAG_INHERIT_RT = 0x800,
|
||||
FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
|
||||
};
|
||||
#ifdef BINDER_IPC_32BIT
|
||||
typedef __u32 binder_size_t;
|
||||
typedef __u32 binder_uintptr_t;
|
||||
#else
|
||||
typedef __u64 binder_size_t;
|
||||
typedef __u64 binder_uintptr_t;
|
||||
#endif
|
||||
struct binder_object_header {
|
||||
__u32 type;
|
||||
};
|
||||
struct flat_binder_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 flags;
|
||||
union {
|
||||
binder_uintptr_t binder;
|
||||
__u32 handle;
|
||||
};
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
struct binder_fd_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 pad_flags;
|
||||
union {
|
||||
binder_uintptr_t pad_binder;
|
||||
__u32 fd;
|
||||
};
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
struct binder_buffer_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 flags;
|
||||
binder_uintptr_t buffer;
|
||||
binder_size_t length;
|
||||
binder_size_t parent;
|
||||
binder_size_t parent_offset;
|
||||
};
|
||||
enum {
|
||||
BINDER_BUFFER_FLAG_HAS_PARENT = 0x01,
|
||||
};
|
||||
struct binder_fd_array_object {
|
||||
struct binder_object_header hdr;
|
||||
__u32 pad;
|
||||
binder_size_t num_fds;
|
||||
binder_size_t parent;
|
||||
binder_size_t parent_offset;
|
||||
};
|
||||
struct binder_write_read {
|
||||
binder_size_t write_size;
|
||||
binder_size_t write_consumed;
|
||||
binder_uintptr_t write_buffer;
|
||||
binder_size_t read_size;
|
||||
binder_size_t read_consumed;
|
||||
binder_uintptr_t read_buffer;
|
||||
};
|
||||
struct binder_version {
|
||||
__s32 protocol_version;
|
||||
};
|
||||
#ifdef BINDER_IPC_32BIT
|
||||
#define BINDER_CURRENT_PROTOCOL_VERSION 7
|
||||
#else
|
||||
#define BINDER_CURRENT_PROTOCOL_VERSION 8
|
||||
#endif
|
||||
struct binder_node_debug_info {
|
||||
binder_uintptr_t ptr;
|
||||
binder_uintptr_t cookie;
|
||||
__u32 has_strong_ref;
|
||||
__u32 has_weak_ref;
|
||||
};
|
||||
struct binder_node_info_for_ref {
|
||||
__u32 handle;
|
||||
__u32 strong_count;
|
||||
__u32 weak_count;
|
||||
__u32 reserved1;
|
||||
__u32 reserved2;
|
||||
__u32 reserved3;
|
||||
};
|
||||
struct binder_freeze_info {
|
||||
__u32 pid;
|
||||
__u32 enable;
|
||||
__u32 timeout_ms;
|
||||
};
|
||||
struct binder_frozen_status_info {
|
||||
__u32 pid;
|
||||
__u32 sync_recv;
|
||||
__u32 async_recv;
|
||||
};
|
||||
struct binder_extended_error {
|
||||
__u32 id;
|
||||
__u32 command;
|
||||
__s32 param;
|
||||
};
|
||||
enum {
|
||||
BINDER_WRITE_READ = _IOWR('b', 1, struct binder_write_read),
|
||||
BINDER_SET_IDLE_TIMEOUT = _IOW('b', 3, __s64),
|
||||
BINDER_SET_MAX_THREADS = _IOW('b', 5, __u32),
|
||||
BINDER_SET_IDLE_PRIORITY = _IOW('b', 6, __s32),
|
||||
BINDER_SET_CONTEXT_MGR = _IOW('b', 7, __s32),
|
||||
BINDER_THREAD_EXIT = _IOW('b', 8, __s32),
|
||||
BINDER_VERSION = _IOWR('b', 9, struct binder_version),
|
||||
BINDER_GET_NODE_DEBUG_INFO = _IOWR('b', 11, struct binder_node_debug_info),
|
||||
BINDER_GET_NODE_INFO_FOR_REF = _IOWR('b', 12, struct binder_node_info_for_ref),
|
||||
BINDER_SET_CONTEXT_MGR_EXT = _IOW('b', 13, struct flat_binder_object),
|
||||
BINDER_FREEZE = _IOW('b', 14, struct binder_freeze_info),
|
||||
BINDER_GET_FROZEN_INFO = _IOWR('b', 15, struct binder_frozen_status_info),
|
||||
BINDER_ENABLE_ONEWAY_SPAM_DETECTION = _IOW('b', 16, __u32),
|
||||
BINDER_GET_EXTENDED_ERROR = _IOWR('b', 17, struct binder_extended_error),
|
||||
};
|
||||
enum transaction_flags {
|
||||
TF_ONE_WAY = 0x01,
|
||||
TF_ROOT_OBJECT = 0x04,
|
||||
TF_STATUS_CODE = 0x08,
|
||||
TF_ACCEPT_FDS = 0x10,
|
||||
TF_CLEAR_BUF = 0x20,
|
||||
TF_UPDATE_TXN = 0x40,
|
||||
};
|
||||
struct binder_transaction_data {
|
||||
union {
|
||||
__u32 handle;
|
||||
binder_uintptr_t ptr;
|
||||
} target;
|
||||
binder_uintptr_t cookie;
|
||||
__u32 code;
|
||||
__u32 flags;
|
||||
__kernel_pid_t sender_pid;
|
||||
__kernel_uid32_t sender_euid;
|
||||
binder_size_t data_size;
|
||||
binder_size_t offsets_size;
|
||||
union {
|
||||
struct {
|
||||
binder_uintptr_t buffer;
|
||||
binder_uintptr_t offsets;
|
||||
} ptr;
|
||||
__u8 buf[8];
|
||||
} data;
|
||||
};
|
||||
struct binder_transaction_data_secctx {
|
||||
struct binder_transaction_data transaction_data;
|
||||
binder_uintptr_t secctx;
|
||||
};
|
||||
struct binder_transaction_data_sg {
|
||||
struct binder_transaction_data transaction_data;
|
||||
binder_size_t buffers_size;
|
||||
};
|
||||
struct binder_ptr_cookie {
|
||||
binder_uintptr_t ptr;
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
struct binder_handle_cookie {
|
||||
__u32 handle;
|
||||
binder_uintptr_t cookie;
|
||||
} __attribute__((__packed__));
|
||||
struct binder_pri_desc {
|
||||
__s32 priority;
|
||||
__u32 desc;
|
||||
};
|
||||
struct binder_pri_ptr_cookie {
|
||||
__s32 priority;
|
||||
binder_uintptr_t ptr;
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
enum binder_driver_return_protocol {
|
||||
BR_ERROR = _IOR('r', 0, __s32),
|
||||
BR_OK = _IO('r', 1),
|
||||
BR_TRANSACTION_SEC_CTX = _IOR('r', 2, struct binder_transaction_data_secctx),
|
||||
BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
|
||||
BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
|
||||
BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
|
||||
BR_DEAD_REPLY = _IO('r', 5),
|
||||
BR_TRANSACTION_COMPLETE = _IO('r', 6),
|
||||
BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
|
||||
BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
|
||||
BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
|
||||
BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
|
||||
BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
|
||||
BR_NOOP = _IO('r', 12),
|
||||
BR_SPAWN_LOOPER = _IO('r', 13),
|
||||
BR_FINISHED = _IO('r', 14),
|
||||
BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
|
||||
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
|
||||
BR_FAILED_REPLY = _IO('r', 17),
|
||||
BR_FROZEN_REPLY = _IO('r', 18),
|
||||
BR_ONEWAY_SPAM_SUSPECT = _IO('r', 19),
|
||||
BR_TRANSACTION_PENDING_FROZEN = _IO('r', 20),
|
||||
};
|
||||
enum binder_driver_command_protocol {
|
||||
BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
|
||||
BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
|
||||
BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
|
||||
BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
|
||||
BC_INCREFS = _IOW('c', 4, __u32),
|
||||
BC_ACQUIRE = _IOW('c', 5, __u32),
|
||||
BC_RELEASE = _IOW('c', 6, __u32),
|
||||
BC_DECREFS = _IOW('c', 7, __u32),
|
||||
BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
|
||||
BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
|
||||
BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
|
||||
BC_REGISTER_LOOPER = _IO('c', 11),
|
||||
BC_ENTER_LOOPER = _IO('c', 12),
|
||||
BC_EXIT_LOOPER = _IO('c', 13),
|
||||
BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie),
|
||||
BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie),
|
||||
BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
|
||||
BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
|
||||
BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
|
||||
};
|
||||
#endif
|
||||
@@ -6,11 +6,14 @@
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <binder/Common.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "kernel/binder.h"
|
||||
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "logging.hpp"
|
||||
#include "dobby.h"
|
||||
@@ -50,36 +53,140 @@ public:
|
||||
status_t onTransact(uint32_t code, const android::Parcel &data, android::Parcel *reply,
|
||||
uint32_t flags) override;
|
||||
|
||||
bool handleIntercept(BBinder *thiz, uint32_t code, const Parcel &data, Parcel *reply,
|
||||
bool handleIntercept(sp<BBinder> target, uint32_t code, const Parcel &data, Parcel *reply,
|
||||
uint32_t flags, status_t &result);
|
||||
|
||||
bool needIntercept(const wp<BBinder>& target);
|
||||
};
|
||||
|
||||
static sp<BinderInterceptor> gBinderInterceptor = nullptr;
|
||||
|
||||
CREATE_MEM_HOOK_STUB_ENTRY(
|
||||
"_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j",
|
||||
status_t, BBinder_Transact,
|
||||
(BBinder * thiz, uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags),
|
||||
{
|
||||
LOGD("transact: binder=%p code=%d", thiz, code);
|
||||
if (IPCThreadState::self()->getCallingUid() == 0 && reply != nullptr &&
|
||||
thiz != gBinderInterceptor) [[unlikely]] {
|
||||
if (code == 0xadbeef) {
|
||||
LOGD("request binder interceptor");
|
||||
reply->writeStrongBinder(gBinderInterceptor);
|
||||
return OK;
|
||||
struct thread_transaction_info {
|
||||
uint32_t code;
|
||||
wp<BBinder> target;
|
||||
};
|
||||
|
||||
thread_local std::queue<thread_transaction_info> ttis;
|
||||
|
||||
class BinderStub : public BBinder {
|
||||
status_t onTransact(uint32_t code, const android::Parcel &data, android::Parcel *reply, uint32_t flags) override {
|
||||
LOGD("BinderStub %d", code);
|
||||
if (!ttis.empty()) {
|
||||
auto tti = ttis.front();
|
||||
ttis.pop();
|
||||
if (tti.target == nullptr && tti.code == 0xdeadbeef && reply) {
|
||||
LOGD("backdoor requested!");
|
||||
reply->writeStrongBinder(gBinderInterceptor);
|
||||
return OK;
|
||||
} else if (tti.target != nullptr) {
|
||||
LOGD("intercepting");
|
||||
auto p = tti.target.promote();
|
||||
if (p) {
|
||||
LOGD("calling interceptor");
|
||||
status_t result;
|
||||
if (!gBinderInterceptor->handleIntercept(p, tti.code, data, reply, flags,
|
||||
result)) {
|
||||
LOGD("calling orig");
|
||||
result = p->transact(tti.code, data, reply, flags);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
LOGE("promote failed");
|
||||
}
|
||||
}
|
||||
status_t result;
|
||||
if (gBinderInterceptor->handleIntercept(thiz, code, data, reply,
|
||||
flags, result)) {
|
||||
LOGD("transact intercepted: binder=%p code=%d result=%d", thiz, code, result);
|
||||
return result;
|
||||
}
|
||||
return UNKNOWN_TRANSACTION;
|
||||
}
|
||||
};
|
||||
|
||||
static sp<BinderStub> gBinderStub = nullptr;
|
||||
|
||||
int (*old_ioctl)(int fd, int request, ...) = nullptr;
|
||||
int new_ioctl(int fd, int request, ...) {
|
||||
va_list list;
|
||||
va_start(list, request);
|
||||
auto arg = va_arg(list, void*);
|
||||
va_end(list);
|
||||
auto result = old_ioctl(fd, request, arg);
|
||||
// TODO: check fd
|
||||
if (result >= 0 && request == BINDER_WRITE_READ) {
|
||||
auto &bwr = *(struct binder_write_read*) arg;
|
||||
LOGD("read buffer %p size %zu consumed %zu", bwr.read_buffer, bwr.read_size,
|
||||
bwr.read_consumed);
|
||||
if (bwr.read_buffer != 0 && bwr.read_size != 0 && bwr.read_consumed > sizeof(int32_t)) {
|
||||
auto ptr = bwr.read_buffer;
|
||||
auto consumed = bwr.read_consumed;
|
||||
while (consumed > 0) {
|
||||
consumed -= sizeof(uint32_t);
|
||||
if (consumed < 0) {
|
||||
LOGE("consumed < 0");
|
||||
break;
|
||||
}
|
||||
auto cmd = *(uint32_t *) ptr;
|
||||
ptr += sizeof(uint32_t);
|
||||
auto sz = _IOC_SIZE(cmd);
|
||||
LOGD("ioctl cmd %d sz %d", cmd, sz);
|
||||
consumed -= sz;
|
||||
if (consumed < 0) {
|
||||
LOGE("consumed < 0");
|
||||
break;
|
||||
}
|
||||
if (cmd == BR_TRANSACTION_SEC_CTX || cmd == BR_TRANSACTION) {
|
||||
binder_transaction_data_secctx *tr_secctx = nullptr;
|
||||
binder_transaction_data *tr = nullptr;
|
||||
if (cmd == BR_TRANSACTION_SEC_CTX) {
|
||||
LOGD("cmd is BR_TRANSACTION_SEC_CTX");
|
||||
tr_secctx = (binder_transaction_data_secctx *) ptr;
|
||||
tr = &tr_secctx->transaction_data;
|
||||
} else {
|
||||
LOGD("cmd is BR_TRANSACTION");
|
||||
tr = (binder_transaction_data *) ptr;
|
||||
}
|
||||
|
||||
if (tr != nullptr) {
|
||||
auto wt = tr->target.ptr;
|
||||
if (wt != 0) {
|
||||
bool need_intercept = false;
|
||||
thread_transaction_info tti{};
|
||||
if (tr->code == 0xdeadbeef && tr->sender_euid == 0) {
|
||||
tti.code = 0xdeadbeef;
|
||||
tti.target = nullptr;
|
||||
need_intercept = true;
|
||||
} else if (reinterpret_cast<RefBase::weakref_type *>(wt)->attemptIncStrong(
|
||||
nullptr)) {
|
||||
auto b = (BBinder *) tr->cookie;
|
||||
auto wb = wp<BBinder>::fromExisting(b);
|
||||
if (gBinderInterceptor->needIntercept(wb)) {
|
||||
tti.code = tr->code;
|
||||
tti.target = wb;
|
||||
need_intercept = true;
|
||||
LOGD("intercept code=%d target=%p", tr->code, b);
|
||||
}
|
||||
b->decStrong(nullptr);
|
||||
}
|
||||
if (need_intercept) {
|
||||
LOGD("add intercept item!");
|
||||
tr->target.ptr = (uintptr_t) gBinderStub->getWeakRefs();
|
||||
tr->cookie = (uintptr_t) gBinderStub.get();
|
||||
tr->code = 0xdeadbeef;
|
||||
ttis.push(tti);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGE("no transaction data found!");
|
||||
}
|
||||
}
|
||||
ptr += sz;
|
||||
}
|
||||
result = backup(thiz, code, data, reply, flags);
|
||||
LOGD("transact: binder=%p code=%d result=%d", thiz, code, result);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BinderInterceptor::needIntercept(const wp<BBinder> &target) {
|
||||
ReadGuard g{lock};
|
||||
return items.find(target) != items.end();
|
||||
}
|
||||
|
||||
status_t
|
||||
BinderInterceptor::onTransact(uint32_t code, const android::Parcel &data, android::Parcel *reply,
|
||||
@@ -182,20 +289,21 @@ public:
|
||||
};
|
||||
|
||||
bool
|
||||
BinderInterceptor::handleIntercept(BBinder *thiz, uint32_t code, const Parcel &data, Parcel *reply,
|
||||
BinderInterceptor::handleIntercept(sp<BBinder> target, uint32_t code, const Parcel &data, Parcel *reply,
|
||||
uint32_t flags, status_t &result) {
|
||||
#define CHECK(expr) ({ auto __result = (expr); if (__result != OK) { LOGE(#expr " = %d", __result); return false; } })
|
||||
sp<IBinder> interceptor;
|
||||
{
|
||||
ReadGuard rg{lock};
|
||||
wp<IBinder> target = wp<IBinder>::fromExisting(thiz);
|
||||
auto it = items.find(target);
|
||||
if (it == items.end()) return false;
|
||||
if (it == items.end()) {
|
||||
LOGE("no intercept item found!");
|
||||
return false;
|
||||
}
|
||||
interceptor = it->second.interceptor;
|
||||
}
|
||||
LOGD("intercept on binder %p code %d flags %d (reply=%s)", thiz, code, flags,
|
||||
LOGD("intercept on binder %p code %d flags %d (reply=%s)", target.get(), code, flags,
|
||||
reply ? "true" : "false");
|
||||
sp<IBinder> target = sp<IBinder>::fromExisting(thiz);
|
||||
Parcel tmpData, tmpReply, realData;
|
||||
CHECK(tmpData.writeStrongBinder(target));
|
||||
CHECK(tmpData.writeUint32(code));
|
||||
@@ -223,7 +331,7 @@ BinderInterceptor::handleIntercept(BBinder *thiz, uint32_t code, const Parcel &d
|
||||
} else {
|
||||
CHECK(realData.appendFrom(&data, 0, data.dataSize()));
|
||||
}
|
||||
result = BBinder_Transact.backup(thiz, code, realData, reply, flags);
|
||||
result = target->transact(code, realData, reply, flags);
|
||||
|
||||
tmpData.freeData();
|
||||
tmpReply.freeData();
|
||||
@@ -258,49 +366,19 @@ BinderInterceptor::handleIntercept(BBinder *thiz, uint32_t code, const Parcel &d
|
||||
}
|
||||
|
||||
bool hookBinder() {
|
||||
HookHandler handler{ElfInfo::getElfInfoForName("libbinder.so")};
|
||||
if (!handler.isValid()) {
|
||||
ElfImg img{ElfInfo::getElfInfoForName("libc.so")};
|
||||
if (!img.isValid()) {
|
||||
LOGE("libbinder not found!");
|
||||
return false;
|
||||
}
|
||||
if (!hook_helper::HookSym(handler, BBinder_Transact)) {
|
||||
gBinderInterceptor = sp<BinderInterceptor>::make();
|
||||
gBinderStub = sp<BinderStub>::make();
|
||||
auto ioctlAddr = img.getSymbAddress("ioctl");
|
||||
if (DobbyHook(ioctlAddr, (dobby_dummy_func_t) new_ioctl, (dobby_dummy_func_t*) &old_ioctl) != 0) {
|
||||
LOGE("hook failed!");
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ open class BinderInterceptor : Binder() {
|
||||
val data = Parcel.obtain()
|
||||
val reply = Parcel.obtain()
|
||||
try {
|
||||
if (!b.transact(0xadbeef, data, reply, 0)) {
|
||||
if (!b.transact(0xdeadbeef.toInt(), data, reply, 0)) {
|
||||
Logger.e("remote return false!")
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user