/ deps / KittyMemoryEx / KittyMemoryMgr.cpp
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  }