├── src └── jni │ ├── Application.mk │ ├── main.cpp │ ├── Android.mk │ ├── ProcessManager.h │ └── ProcessManager.cpp ├── README.md └── LICENSE /src/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := armeabi-v7a 2 | APP_PLATFORM := android-21 3 | APP_STL := c++_static -------------------------------------------------------------------------------- /src/jni/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ProcessManager.h" 2 | 3 | int main() 4 | { 5 | ProcessManager p("com.yourtargetprocess.name"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | include $(CLEAR_VARS) 3 | LOCAL_ARM_MODE := arm 4 | LOCAL_LDLIBS := -llog 5 | LOCAL_ARM_NEON := false 6 | LOCAL_MODULE := mem 7 | LOCAL_SRC_FILES := main.cpp ProcessManager.cpp 8 | LOCAL_CFLAGS := 9 | include $(BUILD_EXECUTABLE) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Emulator-Android-External-Memory-Hacking 2 | android process/memory library root 3 | 4 | Library Features: 5 | 6 | * LoadToMemoryAndHook (will a passed function(should be simple function or shellcode)) 7 | * Hook 8 | * DisablePtrace 9 | * GetFuncSizeArm 10 | * FindCodeCave 11 | * EnumSegments 12 | * FindExternalSymbol (parse the elf header and find for symbols) 13 | * memcpyBackwrd (target to local) 14 | * memcpy (local to target) 15 | * GetFullModulePath 16 | * GetLocalModBaseAddr 17 | * GetModBaseAddr 18 | * WriteProcessMemory 19 | * ReadProcessMemory 20 | * FindDMAddy 21 | * FindPid 22 | 23 | how to build: 24 | 25 | * clone this repo 26 | * explore src in command line. 27 | * run ndk-build 28 | 29 | inplementation: https://www.youtube.com/watch?v=O4B3t2-67jc&t=7s 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mst1k 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/jni/ProcessManager.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define READ 0 8 | #define READ_WRITE 1 9 | #define EXECUTE_READ 2 10 | #define EXECUTE_READ_WRITE 3 11 | 12 | 13 | struct SegmentInfo{ 14 | /** 15 | * @brief full segment name, if is present 16 | * 17 | */ 18 | std::string name; 19 | /** 20 | * @brief segment size range protection 21 | * 22 | */ 23 | std::string prot; 24 | /** 25 | * @brief entry of the the segment in memory 26 | * 27 | */ 28 | uintptr_t start; 29 | /** 30 | * @brief end of the segment in memory 31 | * 32 | */ 33 | uintptr_t end; 34 | /** 35 | * @brief segment size in memory 36 | * 37 | */ 38 | uintptr_t size; 39 | }; 40 | 41 | class ProcessManager 42 | { 43 | private: 44 | /** 45 | * @brief targets process identifier(PID) 46 | * 47 | */ 48 | int pid; 49 | 50 | /** 51 | * @brief target process memory file descriptor 52 | * 53 | */ 54 | int memfd; 55 | 56 | /** 57 | * @brief target process maps file descriptor 58 | * 59 | */ 60 | int mapsfd; 61 | 62 | 63 | public: 64 | /** 65 | * @brief Construct a new Process Manager object 66 | * 67 | * @param procName the name of the target process to attach. 68 | */ 69 | ProcessManager(const char* procName); 70 | 71 | /** 72 | * @brief will find a proc id, enumerating all the /proc folders(pids). 73 | * 74 | * @param procName its the name of the process that we want to get the pid 75 | * @return int 76 | */ 77 | static int FindPid(const char* procName); 78 | 79 | /** 80 | * @brief read the memory in target address 81 | * 82 | * @tparam T target object type in target memory 83 | * @param addr it the target address 84 | * @return T target object return type from this function 85 | */ 86 | template 87 | T ReadProcessMemory(uintptr_t addr); 88 | 89 | /** 90 | * @brief solve multilevel pointers 91 | * 92 | * @param base base address to start the multilevel pointer calculation 93 | * @param offsets array of offset to index the multilevel pointer 94 | * @return uintptr_t return the address pointed in the multilevel pointer provided 95 | */ 96 | uintptr_t FindDMAddy(uintptr_t base, std::vector offsets); 97 | 98 | /** 99 | * @brief write the memory in target address 100 | * 101 | * @tparam T target object type to be writed in target process memory 102 | * @param addr target address in process target memory 103 | * @param newValue target value to be write in target process memory 104 | */ 105 | template 106 | void WriteProcessMemory(uintptr_t addr, T newValue); 107 | 108 | /** 109 | * @brief Get the Module Base Address of a module loaded in target process memory 110 | * 111 | * @param modName its the name of the module in target memory 112 | * @return uintptr_t the base address of the target module in the target memory 113 | */ 114 | uintptr_t GetModBaseAddr(const char* modName); 115 | 116 | /** 117 | * @brief Get the Module Base Address of a module loaded in local process memory 118 | * 119 | * @param modName its the name of the module in local memory 120 | * @return uintptr_t the base address of the target module in the local memory 121 | */ 122 | static uintptr_t GetLocalModBaseAddr(const char* modName); 123 | 124 | /** 125 | * @brief will get the full module path in disk from a loaded module in target memory 126 | * 127 | * @param modName name of the target module in target memory 128 | * @param result contains the full path of the target module 129 | * @return true result contain the full path 130 | * @return false an error ocurred while getting the full path, may wrong target library in target memory name 131 | */ 132 | bool GetFullModulePath(const char* modName, std::string & result); 133 | 134 | /** 135 | * @brief will copy data from local memory to target process memory 136 | * 137 | * @param source here is the source bytes in local memory 138 | * @param destination here is the destination point in target memory 139 | * @param size this is the count in bytes to be write 140 | */ 141 | void memcpy(unsigned char* source, uintptr_t destination, int size); 142 | 143 | /** 144 | * @brief will copy data from target memory to local process memory 145 | * 146 | * @param source here is the source bytes in target memory 147 | * @param destination here is the destination point in local memory 148 | * @param size this is the count in bytes to be write 149 | * @return true sucesfully copied 150 | * @return false error while copying 151 | */ 152 | bool memcpyBackwrd(uintptr_t source, unsigned char* destination, int size); 153 | 154 | /** 155 | * @brief will find for a symbol in target memory 156 | * 157 | * @param modName the name of the target module 158 | * @param symbolName the name of the target symbol 159 | * @return uintptr_t if not null an address to the symbol in target memory 160 | */ 161 | uintptr_t FindExternalSymbol(const char* modName, const char* symbolName); 162 | 163 | /** 164 | * @brief it will enumerate/parse all segments from the maps file 165 | * 166 | * @param segments this is a reference to a vector of segmentInfo struct 167 | * @param prot this is the target protection, could be READ, READ_WRITE, EXECUTE_READ, READ_WRITE_EXECUTE 168 | * @return true sucessfully enumerate all the target proteccion segments 169 | * @return false an error ocurred while enumerating 170 | */ 171 | bool EnumSegments(std::vector & segments, int prot); 172 | 173 | /** 174 | * @brief will find a piece of memory "empty" in the target process memory 175 | * 176 | * @param size the target size of the "empty" memory 177 | * @param prot the target memory proteccion, could be READ, READ_WRITE, EXECUTE_READ, READ_WRITE_EXECUTE 178 | * @return uintptr_t if success the returned address is not null 179 | */ 180 | uintptr_t FindCodeCave(uintptr_t size, uintptr_t prot); 181 | 182 | /** 183 | * @brief it will find and disable the ptrace function in the target process 184 | * 185 | */ 186 | void DisablePtrace(); 187 | 188 | /** 189 | * @brief it will detour the execution flow in determinated target memory point 190 | * 191 | * @param src where the detour will be aplied in the target memory 192 | * @param dst where the detour will go after detour in the target memory 193 | * @param size if arm, dont pass argument, the default size is 8, but in x86 need the size 194 | * @return true sucess 195 | * @return false non sucess 196 | */ 197 | bool Hook(uintptr_t src, uintptr_t dst, uintptr_t targetLen = 8); 198 | 199 | /** 200 | * @brief will load a function located on local process memory in the target process memory and will make a detour from target process memory point to it 201 | * 202 | * @param targetSrc detour entry 203 | * @param targetDst destination function in local process memory 204 | * @param targetLen lenght of bytes to be overwrited 205 | * @return true sucess 206 | * @return false fail 207 | */ 208 | bool LoadToMemoryAndHook(uintptr_t targetSrc, void* targetDst, uintptr_t targetLen = 8); 209 | }; 210 | 211 | template 212 | T ProcessManager::ReadProcessMemory(uintptr_t addr) 213 | { 214 | T result; 215 | lseek(memfd, addr, SEEK_SET); 216 | 217 | if(!read(memfd, &result, sizeof(result))) 218 | printf("ProcessManager : could not read the memory"); 219 | 220 | lseek(memfd, 0, SEEK_SET); 221 | return result; 222 | } 223 | 224 | template 225 | void ProcessManager::WriteProcessMemory(uintptr_t addr, T newValue) 226 | { 227 | lseek(memfd, addr, SEEK_SET); 228 | 229 | if(!write(memfd, &newValue, sizeof(T))) 230 | printf("ProcessManager : could not write the memory"); 231 | 232 | lseek(memfd, 0, SEEK_SET); 233 | } 234 | 235 | 236 | -------------------------------------------------------------------------------- /src/jni/ProcessManager.cpp: -------------------------------------------------------------------------------- 1 | #include "ProcessManager.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | const unsigned char popmask[] = "\xBD\xE8"; 12 | const unsigned char bxlrmask[] = "\x1E\xFF\x2F\xE1"; 13 | const unsigned char parammask[] = "\xCC\xCC\xCC\xCC"; 14 | 15 | #define GetBite(buff, pos) (((buff) & (0x1 << (pos)))) ? true : false 16 | 17 | /** 18 | * @brief definig DEBUG will cause, all the function logging its call. 19 | * 20 | */ 21 | #define DEBUG 22 | 23 | #define ZeroMemory(dst, size) memset((void*)(dst), 0x0, (size)) 24 | 25 | void LOG(const char* msg) 26 | { 27 | fprintf(stdout, "%s\n", msg); 28 | quick_exit(1); 29 | } 30 | 31 | int ProcessManager::FindPid(const char* procName){ 32 | #ifdef DEBUG 33 | printf("FindPid(%s)",procName); 34 | #endif 35 | int pid = -1; 36 | struct dirent* pDirent; 37 | DIR* dir; 38 | 39 | if(!procName) 40 | LOG("ProcessManager : not valid process name.\n"); 41 | 42 | dir = opendir("/proc/"); 43 | if(!dir) 44 | LOG("ProcessManager : cant open proc"); 45 | 46 | for(int currPid = 0;(pDirent = readdir(dir)) != NULL;) 47 | { 48 | if((currPid = atoi(pDirent->d_name)) == 0) 49 | continue; 50 | 51 | char currCmdLinePath[128]; 52 | sprintf(currCmdLinePath, "/proc/%d/cmdline", currPid); 53 | 54 | int currcmdLineFd = open((const char*)currCmdLinePath, O_RDONLY); 55 | if(currcmdLineFd == -1) 56 | continue; 57 | 58 | char currProcName[128]; 59 | 60 | memset(currProcName, NULL, 128); 61 | 62 | if(!read(currcmdLineFd, currProcName ,128)) 63 | continue; 64 | 65 | if(!strcmp(currProcName, procName)) 66 | { 67 | pid = currPid; 68 | break; 69 | } 70 | } 71 | 72 | #ifdef DEBUG 73 | printf(" = %d\n",pid); 74 | #endif 75 | closedir(dir); 76 | return pid; 77 | } 78 | 79 | ProcessManager::ProcessManager(const char* procName) 80 | { 81 | #ifdef DEBUG 82 | printf("ProcessManager(%s)\n",procName); 83 | #endif 84 | 85 | char ProcessMemoryPath[128]; 86 | char ProcessMapsPath[128]; 87 | 88 | if((pid = FindPid(procName)) == -1) 89 | LOG("ProcessManager : Could not found the process"); 90 | 91 | sprintf(ProcessMemoryPath, "/proc/%d/mem", pid); 92 | memfd = open(ProcessMemoryPath, O_RDWR); 93 | sprintf(ProcessMapsPath, "/proc/%d/maps", pid); 94 | mapsfd = open(ProcessMapsPath, O_RDONLY); 95 | 96 | if(memfd == -1) 97 | LOG("ProcessManager : Could not open process memory"); 98 | 99 | if(mapsfd == -1) 100 | LOG("ProcessManager : Could not open process maps"); 101 | 102 | return; 103 | } 104 | 105 | bool GetMapsBuffer(int fd, std::string & result) 106 | { 107 | #ifdef DEBUG 108 | printf("GetMapsBuffer(%d)\n",fd); 109 | #endif 110 | 111 | lseek(fd, 0, SEEK_SET); 112 | FILE* tmpf = fdopen(fd, "r"); 113 | if(!tmpf) 114 | return false; 115 | 116 | uintptr_t maxLineSize = 2048; 117 | char* line = (char*)malloc(maxLineSize); 118 | memset(line, 0, maxLineSize); 119 | if(!line) 120 | return false; 121 | 122 | while(getline(&line, &maxLineSize, tmpf) >= 0) 123 | result += std::string(line); 124 | 125 | free(line); 126 | 127 | return true; 128 | } 129 | 130 | void ParseMapLineSegment(char* lineStartSegment, SegmentInfo* buff) 131 | { 132 | uintptr_t unk1; 133 | char* tempName = (char*)malloc(256); 134 | char* tempProt = (char*)malloc(256); 135 | 136 | sscanf(lineStartSegment, "%08X-%08X %s %08X %02X:%02X %d %s\n", &buff->start, &buff->end, tempProt, &unk1, &unk1, &unk1, &unk1, tempName); 137 | 138 | buff->name = std::string(tempName); 139 | buff->prot = std::string(tempProt); 140 | buff->size = buff->end - buff->start; 141 | 142 | free(tempProt); 143 | free(tempName); 144 | return; 145 | } 146 | 147 | char* GetStartOfLine(char* minLimit, char* currLinePos) 148 | { 149 | char* result = currLinePos; 150 | 151 | if(currLinePos < minLimit) 152 | return minLimit; 153 | 154 | while(*result != '\n' && result > minLimit) result--; 155 | 156 | return result; 157 | } 158 | 159 | bool GetLineSegmentFromName(int fd, const char* modName, SegmentInfo * result) 160 | { 161 | std::string fullMaps; 162 | char* fullMapsPtr, *targetLine = nullptr; 163 | 164 | if(!GetMapsBuffer(fd, fullMaps)) 165 | return false; 166 | 167 | fullMapsPtr = (char*)fullMaps.c_str(); 168 | if((targetLine = strstr(fullMapsPtr, modName)) == nullptr) 169 | return false; 170 | 171 | targetLine = GetStartOfLine(fullMapsPtr, targetLine); 172 | ParseMapLineSegment(targetLine, result); 173 | 174 | return true; 175 | } 176 | 177 | uintptr_t ProcessManager::GetModBaseAddr(const char* modName) 178 | { 179 | #ifdef DEBUG 180 | printf("ProcessManager::GetModBaseAddr(%s)\n",modName); 181 | #endif 182 | 183 | SegmentInfo tSegment; 184 | 185 | if(!GetLineSegmentFromName(mapsfd, modName, &tSegment)) 186 | return 0; 187 | 188 | return tSegment.start; 189 | } 190 | 191 | uintptr_t ProcessManager::FindDMAddy(uintptr_t base, std::vector offsets) 192 | { 193 | uintptr_t result = base; 194 | 195 | for(int i = 0; i < offsets.size(); i++) 196 | { 197 | result = ReadProcessMemory(result); 198 | result += offsets[i]; 199 | } 200 | 201 | return result; 202 | } 203 | 204 | uintptr_t ProcessManager::GetLocalModBaseAddr(const char* modName) 205 | { 206 | #ifdef DEBUG 207 | printf("ProcessManager::GetLocalModBaseAdd(%s)\n",modName); 208 | #endif 209 | 210 | int localMapsfd = open("/proc/self/maps", O_RDONLY); 211 | SegmentInfo tSegment; 212 | ZeroMemory(&tSegment, sizeof(tSegment)); 213 | 214 | if(!localMapsfd) 215 | return 0; 216 | 217 | GetLineSegmentFromName(localMapsfd, modName, &tSegment); 218 | close(localMapsfd); 219 | 220 | return tSegment.start; 221 | } 222 | 223 | bool ProcessManager::GetFullModulePath(const char* modName, std::string & result) 224 | { 225 | #ifdef DEBUG 226 | printf("ProcessManager::GetFullModulePath(%s)\n",modName); 227 | #endif 228 | 229 | SegmentInfo tSegment; 230 | 231 | if(!GetLineSegmentFromName(mapsfd, modName, &tSegment)) 232 | return 0; 233 | 234 | result = tSegment.name; 235 | 236 | return true; 237 | } 238 | 239 | uintptr_t ProcessManager::FindExternalSymbol(const char* modName, const char* symbolName) 240 | { 241 | #ifdef DEBUG 242 | printf("ProcessManager::FindExternalSymbol(%s, %s)\n",modName, symbolName); 243 | #endif 244 | 245 | std::string fullModPath; 246 | int modfd; 247 | struct stat modstats; 248 | 249 | if(!GetFullModulePath(modName, fullModPath)) 250 | return 0; 251 | 252 | modfd = open(fullModPath.c_str(), O_RDONLY); 253 | 254 | fstat(modfd, &modstats); 255 | uintptr_t modBase = (uintptr_t)mmap(NULL,modstats.st_size, PROT_READ, MAP_SHARED, modfd, 0 ); 256 | 257 | Elf32_Ehdr* header = (Elf32_Ehdr*)modBase; 258 | Elf32_Shdr* sections = (Elf32_Shdr*)((Elf32_Off)modBase + header->e_shoff); 259 | 260 | for(int i = 0; i < header->e_shnum; i++) 261 | { 262 | if(sections[i].sh_type == SHT_SYMTAB) 263 | { 264 | uintptr_t stringSectionAddr = modBase + sections[sections[i].sh_link].sh_offset; 265 | Elf32_Sym* currSymbolSectionAddr = (Elf32_Sym*)(modBase + sections[i].sh_offset); 266 | 267 | for(int j = 0; j < (sections[i].sh_size / sizeof(Elf32_Sym)); j++) 268 | { 269 | if(ELF32_ST_BIND(currSymbolSectionAddr[j].st_info) & (STT_FUNC | STB_GLOBAL)) 270 | { 271 | char* currSymbolName = (char*)(stringSectionAddr + currSymbolSectionAddr[j].st_name); 272 | if(!strcmp(currSymbolName, symbolName)){ 273 | return GetModBaseAddr(modName) + currSymbolSectionAddr[j].st_value; 274 | } 275 | } 276 | } 277 | } 278 | } 279 | 280 | close(modfd); 281 | 282 | return 0; 283 | } 284 | 285 | void ProcessManager::memcpy(unsigned char* source, uintptr_t destination, int size) 286 | { 287 | for(int i = 0 ; i < size; i++) 288 | WriteProcessMemory(destination + i, source[i]); 289 | } 290 | 291 | bool ProcessManager::memcpyBackwrd(uintptr_t source, unsigned char* destination, int size) 292 | { 293 | for(int i = 0 ; i < size; i++) 294 | destination[i] = ReadProcessMemory(source + i); 295 | 296 | return true; 297 | } 298 | 299 | bool ProcessManager::EnumSegments(std::vector & segments, int prot) 300 | { 301 | #ifdef DEBUG 302 | printf("ProcessManager::EnumSegments(&)\n"); 303 | #endif 304 | 305 | std::string fullMaps; 306 | if(!GetMapsBuffer(mapsfd, fullMaps)) 307 | return false; 308 | 309 | char mask[5]; 310 | 311 | switch (prot) 312 | { 313 | case READ: 314 | strcpy(mask, "r--p"); 315 | break; 316 | 317 | case READ_WRITE: 318 | strcpy(mask, "rw-p"); 319 | break; 320 | 321 | case EXECUTE_READ: 322 | strcpy(mask, "r-xp"); 323 | break; 324 | 325 | case EXECUTE_READ_WRITE: 326 | strcpy(mask, "rwxp"); 327 | break; 328 | 329 | default: 330 | return false; 331 | break; 332 | } 333 | 334 | char* fullMapsPtr = (char*)fullMaps.c_str(); 335 | char* currLinePos = (char*)strstr(fullMapsPtr, (char*)mask); 336 | char* lastFoundMask = currLinePos; 337 | for(;currLinePos != nullptr;currLinePos = strstr(lastFoundMask, (char*)mask)) 338 | { 339 | SegmentInfo currSegment; 340 | 341 | lastFoundMask = currLinePos + 1; 342 | currLinePos = GetStartOfLine(fullMapsPtr, currLinePos); 343 | ParseMapLineSegment(currLinePos, &currSegment); 344 | segments.push_back(currSegment); 345 | } 346 | 347 | return true; 348 | } 349 | 350 | void ProcessManager::DisablePtrace() 351 | { 352 | #ifdef DEBUG 353 | printf("ProcessManager::DisablePtrace()\n"); 354 | #endif 355 | uintptr_t ptraceAddr = ptraceAddr = FindExternalSymbol("libc.so", "ptrace"); 356 | 357 | while(!ptraceAddr){ 358 | printf("ProcessManager : ptrace not found\n"); 359 | ptraceAddr = FindExternalSymbol("libc.so", "ptrace"); 360 | }; 361 | 362 | unsigned char buff[] = "\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"; // mov r0, 0 363 | // bx lr 364 | memcpy(buff, ptraceAddr, sizeof(buff)); 365 | } 366 | 367 | uintptr_t ProcessManager::FindCodeCave(uintptr_t size, uintptr_t prot) 368 | { 369 | #ifdef DEBUG 370 | printf("ProcessManager::FindCodeCave(%08X, %d)\n", size, prot); 371 | #endif 372 | 373 | std::vector segments; 374 | if(!EnumSegments(segments, prot)) 375 | return 0; 376 | 377 | size = ((size / 4) + 1) * 4; 378 | for(int i = 0; i < segments.size(); i++) 379 | { 380 | uintptr_t lastMatchIndex = 0; 381 | for(uintptr_t currAddr = segments[i].start; currAddr + size < segments[i].end; currAddr += 1 + lastMatchIndex) 382 | { 383 | if(ReadProcessMemory(currAddr) == 0x0) 384 | { 385 | bool found = true; 386 | for(int j = 1; j <= size; j++) 387 | { 388 | if(ReadProcessMemory(currAddr + j) != 0x0) 389 | { 390 | found = false; 391 | break; 392 | } else 393 | lastMatchIndex = j; 394 | } 395 | 396 | if(found) 397 | return ((currAddr / 4) + 1) * 4; 398 | } 399 | } 400 | } 401 | 402 | return 0; 403 | } 404 | 405 | bool ProcessManager::Hook(uintptr_t src, uintptr_t dst, uintptr_t size) 406 | { 407 | #ifdef DEBUG 408 | printf("ProcessManager::Hook(%08X, %08X, %08X)\n", src, dst, size); 409 | #endif 410 | unsigned char* detourPtr; 411 | uintptr_t tSize = size; 412 | #ifdef __arm__ 413 | if(tSize < 8) 414 | return false; 415 | 416 | unsigned char detour[] = {0x04, 0xF0, 0x1F, 0xE5, 0x0, 0x0, 0x0, 0x0}; 417 | *(uintptr_t*)(detour + 4) = dst; 418 | detourPtr = ( unsigned char*)detour; 419 | #elif defined(__i386__) 420 | if(tSize < 5) 421 | return false; 422 | 423 | unsigned char detour[] = {0xE9, 0x0, 0x0, 0x0, 0x0}; 424 | uintptr_t relativeAddr = src - dst - 5; 425 | *(uintptr_t*)(detour + 1) = relativeAddr; 426 | #endif 427 | 428 | memcpy(detourPtr, src, tSize); 429 | 430 | return true; 431 | } 432 | 433 | bool RelatedReturn(void* _chunk) 434 | { 435 | bool found = false; 436 | if (!memcmp(popmask, (unsigned char*)_chunk + 2, 2)) 437 | { 438 | int8_t chunk = *(int8_t*)((unsigned char*)_chunk + 1); 439 | if(GetBite(chunk, 7)) 440 | found = true; 441 | } 442 | 443 | if (!memcmp(bxlrmask, _chunk, 4)) 444 | found = true; 445 | 446 | return found; 447 | } 448 | 449 | uintptr_t GetFuncSizeArm(void* Func) 450 | { 451 | if (!Func) 452 | return 0; 453 | 454 | for (unsigned char* i = (unsigned char*)Func; ; i += 4) 455 | if (RelatedReturn(i)) 456 | { 457 | uintptr_t size = (((uintptr_t)i - (uintptr_t)Func)) + 4; 458 | size += 4; 459 | 460 | return size; 461 | } 462 | 463 | return 0; 464 | } 465 | 466 | bool ProcessManager::LoadToMemoryAndHook(uintptr_t targetSrc, void* targetDst, uintptr_t targetLen) 467 | { 468 | #ifdef DEBUG 469 | printf("ProcessManager::LoadToMemoryAndHook(%08X, %08X, %08X)\n", targetSrc, (uintptr_t)targetDst, targetLen); 470 | #endif 471 | uintptr_t DstAddrinTargetMemory; 472 | uintptr_t localDstSize = 1024; 473 | 474 | #ifdef __arm__ 475 | if(targetLen < 8) 476 | return false; 477 | 478 | localDstSize = GetFuncSizeArm(targetDst); 479 | if(!localDstSize) 480 | return false; 481 | 482 | DstAddrinTargetMemory = FindCodeCave(localDstSize, EXECUTE_READ); 483 | if(!DstAddrinTargetMemory) 484 | return false; 485 | 486 | #elif defined(__i386__) 487 | if(targetLen < 5) 488 | return false; 489 | 490 | 491 | #endif 492 | 493 | memcpy((unsigned char*)targetDst, DstAddrinTargetMemory, localDstSize); 494 | return Hook(targetSrc, DstAddrinTargetMemory); 495 | 496 | } --------------------------------------------------------------------------------