mirror of
https://github.com/LSPosed/LSPlt.git
synced 2025-05-06 21:48:48 +08:00
Allow self hooking
This commit is contained in:
parent
b7fcd5c915
commit
fcba24abe2
@ -33,14 +33,27 @@ struct HookInfo : public lsplt::MapInfo {
|
|||||||
std::map<uintptr_t, uintptr_t> hooks;
|
std::map<uintptr_t, uintptr_t> hooks;
|
||||||
uintptr_t backup;
|
uintptr_t backup;
|
||||||
std::unique_ptr<Elf> elf;
|
std::unique_ptr<Elf> elf;
|
||||||
|
bool self;
|
||||||
[[nodiscard]] bool Match(const RegisterInfo &info) const { return info.inode == inode; }
|
[[nodiscard]] bool Match(const RegisterInfo &info) const { return info.inode == inode; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class HookInfos : public std::map<uintptr_t, HookInfo, std::greater<>> {
|
class HookInfos : public std::map<uintptr_t, HookInfo, std::greater<>> {
|
||||||
public:
|
public:
|
||||||
static auto ScanHookInfo() {
|
static auto ScanHookInfo() {
|
||||||
|
static ino_t kSelfInode = 0;
|
||||||
HookInfos info;
|
HookInfos info;
|
||||||
for (auto &map : lsplt::MapInfo::Scan()) {
|
auto maps = lsplt::MapInfo::Scan();
|
||||||
|
if (kSelfInode == 0) {
|
||||||
|
auto self = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
|
||||||
|
for (auto &map : maps) {
|
||||||
|
if (self >= map.start && self < map.end) {
|
||||||
|
kSelfInode = map.inode;
|
||||||
|
LOGV("self inode = %lu", kSelfInode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &map : maps) {
|
||||||
// we basically only care about r-?p entry
|
// we basically only care about r-?p entry
|
||||||
// and for offset == 0 it's an ELF header
|
// and for offset == 0 it's an ELF header
|
||||||
// and for offset != 0 it's what we hook
|
// and for offset != 0 it's what we hook
|
||||||
@ -48,7 +61,8 @@ public:
|
|||||||
if (map.path.empty()) continue;
|
if (map.path.empty()) continue;
|
||||||
if (map.path[0] == '[') continue;
|
if (map.path[0] == '[') continue;
|
||||||
auto start = map.start;
|
auto start = map.start;
|
||||||
info.emplace(start, HookInfo{{std::move(map)}, {}, 0, nullptr});
|
auto inode = map.inode;
|
||||||
|
info.emplace(start, HookInfo{{std::move(map)}, {}, 0, nullptr, inode == kSelfInode});
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -96,7 +110,7 @@ public:
|
|||||||
// iter.first < addr
|
// iter.first < addr
|
||||||
auto &info = iter->second;
|
auto &info = iter->second;
|
||||||
if (info.end <= addr) return false;
|
if (info.end <= addr) return false;
|
||||||
if (!iter->second.backup) {
|
if (!iter->second.backup && !info.self) {
|
||||||
auto len = info.end - info.start;
|
auto len = info.end - info.start;
|
||||||
// let os find a suitable address
|
// let os find a suitable address
|
||||||
auto *backup_addr = mmap(nullptr, len, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
auto *backup_addr = mmap(nullptr, len, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
@ -116,6 +130,14 @@ public:
|
|||||||
memcpy(reinterpret_cast<void *>(info.start), backup_addr, len);
|
memcpy(reinterpret_cast<void *>(info.start), backup_addr, len);
|
||||||
info.backup = reinterpret_cast<uintptr_t>(backup_addr);
|
info.backup = reinterpret_cast<uintptr_t>(backup_addr);
|
||||||
}
|
}
|
||||||
|
if (info.self) {
|
||||||
|
// self hooking, no need backup since we are always dirty
|
||||||
|
auto len = info.end - info.start;
|
||||||
|
if (!(info.perms & PROT_WRITE)) {
|
||||||
|
info.perms |= PROT_WRITE;
|
||||||
|
mprotect(reinterpret_cast<void *>(info.start), len, info.perms);
|
||||||
|
}
|
||||||
|
}
|
||||||
auto *the_addr = reinterpret_cast<uintptr_t *>(addr);
|
auto *the_addr = reinterpret_cast<uintptr_t *>(addr);
|
||||||
auto the_backup = *the_addr;
|
auto the_backup = *the_addr;
|
||||||
if (*the_addr != addr) {
|
if (*the_addr != addr) {
|
||||||
@ -128,7 +150,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
info.hooks.emplace(addr, the_backup);
|
info.hooks.emplace(addr, the_backup);
|
||||||
}
|
}
|
||||||
if (info.hooks.empty()) {
|
if (info.hooks.empty() && !info.self) {
|
||||||
auto len = info.end - info.start;
|
auto len = info.end - info.start;
|
||||||
LOGD("Restore %p from %p", reinterpret_cast<void *>(info.start),
|
LOGD("Restore %p from %p", reinterpret_cast<void *>(info.start),
|
||||||
reinterpret_cast<void *>(info.backup));
|
reinterpret_cast<void *>(info.backup));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user