KittyMemoryMgr.cpp
1 #include "KittyMemoryMgr.hpp" 2 #include "KittyMemoryEx.hpp" 3 4 bool KittyMemoryMgr::initialize(pid_t pid, EKittyMemOP eMemOp, bool initMemPatch) 5 { 6 _init = false; 7 _pid = pid; 8 9 if (_pid <= 0) 10 { 11 KITTY_LOGE("KittyMemoryMgr: Invalid arg (pid)."); 12 return false; 13 } 14 15 _process_name = KittyMemoryEx::getProcessName(_pid); 16 17 if (_pMemOp.get()) 18 _pMemOp.reset(); 19 20 _eMemOp = eMemOp; 21 switch (eMemOp) 22 { 23 case EK_MEM_OP_SYSCALL: 24 _pMemOp = std::make_unique<KittyMemSys>(); 25 break; 26 case EK_MEM_OP_IO: 27 _pMemOp = std::make_unique<KittyMemIO>(); 28 break; 29 default: 30 KITTY_LOGE("KittyMemoryMgr: Unknown memory operation."); 31 return false; 32 } 33 34 if (!_pMemOp->init(_pid)) 35 { 36 KITTY_LOGE("KittyMemoryMgr: Couldn't initialize memory operation."); 37 return false; 38 } 39 40 _init = true; 41 42 // patching mem only avaialabe for IO operation 43 if (initMemPatch) 44 { 45 if (eMemOp == EK_MEM_OP_IO) 46 { 47 memPatch = MemoryPatchMgr(_pMemOp.get()); 48 memBackup = MemoryBackupMgr(_pMemOp.get()); 49 } 50 else 51 { 52 if (_pMemOpPatch.get()) 53 _pMemOpPatch.reset(); 54 55 _pMemOpPatch = std::make_unique<KittyMemIO>(); 56 if (_pMemOpPatch->init(pid)) 57 { 58 memPatch = MemoryPatchMgr(_pMemOpPatch.get()); 59 memBackup = MemoryBackupMgr(_pMemOpPatch.get()); 60 } 61 else 62 { 63 KITTY_LOGW("KittyMemoryMgr: Couldn't initialize IO memory operation for memory patching."); 64 } 65 } 66 } 67 68 memScanner = KittyScannerMgr(_pMemOp.get()); 69 elfScanner = ElfScannerMgr(_pMemOp.get()); 70 71 #ifdef __ANDROID__ 72 73 #ifdef __LP64__ 74 linkerScanner = LinkerScannerMgr(_pMemOp.get(), 75 elfScanner.findElf("/linker64", EScanElfType::Native, EScanElfFilter::System)); 76 #else 77 linkerScanner = LinkerScannerMgr(_pMemOp.get(), 78 elfScanner.findElf("/linker", EScanElfType::Native, EScanElfFilter::System)); 79 #endif 80 81 nbScanner = NativeBridgeScannerMgr(_pMemOp.get(), &memScanner, &elfScanner); 82 83 #endif 84 85 if (trace.pid() != pid) 86 { 87 trace = KittyTraceMgr(pid); 88 } 89 90 return true; 91 } 92 93 size_t KittyMemoryMgr::readMem(uintptr_t address, void *buffer, size_t len) const 94 { 95 if (!isMemValid() || !buffer || !len) 96 return 0; 97 98 return _pMemOp->Read(address, buffer, len); 99 } 100 101 size_t KittyMemoryMgr::writeMem(uintptr_t address, void *buffer, size_t len) const 102 { 103 if (!isMemValid() || !buffer || !len) 104 return 0; 105 106 return _pMemOp->Write(address, buffer, len); 107 } 108 109 std::string KittyMemoryMgr::readMemStr(uintptr_t address, size_t maxLen) const 110 { 111 if (!isMemValid() || !address || !maxLen) 112 return ""; 113 114 return _pMemOp->ReadStr(address, maxLen); 115 } 116 117 bool KittyMemoryMgr::writeMemStr(uintptr_t address, std::string str) const 118 { 119 if (!isMemValid() || !address || str.empty()) 120 return false; 121 122 return _pMemOp->WriteStr(address, str); 123 } 124 125 bool KittyMemoryMgr::dumpMemRange(uintptr_t start, uintptr_t end, const std::string &destination) const 126 { 127 if (!isMemValid()) 128 return false; 129 130 if (start >= end) 131 { 132 KITTY_LOGE("dumpMemRange: start(%p) is equal or greater than end(%p).", (void *)start, (void *)end); 133 return false; 134 } 135 136 bool ok = false; 137 std::vector<char> memBuffer(end - start, 0); 138 if (_eMemOp == EK_MEM_OP_IO) 139 { 140 ok = _pMemOp->Read(start, memBuffer.data(), memBuffer.size()) > 0x1000; 141 } 142 else 143 { 144 KittyMemIO memIO = {}; 145 if (memIO.init(_pid)) 146 { 147 ok = memIO.Read(start, memBuffer.data(), memBuffer.size()) > 0x1000; 148 } 149 } 150 151 if (ok) 152 { 153 KittyIOFile destIO(destination, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0666); 154 if (destIO.open()) 155 { 156 ok = destIO.write(memBuffer.data(), memBuffer.size()) > 0x1000; 157 destIO.close(); 158 return ok; 159 } 160 } 161 162 return false; 163 } 164 165 bool KittyMemoryMgr::dumpMemFile(const std::string &memFile, const std::string &destination) const 166 { 167 if (!isMemValid() || memFile.empty() || destination.empty()) 168 return false; 169 170 auto fileMaps = KittyMemoryEx::getMaps(_pid, EProcMapFilter::EndWith, memFile); 171 if (fileMaps.empty()) 172 return false; 173 174 auto firstMap = fileMaps.front(); 175 uintptr_t lastEnd = firstMap.endAddress; 176 177 for (size_t i = 1; i < fileMaps.size(); ++i) 178 { 179 const auto &it = fileMaps[i]; 180 if (firstMap.inode != 0 && it.inode == firstMap.inode && it.startAddress == lastEnd) 181 { 182 lastEnd = it.endAddress; 183 continue; 184 } 185 break; 186 } 187 188 return dumpMemRange(firstMap.startAddress, lastEnd, destination); 189 } 190 191 bool KittyMemoryMgr::dumpMemELF(const ElfScanner &elf, const std::string &destination) const 192 { 193 if (!isMemValid() || !elf.base() || !elf.loadSize()) 194 return false; 195 196 bool dumped = dumpMemRange(elf.base(), elf.end(), destination); 197 if (dumped && elf.isFixedBySoInfo()) 198 { 199 KittyIOFile destIO(destination, O_WRONLY); 200 destIO.open(); 201 KT_ElfW(Ehdr) fixedHdr = elf.header(); 202 destIO.pwrite(0, &fixedHdr, sizeof(fixedHdr)); 203 destIO.close(); 204 } 205 206 return dumped; 207 }