Skip to content

Commit 7abffbc

Browse files
committed
v3.0.0 lib hide update
1 parent c2a12e9 commit 7abffbc

File tree

7 files changed

+276
-35
lines changed

7 files changed

+276
-35
lines changed

AndKittyInjector/runtest.bat

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@ECHO OFF
22

3+
SET "INJECTOR_ARCH=arm64"
34
SET "INJECTOR_NAME=AndKittyInjector"
45
SET "INJECTOR_PATH=/data/local/tmp/AndKittyInjector"
56

@@ -14,24 +15,31 @@ ECHO APP = %APP%
1415
ECHO LIB_ARCH = %LIB_ARCH%
1516
ECHO LIB_PATH = %LIB_PATH%
1617

18+
ECHO =========== PUSH ===========
19+
20+
IF "%INJECTOR_ARCH%"=="arm" adb push libs/armeabi-v7a/%INJECTOR_NAME% %INJECTOR_PATH%
21+
IF "%INJECTOR_ARCH%"=="arm64" adb push libs/arm64-v8a/%INJECTOR_NAME% %INJECTOR_PATH%
22+
IF "%INJECTOR_ARCH%"=="x86" adb push libs/x86/%INJECTOR_NAME% %INJECTOR_PATH%
23+
IF "%INJECTOR_ARCH%"=="x86_64" adb push libs/x86_64/%INJECTOR_NAME% %INJECTOR_PATH%
24+
1725
IF "%LIB_ARCH%"=="arm" adb push injtest/armeabi-v7a/libinjtest.so %LIB_PATH%
1826
IF "%LIB_ARCH%"=="arm64" adb push injtest/arm64-v8a/libinjtest.so %LIB_PATH%
1927
IF "%LIB_ARCH%"=="x86" adb push injtest/x86/libinjtest.so %LIB_PATH%
2028
IF "%LIB_ARCH%"=="x86_64" adb push injtest/x86_64/libinjtest.so %LIB_PATH%
2129

22-
ECHO =========== INJECTOR ===========
30+
ECHO =========== INJECT ===========
2331

24-
adb shell "su -c 'kill $(pidof %INJECTOR_PATH%) > /dev/null 2>&1'"
32+
adb shell "su -c 'kill $(pidof %INJECTOR_NAME%) > /dev/null 2>&1'"
2533

2634
:: exec perm
2735
adb shell "su -c 'chmod 755 %INJECTOR_PATH%'"
2836

29-
:: using -dl_memfd -watch and -delay 100000 microsecond, 100ms
30-
adb shell "su -c './%INJECTOR_NAME% -pkg %APP% -lib %LIB_PATH% -dl_memfd -watch -delay 100000'"
37+
:: using -dl_memfd -hide -watch and -delay 100000 microsecond, 100ms
38+
adb shell "su -c './%INJECTOR_PATH% -pkg %APP% -lib %LIB_PATH% -dl_memfd -hide -watch -delay 100000'"
3139

3240
ECHO ========= CHECKING MAPS =========
3341

34-
adb shell "su -c 'cat /proc/$(pgrep -n %APP%)/maps | grep %LIB_PATH%'"
35-
adb shell "su -c 'cat /proc/$(pgrep -n %APP%)/maps | grep memfd'"
42+
adb shell "su -c 'cat /proc/$(pidof %APP%)/maps | grep %LIB_PATH%'"
43+
adb shell "su -c 'cat /proc/$(pidof %APP%)/maps | grep memfd'"
3644

3745
PAUSE

AndKittyInjector/src/Injector/KittyInjector.cpp

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ bool KittyInjector::init(pid_t pid, EKittyMemOP eMemOp)
77

88
_kMgr = std::make_unique<KittyMemoryMgr>();
99

10-
if (!_kMgr->initialize(pid, eMemOp, false))
10+
if (!_kMgr->initialize(pid, eMemOp, true))
1111
{
1212
KITTY_LOGE("KittyInjector: Failed to initialize kittyMgr.");
1313
return false;
1414
}
1515

16+
_kMgr->trace.setAutoRestoreRegs(false);
17+
1618
bool isLocal64bit = !KittyMemoryEx::getMapsContain(getpid(), "/lib64/").empty();
1719
bool isRemote64bit = !KittyMemoryEx::getMapsContain(pid, "/lib64/").empty();
1820
if (isLocal64bit != isRemote64bit)
1921
{
20-
KITTY_LOGE("KittyInjector: Injector is %sbit but target app is %sbit.",
21-
isLocal64bit ? "64" : "32", isRemote64bit ? "64" : "32");
22+
KITTY_LOGE("KittyInjector: Injector is %sbit but target app is %sbit.", isLocal64bit ? "64" : "32", isRemote64bit ? "64" : "32");
2223
return false;
2324
}
2425

@@ -28,6 +29,8 @@ bool KittyInjector::init(pid_t pid, EKittyMemOP eMemOp)
2829
return false;
2930
}
3031

32+
_soinfo_patch.init(_kMgr.get());
33+
3134
_remote_dlopen = _kMgr->findRemoteOf("dlopen", (uintptr_t)&dlopen);
3235
if (!_remote_dlopen)
3336
{
@@ -59,7 +62,7 @@ bool KittyInjector::init(pid_t pid, EKittyMemOP eMemOp)
5962
return true;
6063
}
6164

62-
injected_info_t KittyInjector::injectLibrary(std::string libPath, int flags, bool use_memfd_dl)
65+
injected_info_t KittyInjector::injectLibrary(std::string libPath, int flags, bool use_memfd_dl, bool hide)
6366
{
6467
if (!_kMgr.get() || !_kMgr->isMemValid())
6568
{
@@ -133,14 +136,46 @@ injected_info_t KittyInjector::injectLibrary(std::string libPath, int flags, boo
133136
}
134137
}
135138

139+
pt_regs bkup_regs;
140+
memset(&bkup_regs, 0, sizeof(bkup_regs));
141+
142+
if (!_kMgr->trace.getRegs(&bkup_regs))
143+
{
144+
KITTY_LOGE("injectLibrary: failed to backup registers.");
145+
return {};
146+
}
147+
136148
injected_info_t injected {};
137149

138150
if (libHdr.e_machine == kNativeEM)
151+
{
152+
if (hide)
153+
_soinfo_patch.before_dlopen_patch();
154+
139155
injected = nativeInject(libFile, flags, canUseMemfd);
156+
157+
if (hide)
158+
_soinfo_patch.after_dlopen_patch();
159+
}
140160
else
161+
{
141162
injected = emuInject(libFile, flags);
163+
}
164+
165+
KITTY_LOGI("lib handle = %p", (void*)injected.dl_handle);
142166

143-
if (!injected.is_valid())
167+
if (injected.is_valid())
168+
{
169+
if (libHdr.e_machine == kNativeEM && hide)
170+
{
171+
hideSegmentsFromMaps(injected);
172+
173+
uintptr_t hide_init = injected.elfMap.elfScan.findSymbol("hide_init");
174+
KITTY_LOGI("Calling hide_init -> %p", (void*)hide_init);
175+
_kMgr->trace.callFunction(hide_init, 0);
176+
}
177+
}
178+
else
144179
{
145180
KITTY_LOGE("injectLibrary: failed )':");
146181
KITTY_LOGE("injectLibrary: calling dlerror...");
@@ -165,6 +200,9 @@ injected_info_t KittyInjector::injectLibrary(std::string libPath, int flags, boo
165200
// cleanup
166201
_remote_syscall.clearAllocatedMaps();
167202

203+
if (!_kMgr->trace.setRegs(&bkup_regs))
204+
KITTY_LOGE("injectLibrary: failed to restore registers.");
205+
168206
return injected;
169207
}
170208

@@ -196,7 +234,7 @@ injected_info_t KittyInjector::nativeInject(KittyIOFile& lib, int flags, bool us
196234
{
197235
std::string memfd_rand = KittyUtils::random_string(KittyUtils::randInt(5, 12));
198236

199-
info.name = memfd_rand;
237+
info.name = "/memfd:" + memfd_rand;
200238

201239
uintptr_t rmemfd_name = _remote_syscall.rmmap_str(memfd_rand);
202240
if (!rmemfd_name)
@@ -237,7 +275,7 @@ injected_info_t KittyInjector::nativeInject(KittyIOFile& lib, int flags, bool us
237275
info.dl_handle = _kMgr->trace.callFunction(_remote_dlopen_ext, 3, rmemfd_name, flags, rdlextinfo);
238276
kINJ_WAIT;
239277

240-
info.elfMap = _kMgr->getElfBaseMap(memfd_rand);
278+
info.elfMap = _kMgr->getElfBaseMap(info.name);
241279

242280
return info.elfMap.isValid();
243281
};
@@ -290,7 +328,8 @@ injected_info_t KittyInjector::emuInject(KittyIOFile& lib, int flags)
290328
// return (char *)&unk_64DF10 + 0xC670 * ns + qword_80C6C8;
291329
auto tryRemoteloadLibraryExt = [&](uint8_t ns_start, uint8_t ns_end) -> uintptr_t
292330
{
293-
for (uint8_t i = ns_start; i <= ns_end; i++) {
331+
for (uint8_t i = ns_start; i <= ns_end; i++)
332+
{
294333
uintptr_t h = _kMgr->trace.callFunction((uintptr_t)_nativeBridgeItf.loadLibraryExt, 3, remoteLibPath, flags, i);
295334
kINJ_WAIT;
296335

@@ -339,4 +378,49 @@ injected_info_t KittyInjector::emuInject(KittyIOFile& lib, int flags)
339378
info.elfMap = _kMgr->getElfBaseMap(lib.Path());
340379

341380
return info;
381+
}
382+
383+
bool KittyInjector::hideSegmentsFromMaps(injected_info_t &inj_info)
384+
{
385+
if (!inj_info.is_valid())
386+
{
387+
KITTY_LOGE("hideSegmentsFromMaps: Invalid info.");
388+
return false;
389+
}
390+
391+
if (inj_info.is_hidden || inj_info.elfMap.map.pathname.empty())
392+
return true;
393+
394+
// idea from https://github.com/RikkaApps/Riru/blob/master/riru/src/main/cpp/hide/hide.cpp
395+
396+
auto maps = KittyMemoryEx::getMapsContain(_kMgr->processID(), inj_info.elfMap.map.pathname);
397+
for (auto& it : maps)
398+
{
399+
KITTY_LOGI("hideSegmentsFromMaps: Hiding segment %p - %p", (void*)it.startAddress, (void*)it.endAddress);
400+
401+
// backup segment code
402+
auto bkup = _kMgr->memBackup.createBackup(it.startAddress, it.length);
403+
404+
_remote_syscall.rmunmap(it.startAddress, it.length);
405+
uintptr_t segment_new_map = _remote_syscall.rmmap_anon(it.startAddress, it.length, it.protection, false);
406+
407+
if (!IsValidRetPtr(segment_new_map))
408+
{
409+
KITTY_LOGE("hideSegmentsFromMaps: Failed to re-map segment %p, error = %s", (void*)it.startAddress, _remote_syscall.getRemoteError().c_str());
410+
return false;
411+
}
412+
413+
// restore segment code
414+
bkup.Restore();
415+
}
416+
417+
inj_info.name.clear();
418+
inj_info.name.shrink_to_fit();
419+
420+
inj_info.elfMap.map.pathname.clear();
421+
inj_info.elfMap.map.pathname.shrink_to_fit();
422+
423+
inj_info.is_hidden = true;
424+
425+
return true;
342426
}

AndKittyInjector/src/Injector/KittyInjector.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "../NativeBridge/NativeBridge.hpp"
99

1010
#include "RemoteSyscall.hpp"
11+
#include "SoInfoPatch.hpp"
1112

1213
#ifdef __aarch64__
1314
static constexpr ElfW_(Half) kNativeEM = EM_AARCH64;
@@ -47,6 +48,8 @@ class KittyInjector
4748
ElfBaseMap _houdiniElf;
4849
NativeBridgeCallbacks _nativeBridgeItf;
4950

51+
SoInfoPatch _soinfo_patch;
52+
5053
public:
5154
KittyInjector() : _remote_dlopen(0), _remote_dlopen_ext(0), _remote_dlclose(0), _remote_dlerror(0)
5255
{
@@ -68,9 +71,11 @@ class KittyInjector
6871
inline bool attach() { return _kMgr.get() && _kMgr->isMemValid() && _kMgr->trace.Attach(); };
6972
inline bool detach() { return _kMgr.get() && _kMgr->isMemValid() && _kMgr->trace.Detach(); }
7073

71-
injected_info_t injectLibrary(std::string libPath, int flags, bool use_dl_memfd);
74+
injected_info_t injectLibrary(std::string libPath, int flags, bool use_dl_memfd, bool hide);
7275

7376
private:
7477
injected_info_t nativeInject(KittyIOFile& lib, int flags, bool use_dl_memfd);
7578
injected_info_t emuInject(KittyIOFile& lib, int flags);
79+
80+
bool hideSegmentsFromMaps(injected_info_t &inj_info);
7681
};

AndKittyInjector/src/Injector/RemoteSyscall.hpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
#define syscall_munmap_n 215
1010
#define syscall_memfd_create_n 279
1111
#elif __arm__
12-
#define syscall_mprotect_n 125
1312
#define syscall_fcntl_n 221 // fcntl64
14-
//#define syscall_fcntl_n 55
13+
#define syscall_mprotect_n 125
1514
#define syscall_mmap_n 192 // mmap2
1615
#define syscall_munmap_n 91
1716
#define syscall_memfd_create_n 385
@@ -78,8 +77,11 @@ class RemoteSyscall
7877
if (!_kMgr || !_kMgr->isMemValid())
7978
return 0;
8079

81-
intptr_t remoteMem = _kMgr->trace.callFunction(_remote_syscall, 7, syscall_mmap_n,
82-
addr, size, prot, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
80+
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
81+
if (addr)
82+
flags |= MAP_FIXED;
83+
84+
intptr_t remoteMem = _kMgr->trace.callFunction(_remote_syscall, 7, syscall_mmap_n, addr, size, prot, flags, 0, 0);
8385
if (!IsValidRetPtr(remoteMem))
8486
return 0;
8587

@@ -89,17 +91,22 @@ class RemoteSyscall
8991
return remoteMem;
9092
}
9193

92-
uintptr_t rmmap_shared(uintptr_t addr, size_t size, int prot, int fd)
94+
uintptr_t rmmap_shared(uintptr_t addr, size_t size, int prot, int fd, bool deleteOnClear=true)
9395
{
9496
if (!_kMgr || !_kMgr->isMemValid())
9597
return 0;
9698

97-
intptr_t remoteMem = _kMgr->trace.callFunction(_remote_syscall, 7, syscall_mmap_n,
98-
addr, size, prot, MAP_SHARED, fd, 0);
99+
int flags = MAP_SHARED;
100+
if (addr)
101+
flags |= MAP_FIXED;
102+
103+
intptr_t remoteMem = _kMgr->trace.callFunction(_remote_syscall, 7, syscall_mmap_n, addr, size, prot, flags, fd, 0);
99104
if (!IsValidRetPtr(remoteMem))
100105
return 0;
101106

102-
vAllocatedMaps[remoteMem] = size;
107+
if (deleteOnClear)
108+
vAllocatedMaps[remoteMem] = size;
109+
103110
return remoteMem;
104111
}
105112

0 commit comments

Comments
 (0)