mirror of
https://github.com/LSPosed/LSPlt.git
synced 2025-05-06 21:48:48 +08:00
Export scan map interface
This commit is contained in:
parent
1155891414
commit
5e1c3b1a9e
@ -17,7 +17,7 @@ struct MapInfo {
|
|||||||
ino_t inode;
|
ino_t inode;
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
||||||
static std::vector<MapInfo> Scan();
|
[[maybe_unused, gnu::visibility("default")]] static std::vector<MapInfo> Scan();
|
||||||
};
|
};
|
||||||
|
|
||||||
[[maybe_unused, gnu::visibility("default")]] bool RegisterHook(ino_t ino, std::string_view symbol,
|
[[maybe_unused, gnu::visibility("default")]] bool RegisterHook(ino_t ino, std::string_view symbol,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
@ -20,52 +21,29 @@ struct RegisterInfo {
|
|||||||
void **backup;
|
void **backup;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HookMapInfo : public lsplt::MapInfo {
|
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;
|
||||||
[[nodiscard]] bool Match(const RegisterInfo &info) const { return info.inode == inode; }
|
[[nodiscard]] bool Match(const RegisterInfo &info) const { return info.inode == inode; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class HookMapInfos : public std::map<uintptr_t, MapInfo, std::greater<>> {
|
class HookInfos : public std::map<uintptr_t, HookInfo, std::greater<>> {
|
||||||
public:
|
public:
|
||||||
static MapInfos ScanMapInfo() {
|
static auto ScanHookInfo() {
|
||||||
constexpr static auto kPermLength = 5;
|
HookInfos info;
|
||||||
constexpr static auto kMapEntry = 5;
|
for (auto &map : lsplt::MapInfo::Scan()) {
|
||||||
MapInfos info;
|
// we basically only care about r--p entry
|
||||||
auto maps =
|
// and for offset == 0 it's an ELF header
|
||||||
std::unique_ptr<FILE, decltype(&fclose)>{fopen("/proc/self/maps", "r"), &fclose};
|
// and for offset != 0 it's what we hook
|
||||||
if (maps) {
|
// if (perm[0] != 'r') continue;
|
||||||
char *line = nullptr;
|
if (!map.is_private) continue;
|
||||||
size_t len = 0;
|
if (map.perm & PROT_EXEC) continue;
|
||||||
ssize_t read;
|
// if (off != 0) continue;
|
||||||
while ((read = getline(&line, &len, maps.get())) != -1) {
|
if (map.path.empty()) continue;
|
||||||
uintptr_t start = 0;
|
if (map.path[0] == '[') continue;
|
||||||
uintptr_t end = 0;
|
auto start = map.start;
|
||||||
uintptr_t off = 0;
|
info.emplace(start, HookInfo{{std::move(map)}, {}, 0, nullptr});
|
||||||
ino_t inode = 0;
|
|
||||||
std::array<char, kPermLength> perm{'\0'};
|
|
||||||
int path_off;
|
|
||||||
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %lu %n%*s",
|
|
||||||
&start, &end, perm.data(), &off, &inode, &path_off) != kMapEntry) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// we basically only care about r--p entry
|
|
||||||
// and for offset == 0 it's an ELF header
|
|
||||||
// and for offset != 0 it's what we hook
|
|
||||||
// if (perm[0] != 'r') continue;
|
|
||||||
if (perm[3] != 'p') continue;
|
|
||||||
if (perm[2] == 'x') continue;
|
|
||||||
// if (off != 0) continue;
|
|
||||||
while (path_off < read && isspace(line[path_off])) path_off++;
|
|
||||||
if (path_off >= read) continue;
|
|
||||||
std::string path{line + path_off};
|
|
||||||
if (path.empty()) continue;
|
|
||||||
if (path[0] == '[') continue;
|
|
||||||
|
|
||||||
info.emplace(start, MapInfo{std::move(path), inode, start, end, {}, 0, nullptr});
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -89,7 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Merge(MapInfos &old) {
|
void Merge(HookInfos &old) {
|
||||||
// merge with old map info
|
// merge with old map info
|
||||||
for (auto &info : old) {
|
for (auto &info : old) {
|
||||||
if (info.second.backup) {
|
if (info.second.backup) {
|
||||||
@ -198,14 +176,13 @@ public:
|
|||||||
|
|
||||||
std::mutex hook_mutex;
|
std::mutex hook_mutex;
|
||||||
std::list<RegisterInfo> register_info;
|
std::list<RegisterInfo> register_info;
|
||||||
MapInfos map_info;
|
HookInfos hook_info;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace lsplt {
|
namespace lsplt {
|
||||||
|
[[maybe_unused]] std::vector<MapInfo> MapInfo::Scan() {
|
||||||
std::vector<MapInfo> MapInfo::Scan() {
|
|
||||||
constexpr static auto kPermLength = 5;
|
constexpr static auto kPermLength = 5;
|
||||||
constexpr static auto kMapEntry = 5;
|
constexpr static auto kMapEntry = 7;
|
||||||
std::vector<MapInfo> info;
|
std::vector<MapInfo> info;
|
||||||
auto maps = std::unique_ptr<FILE, decltype(&fclose)>{fopen("/proc/self/maps", "r"), &fclose};
|
auto maps = std::unique_ptr<FILE, decltype(&fclose)>{fopen("/proc/self/maps", "r"), &fclose};
|
||||||
if (maps) {
|
if (maps) {
|
||||||
@ -217,26 +194,22 @@ std::vector<MapInfo> MapInfo::Scan() {
|
|||||||
uintptr_t end = 0;
|
uintptr_t end = 0;
|
||||||
uintptr_t off = 0;
|
uintptr_t off = 0;
|
||||||
ino_t inode = 0;
|
ino_t inode = 0;
|
||||||
|
unsigned int dev_major = 0;
|
||||||
|
unsigned int dev_minor = 0;
|
||||||
std::array<char, kPermLength> perm{'\0'};
|
std::array<char, kPermLength> perm{'\0'};
|
||||||
int path_off;
|
int path_off;
|
||||||
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %lu %n%*s", &start,
|
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %x:%x %lu %n%*s", &start,
|
||||||
&end, perm.data(), &off, &inode, &path_off) != kMapEntry) {
|
&end, perm.data(), &off, &dev_major, &dev_minor, &inode,
|
||||||
|
&path_off) != kMapEntry) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// we basically only care about r--p entry
|
|
||||||
// and for offset == 0 it's an ELF header
|
|
||||||
// and for offset != 0 it's what we hook
|
|
||||||
// if (perm[0] != 'r') continue;
|
|
||||||
if (perm[3] != 'p') continue;
|
|
||||||
if (perm[2] == 'x') continue;
|
|
||||||
// if (off != 0) continue;
|
|
||||||
while (path_off < read && isspace(line[path_off])) path_off++;
|
while (path_off < read && isspace(line[path_off])) path_off++;
|
||||||
if (path_off >= read) continue;
|
auto &ref = info.emplace_back(MapInfo{start, end, 0, perm[3] == 'p',
|
||||||
std::string path{line + path_off};
|
static_cast<dev_t>(makedev(dev_major, dev_minor)),
|
||||||
if (path.empty()) continue;
|
inode, line + path_off});
|
||||||
if (path[0] == '[') continue;
|
if (perm[0] == 'r') ref.perm |= PROT_READ;
|
||||||
|
if (perm[1] == 'w') ref.perm |= PROT_WRITE;
|
||||||
info.emplace(start, MapInfo{std::move(path), inode, start, end, {}, 0, nullptr});
|
if (perm[2] == 'x') ref.perm |= PROT_EXEC;
|
||||||
}
|
}
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
@ -256,20 +229,20 @@ std::vector<MapInfo> MapInfo::Scan() {
|
|||||||
std::unique_lock lock(hook_mutex);
|
std::unique_lock lock(hook_mutex);
|
||||||
if (register_info.empty()) return true;
|
if (register_info.empty()) return true;
|
||||||
|
|
||||||
auto new_map_info = MapInfos::ScanMapInfo();
|
auto new_hook_info = HookInfos::ScanHookInfo();
|
||||||
if (new_map_info.empty()) return false;
|
if (new_hook_info.empty()) return false;
|
||||||
|
|
||||||
new_map_info.Filter(register_info);
|
new_hook_info.Filter(register_info);
|
||||||
|
|
||||||
new_map_info.Merge(map_info);
|
new_hook_info.Merge(hook_info);
|
||||||
// update to new map info
|
// update to new map info
|
||||||
map_info = std::move(new_map_info);
|
hook_info = std::move(new_hook_info);
|
||||||
|
|
||||||
return map_info.DoHook(register_info);
|
return hook_info.DoHook(register_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[gnu::destructor]] [[maybe_unused]] bool InvalidateBackup() {
|
[[gnu::destructor]] [[maybe_unused]] bool InvalidateBackup() {
|
||||||
std::unique_lock lock(hook_mutex);
|
std::unique_lock lock(hook_mutex);
|
||||||
return map_info.InvalidateBackup();
|
return hook_info.InvalidateBackup();
|
||||||
}
|
}
|
||||||
} // namespace lsplt
|
} // namespace lsplt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user