1+ //
2+ // KittyMemory.cpp
3+ //
4+ // Created by MJ (Ruit) on 1/1/19.
5+ //
6+
7+ #include " KittyMemory.h"
8+
9+ using KittyMemory::Memory_Status;
10+ using KittyMemory::ProcMap;
11+
12+
13+ struct mapsCache {
14+ std::string identifier;
15+ ProcMap map;
16+ };
17+
18+ static std::vector<mapsCache> __mapsCache;
19+ static ProcMap findMapInCache (std::string id){
20+ ProcMap ret;
21+ for (int i = 0 ; i < __mapsCache.size (); i++){
22+ if (__mapsCache[i].identifier .compare (id) == 0 ){
23+ ret = __mapsCache[i].map ;
24+ break ;
25+ }
26+ }
27+ return ret;
28+ }
29+
30+
31+ bool KittyMemory::ProtectAddr (void *addr, size_t length, int protection) {
32+ uintptr_t pageStart = _PAGE_START_OF_ (addr);
33+ uintptr_t pageLen = _PAGE_LEN_OF_ (addr, length);
34+ return (
35+ mprotect (reinterpret_cast <void *>(pageStart), pageLen, protection) != -1
36+ );
37+ }
38+
39+
40+ Memory_Status KittyMemory::memWrite (void *addr, const void *buffer, size_t len) {
41+ if (addr == NULL )
42+ return INV_ADDR ;
43+
44+ if (buffer == NULL )
45+ return INV_BUF ;
46+
47+ if (len < 1 || len > INT_MAX )
48+ return INV_LEN ;
49+
50+ if (!ProtectAddr (addr, len, _PROT_RWX_))
51+ return INV_PROT ;
52+
53+ if (memcpy (addr, buffer, len) != NULL && ProtectAddr (addr, len, _PROT_RX_))
54+ return SUCCESS ;
55+
56+ return FAILED ;
57+ }
58+
59+
60+ Memory_Status KittyMemory::memRead (void *buffer, const void *addr, size_t len) {
61+ if (addr == NULL )
62+ return INV_ADDR ;
63+
64+ if (buffer == NULL )
65+ return INV_BUF ;
66+
67+ if (len < 1 || len > INT_MAX )
68+ return INV_LEN ;
69+
70+ if (memcpy (buffer, addr, len) != NULL )
71+ return SUCCESS ;
72+
73+ return FAILED ;
74+ }
75+
76+
77+ std::string KittyMemory::read2HexStr (const void *addr, size_t len) {
78+ char temp[len];
79+ memset (temp, 0 , len);
80+
81+ const size_t bufferLen = len * 2 + 1 ;
82+ char buffer[bufferLen];
83+ memset (buffer, 0 , bufferLen);
84+
85+ std::string ret;
86+
87+ if (memRead (temp, addr, len) != SUCCESS )
88+ return ret;
89+
90+ for (int i = 0 ; i < len; i++) {
91+ sprintf (&buffer[i * 2 ], " %02X" , (unsigned char ) temp[i]);
92+ }
93+
94+ ret += buffer;
95+ return ret;
96+ }
97+
98+ ProcMap KittyMemory::getLibraryMap (const char *libraryName) {
99+ ProcMap retMap;
100+ char line[512 ] = {0 };
101+
102+ FILE *fp = fopen (" /proc/self/maps" , " rt" );
103+ if (fp != NULL ) {
104+ while (fgets (line, sizeof (line), fp)) {
105+ if (strstr (line, libraryName)) {
106+ char tmpPerms[5 ] = {0 }, tmpDev[12 ] = {0 }, tmpPathname[444 ] = {0 };
107+ // parse a line in maps file
108+ // (format) startAddress-endAddress perms offset dev inode pathname
109+ sscanf (line, " %llx-%llx %s %ld %s %d %s" ,
110+ (long long unsigned *) &retMap.startAddr ,
111+ (long long unsigned *) &retMap.endAddr ,
112+ tmpPerms, &retMap.offset , tmpDev, &retMap.inode , tmpPathname);
113+
114+ retMap.length = (uintptr_t ) retMap.endAddr - (uintptr_t ) retMap.startAddr ;
115+ retMap.perms = tmpPerms;
116+ retMap.dev = tmpDev;
117+ retMap.pathname = tmpPathname;
118+
119+ break ;
120+ }
121+ }
122+ fclose (fp);
123+ }
124+ return retMap;
125+ }
126+
127+ uintptr_t KittyMemory::getAbsoluteAddress (const char *libraryName, uintptr_t relativeAddr, bool useCache) {
128+ ProcMap libMap;
129+
130+ if (useCache){
131+ libMap = findMapInCache (libraryName);
132+ if (libMap.isValid ())
133+ return (reinterpret_cast <uintptr_t >(libMap.startAddr ) + relativeAddr);
134+ }
135+
136+ libMap = getLibraryMap (libraryName);
137+ if (!libMap.isValid ())
138+ return 0 ;
139+
140+ if (useCache){
141+ mapsCache cachedMap;
142+ cachedMap.identifier = libraryName;
143+ cachedMap.map = libMap;
144+ __mapsCache.push_back (cachedMap);
145+ }
146+
147+ return (reinterpret_cast <uintptr_t >(libMap.startAddr ) + relativeAddr);
148+ }
0 commit comments