8#include <unordered_map>
15#include "KittyUtils.hpp"
16#include "KittyMemoryEx.hpp"
17#include "KittyMemOp.hpp"
19#define KT_SCANNER_CHUNK_SIZE ((size_t)(1024 * 1024))
30 KittyScannerMgr() : _pMem(
nullptr)
56 const std::string &mask)
const;
68 uintptr_t
findBytesFirst(uintptr_t start, uintptr_t end,
const char *bytes,
const std::string &mask)
const;
80 std::vector<uintptr_t>
findHexAll(uintptr_t start, uintptr_t end, std::string hex,
const std::string &mask)
const;
92 uintptr_t
findHexFirst(uintptr_t start, uintptr_t end, std::string hex,
const std::string &mask)
const;
103 std::vector<uintptr_t>
findIdaPatternAll(uintptr_t start, uintptr_t end,
const std::string &pattern)
const;
126 std::vector<uintptr_t>
findDataAll(uintptr_t start, uintptr_t end,
const void *data,
size_t size)
const;
138 uintptr_t
findDataFirst(uintptr_t start, uintptr_t end,
const void *data,
size_t size)
const;
143#define KT_SOINFO_BUFFER_SZ 0x250
156 uintptr_t strtab = 0;
157 uintptr_t symtab = 0;
161 uint16_t e_machine = 0;
163 std::string realpath;
169enum class EScanElfType : uint32_t
179enum class EScanElfFilter : uint32_t
194 friend class ElfScannerMgr;
195 friend class LinkerScannerMgr;
196 friend class NativeBeidgeScannerMgr;
203 std::vector<KT_ElfW(Phdr)> _phdrs;
205 uintptr_t _loadBias, _loadSize;
207 std::vector<KT_ElfW(Dyn)> _dynamics;
208 uintptr_t _stringTable, _symbolTable, _elfHashTable, _gnuHashTable;
209 size_t _strsz, _syment;
212 std::vector<KittyMemoryEx::ProcMap> _segments;
213 std::vector<KittyMemoryEx::ProcMap> _bssSegments;
214 std::string _filepath;
215 std::string _realpath;
217 std::unordered_map<std::string, uintptr_t> _dsymbolsMap;
221 : _pMem(
nullptr), _elfBase(0), _phdr(0), _loads(0), _loadBias(0), _loadSize(0), _dynamic(0), _stringTable(0),
222 _symbolTable(0), _elfHashTable(0), _gnuHashTable(0), _strsz(0), _syment(0), _fixedBySoInfo(
false),
223 _dsymbols_init(
false)
261 ElfScanner(
IKittyMemOp *pMem,
const kitty_soinfo_t &soinfo,
const std::vector<KittyMemoryEx::ProcMap> &maps);
284 return _elfBase && _loadSize && _phdr && _loadBias;
294 return _fixedBySoInfo;
308 inline uintptr_t
end()
const
310 return _elfBase + _loadSize;
414 return _elfHashTable;
422 return _gnuHashTable;
429 std::unordered_map<std::string, uintptr_t>
dsymbols();
458 std::vector<KittyMemoryEx::ProcMap>
segments()
const
493 return _baseSegment.offset != 0;
503 for (
auto &it : _dynamics)
505 if (it.d_tag == DT_DEBUG && it.d_un.d_val)
508 _pMem->Read(it.d_un.d_val, out,
sizeof(r_debug));
522 friend class NativeBeidgeScannerMgr;
527 std::unordered_map<uintptr_t, ElfScanner> _cached_elfs;
530 ElfScannerMgr() : _pMem(
nullptr)
567 inline ElfScanner createWithSoInfo(
const kitty_soinfo_t &soinfo)
const
586 int a =
getProgramElf().header().e_machine, b = elf.header().e_machine;
587 return a != 0 && b != 0 && a == b;
597 int a =
getProgramElf().header().e_machine, b = elf.header().e_machine;
598 return a != 0 && b != 0 && a != b;
613 std::vector<ElfScanner>
getAllELFs(EScanElfType type = EScanElfType::Any,
614 EScanElfFilter filter = EScanElfFilter::Any);
627 EScanElfType type = EScanElfType::Any,
628 EScanElfFilter filter = EScanElfFilter::Any);
637 std::vector<std::pair<uintptr_t, ElfScanner>>
findSymbolAll(
const std::string &symbolName,
638 EScanElfType type = EScanElfType::Any,
639 EScanElfFilter filter = EScanElfFilter::Any);
662 std::vector<std::pair<uintptr_t, ElfScanner>>
findSymbolAll(
const std::string &symbolName);
682struct kitty_linker_syms_t
684 uintptr_t solist = 0;
685 uintptr_t somain = 0;
686 uintptr_t sonext = 0;
692struct kitty_soinfo_offsets_t
698 static constexpr uintptr_t noff = uintptr_t(-1);
700 uintptr_t base = noff;
701 uintptr_t size = noff;
702 uintptr_t phdr = noff;
703 uintptr_t phnum = noff;
704 uintptr_t dyn = noff;
705 uintptr_t strtab = noff;
706 uintptr_t symtab = noff;
707 uintptr_t strsz = noff;
708 uintptr_t bias = noff;
709 uintptr_t next = noff;
715 inline bool isValid()
const
717 return phdr != noff && phnum != noff && base != noff && size != noff && dyn != noff && strtab != noff &&
718 symtab != noff && bias != noff && next != noff;
730 kitty_linker_syms_t _linker_syms;
731 kitty_soinfo_offsets_t _soinfo_offsets;
735 LinkerScannerMgr() : ElfScanner(), _init(false)
737 memset(&_linker_syms, 0,
sizeof(_linker_syms));
738 memset(&_soinfo_offsets, 0,
sizeof(_soinfo_offsets));
746 LinkerScannerMgr(IKittyMemOp *pMem,
const ElfScanner &linkerElf);
753 LinkerScannerMgr(IKittyMemOp *pMem, uintptr_t linkerBase);
764 inline bool isInitialized()
const
773 inline ElfScanner *asELF()
const
775 return (ElfScanner *)
this;
781 inline kitty_linker_syms_t linker_offsets()
const
789 inline kitty_soinfo_offsets_t soinfo_offsets()
const
791 return _soinfo_offsets;
797 inline uintptr_t solist()
const
799 if (!
isValid() || !_linker_syms.solist)
803 return _pMem->
Read(_linker_syms.solist, &value,
sizeof(uintptr_t)) ==
sizeof(uintptr_t) ? value : 0;
809 inline uintptr_t somain()
const
811 if (!
isValid() || !_linker_syms.somain)
815 return _pMem->
Read(_linker_syms.somain, &value,
sizeof(uintptr_t)) ==
sizeof(uintptr_t) ? value : 0;
821 inline uintptr_t sonext()
const
823 if (!
isValid() || !_linker_syms.sonext)
827 return _pMem->
Read(_linker_syms.sonext, &value,
sizeof(uintptr_t)) ==
sizeof(uintptr_t) ? value : 0;
833 inline kitty_soinfo_t somainInfo()
const
835 if (!
isValid() || !_linker_syms.somain)
844 inline kitty_soinfo_t sonextInfo()
const
855 std::vector<kitty_soinfo_t> allSoInfo()
const;
862 kitty_soinfo_t findSoInfo(
const std::string &name)
const;
865 kitty_soinfo_t infoFromSoInfo_(uintptr_t si,
const std::vector<KittyMemoryEx::ProcMap> &maps)
const;
870 KT_JNICallTypeRegular = 1,
871 KT_JNICallTypeCriticalNative = 2,
874enum KT_NativeBridgeImplementationVersion
877 KT_NB_DEFAULT_VERSION = 1,
879 KT_NB_SIGNAL_VERSION = 2,
881 KT_NB_NAMESPACE_VERSION = 3,
883 KT_NB_VENDOR_NAMESPACE_VERSION = 4,
885 KT_NB_RUNTIME_NAMESPACE_VERSION = 5,
887 KT_NB_PRE_ZYGOTE_FORK_VERSION = 6,
889 KT_NB_CRITICAL_NATIVE_SUPPORT_VERSION = 7,
891 KT_NB_IDENTIFY_NATIVELY_BRIDGED_FUNCTION_POINTERS_VERSION = 8,
899 inline nbItf_data_t()
901 memset(
this, 0,
sizeof(nbItf_data_t));
908 bool (*initialize)(
const void *runtime_cbs,
const char *private_dir,
const char *instruction_set);
909 void *(*loadLibrary)(
const char *libpath,
int flag);
910 void *(*getTrampoline)(
void *handle,
const char *name,
const char *shorty, uint32_t len);
911 bool (*isSupported)(
const char *libpath);
912 const void *(*getAppEnv)(
const char *instruction_set);
913 bool (*isCompatibleWith)(uint32_t bridge_version);
914 void *(*getSignalHandler)(
int signal);
915 int (*unloadLibrary)(
void *handle);
916 const char *(*getError)();
917 bool (*isPathSupported)(
const char *library_path);
918 bool (*initAnonymousNamespace)(
const char *public_ns_sonames,
const char *anon_ns_library_path);
919 void *(*createNamespace)(
const char *name,
920 const char *ld_library_path,
921 const char *default_library_path,
923 const char *permitted_when_isolated_path,
925 bool (*linkNamespaces)(
void *from,
void *to,
const char *shared_libs_sonames);
926 void *(*loadLibraryExt)(
const char *libpath,
int flag,
void *ns);
927 void *(*getVendorNamespace)();
928 void *(*getExportedNamespace)(
const char *name);
929 void (*preZygoteFork)();
930 void *(*getTrampolineWithJNICallType)(
void *handle,
934 enum KT_JNICallType jni_call_type);
935 void *(*getTrampolineForFunctionPointer)(
const void *method,
938 enum KT_JNICallType jni_call_type);
939 bool (*isNativeBridgeFunctionPointer)(
const void *method);
941 inline static size_t GetStructSize(
int version)
945 case KT_NB_SIGNAL_VERSION:
946 return sizeof(uintptr_t) * 8;
947 case KT_NB_NAMESPACE_VERSION:
948 return sizeof(uintptr_t) * 15;
949 case KT_NB_VENDOR_NAMESPACE_VERSION:
950 return sizeof(uintptr_t) * 16;
951 case KT_NB_RUNTIME_NAMESPACE_VERSION:
952 return sizeof(uintptr_t) * 17;
953 case KT_NB_PRE_ZYGOTE_FORK_VERSION:
954 return sizeof(uintptr_t) * 18;
955 case KT_NB_CRITICAL_NATIVE_SUPPORT_VERSION:
956 return sizeof(uintptr_t) * 19;
957 case KT_NB_IDENTIFY_NATIVELY_BRIDGED_FUNCTION_POINTERS_VERSION:
958 return sizeof(uintptr_t) * 21;
967class NativeBridgeScannerMgr
971 KittyScannerMgr *_memScanner;
972 ElfScannerMgr *_elfScanner;
973 ElfScanner _nbElf, _nbImplElf, _soheadElf;
975 kitty_soinfo_offsets_t _soinfo_offsets;
980 size_t _nbItf_data_size;
981 nbItf_data_t _nbItf_data;
984 bool (*fnNativeBridgeInitialized)();
986 NativeBridgeScannerMgr()
987 : _pMem(nullptr), _memScanner(nullptr), _elfScanner(nullptr), _sohead(0), _init(false), _isHoudini(false),
988 _nbItf(0), _nbItf_data_size(0), fnNativeBridgeInitialized(nullptr)
990 memset(&_nbItf_data, 0,
sizeof(_nbItf_data));
991 memset(&_soinfo_offsets, 0,
sizeof(_soinfo_offsets));
1000 NativeBridgeScannerMgr(IKittyMemOp *pMem, KittyScannerMgr *memScanner, ElfScannerMgr *elfScanner);
1011 inline bool isValid()
const
1019 inline kitty_soinfo_offsets_t soinfo_offsets()
const
1021 return _soinfo_offsets;
1027 inline ElfScanner &nbElf()
1035 inline ElfScanner &nbImplElf()
1043 inline ElfScanner &soheadElf()
1051 inline bool isHoudini()
const
1059 inline uintptr_t sohead()
const
1067 inline kitty_soinfo_t soheadInfo()
const
1069 if (!_pMem || !_sohead)
1078 std::vector<kitty_soinfo_t> allSoInfo()
const;
1085 kitty_soinfo_t findSoInfo(
const std::string &name)
const;
1090 inline size_t nbItfDataSize()
const
1092 return _nbItf_data_size;
1098 inline nbItf_data_t nbItfData()
const
1104 kitty_soinfo_t infoFromSoInfo_(uintptr_t si,
const std::vector<KittyMemoryEx::ProcMap> &maps)
const;
ElfScanner createWithBase(uintptr_t elfBase) const
Constructs ElfScanner class with the given ELF base address.
Definition KittyScanner.hpp:547
ElfScannerMgr(IKittyMemOp *pMem)
Constructor for ElfScannerMgr.
Definition KittyScanner.hpp:538
bool isElfEmulated(const ElfScanner &elf)
Checks if the memory-mapped ELF file is emulated to the Android device.
Definition KittyScanner.hpp:595
ElfScanner findElf(const std::string &path)
Searches for a memory mapped ELF file based on the given path, type, and filter.
uintptr_t findRemoteSymbol(const std::string &local_sym_name, uintptr_t local_sym_addr)
Finds the remote address of a local symbol.
bool isValidELF(uintptr_t elfBase) const
Checks if provided base address is an Elf.
std::vector< ElfScanner > getAllELFs()
Fetches all memory mapped ELFs.
ElfScanner createWithMap(const KittyMemoryEx::ProcMap &map) const
Constructs ElfScanner class with the given process memory map info.
Definition KittyScanner.hpp:557
ElfScanner & getProgramElf()
Returns the program ELF.
bool isElfNative(const ElfScanner &elf)
Checks if the memory-mapped ELF file is native to the Android device.
Definition KittyScanner.hpp:584
std::vector< std::pair< uintptr_t, ElfScanner > > findSymbolAll(const std::string &symbolName)
Lookup dynamic symbol name in all loaded ELFs.
Represents a scanner for memory ELF files. This class is used to scan ELF files from memory and extra...
Definition KittyScanner.hpp:193
uintptr_t loadSize() const
Elf's load size.
Definition KittyScanner.hpp:356
KT_ElfW(Ehdr) header() const
Elf's header.
Definition KittyScanner.hpp:316
uintptr_t stringTable() const
Elf's dynamic string table address in memory.
Definition KittyScanner.hpp:380
std::string realPath() const
Returns the real path of the memory mapped Elf file (e.g, incase if it's inside a zip,...
Definition KittyScanner.hpp:483
uintptr_t end() const
Elf's end address in memory.
Definition KittyScanner.hpp:308
size_t stringTableSize() const
Elf's dynamic string table size.
Definition KittyScanner.hpp:396
std::vector< KittyMemoryEx::ProcMap > segments() const
Returns all of Elf's memory maps info.
Definition KittyScanner.hpp:458
uintptr_t base() const
Elf's Base address in memory.
Definition KittyScanner.hpp:300
uintptr_t elfHashTable() const
Elf's ELF hash table address in memory (DT_HASH), zero if not present.
Definition KittyScanner.hpp:412
std::vector< KT_ElfW(Phdr)> programHeaders() const
Vector of Elf's program headers.
Definition KittyScanner.hpp:332
bool isValid() const
Checks if the ElfScanner class is valid.
Definition KittyScanner.hpp:282
bool isZipped() const
Returns if the memory mapped Elf file was loaded from zip file.
Definition KittyScanner.hpp:491
size_t symbolEntrySize() const
Elf's symbol entry size.
Definition KittyScanner.hpp:404
uintptr_t dynamic() const
Elf's dynamic section address in memory.
Definition KittyScanner.hpp:364
KittyMemoryEx::ProcMap baseSegment() const
Elf's base memory map info.
Definition KittyScanner.hpp:450
uintptr_t phdr() const
Elf's program header address in memory.
Definition KittyScanner.hpp:324
std::string filePath() const
Returns the file path of the memory mapped Elf file.
Definition KittyScanner.hpp:474
std::vector< KittyMemoryEx::ProcMap > bssSegments() const
Returns all of Elf's BSS memory maps.
Definition KittyScanner.hpp:466
uintptr_t findSymbol(const std::string &symbolName) const
Finds a symbol from the dynamic symbol table by name.
std::unordered_map< std::string, uintptr_t > dsymbols()
Returns a map of symbols from the symbol table (SHT_SYMTAB) on disk.
std::vector< KT_ElfW(Dyn)> dynamics() const
Vector of Elf's dynamic sections.
Definition KittyScanner.hpp:372
ElfScanner(IKittyMemOp *pMem, uintptr_t elfBase)
Constructor for ElfScanner class. This constructor initializes the ElfScanner class with the given EL...
Definition KittyScanner.hpp:245
bool isFixedBySoInfo() const
Checks if the ELF file is fixed by soinfo. Some Elf headers are obfuscated or removed,...
Definition KittyScanner.hpp:292
uintptr_t findDebugSymbol(const std::string &symbolName)
Finds a symbol from the symbol table (SHT_SYMTAB) on disk by name.
uintptr_t loadBias() const
Elf's load bias address in memory.
Definition KittyScanner.hpp:348
int loads() const
Elf's number of loads.
Definition KittyScanner.hpp:340
ElfScanner(IKittyMemOp *pMem, uintptr_t elfBase, const std::vector< KittyMemoryEx::ProcMap > &maps)
Constructor for ElfScanner class. This constructor initializes the ElfScanner class with the given EL...
uintptr_t symbolTable() const
Elf's dynamic symbol table address in memory.
Definition KittyScanner.hpp:388
bool find_r_debug(r_debug *out) const
Finds the r_debug structure in the process.
Definition KittyScanner.hpp:501
uintptr_t gnuHashTable() const
Elf's GNU hash table address in memory (DT_GNU_HASH), zero if not present.
Definition KittyScanner.hpp:420
Interface class for memory operations.
Definition KittyMemOp.hpp:46
pid_t processID() const
Returns the process ID.
Definition KittyMemOp.hpp:67
virtual size_t Read(uintptr_t address, void *buffer, size_t len, MemMode mode=MemMode::Normal)=0
Reads data from process memory.
Represents a mapping of a memory region.
Definition KittyMemoryEx.hpp:15
std::vector< uintptr_t > findDataAll(uintptr_t start, uintptr_t end, const void *data, size_t size) const
Searches for data within a remote memory range and returns all results.
uintptr_t findHexFirst(uintptr_t start, uintptr_t end, std::string hex, const std::string &mask) const
Searches for hex within a remote memory range and returns the first result.
std::vector< uintptr_t > findBytesAll(uintptr_t start, uintptr_t end, const char *bytes, const std::string &mask) const
Searches for bytes within a remote memory range and returns all results.
KittyScannerMgr(IKittyMemOp *pMem)
Constructor for KittyScannerMgr.
Definition KittyScanner.hpp:39
std::vector< uintptr_t > findIdaPatternAll(uintptr_t start, uintptr_t end, const std::string &pattern) const
Searches for a pattern within a remote memory range using the IDA pattern syntax and returns all resu...
uintptr_t findDataFirst(uintptr_t start, uintptr_t end, const void *data, size_t size) const
Searches for data within a remote memory range and returns the first result.
std::vector< uintptr_t > findHexAll(uintptr_t start, uintptr_t end, std::string hex, const std::string &mask) const
Searches for hex within a remote memory range and returns all results.
uintptr_t findBytesFirst(uintptr_t start, uintptr_t end, const char *bytes, const std::string &mask) const
Searches for bytes within a remote memory range and returns the first result.
uintptr_t findIdaPatternFirst(uintptr_t start, uintptr_t end, const std::string &pattern) const
Searches for a pattern within a remote memory range using the IDA pattern syntax and returns the firs...
Represents a mapping of a memory region.
Definition KittyMemoryEx.hpp:15
Provides utility functions for process memory.
Definition KittyMemoryEx.hpp:10
std::vector< ProcMap > getAllMaps(pid_t pid)
Retrieves information about all memory maps in a remote process.