Skip to content

Commit 209f8f9

Browse files
committed
Update v2.0.0
- Code improvements & fixes - Added command line arguments - Added option to watch app launch - Added option to set delay - Added test lib
1 parent b062ff7 commit 209f8f9

File tree

13 files changed

+511
-81
lines changed

13 files changed

+511
-81
lines changed

AndKittyInjector/Android.mk

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
LOCAL_PATH := $(call my-dir)
22

33
KITTYMEMORY_PATH = $(LOCAL_PATH)/../KittyMemoryEx/KittyMemoryEx
4-
KITTYMEMORY_SRC = $(wildcard $(KITTYMEMORY_PATH)/*.cpp)
4+
KITTYMEMORY_SRC = $(wildcard $(KITTYMEMORY_PATH)/*.cpp)
55

66
## Example exec
77
include $(CLEAR_VARS)
88

99
LOCAL_MODULE := AndKittyInjector
1010

1111
# add -DkITTYMEMORY_DEBUG for debug outputs
12-
LOCAL_CPPFLAGS += -std=c++17 -DkNO_KEYSTONE
12+
# use logcat logging to get outputs in realtime
13+
LOCAL_CPPFLAGS += -std=c++17 -DkNO_KEYSTONE #-DkUSE_LOGCAT -DkITTYMEMORY_DEBUG
1314

14-
LOCAL_SRC_FILES := src/main.cpp $(wildcard src/Injector/*.cpp) $(KITTYMEMORY_SRC)
15+
LOCAL_C_INCLUDES += $(KITTYMEMORY_PATH)
1516

16-
LOCAL_C_INCLUDES += $(KITTYMEMORY_PATH)/../
17+
PROJ_SRC = $(wildcard $(LOCAL_PATH)/src/*.cpp) $(wildcard $(LOCAL_PATH)/src/Injector/*.cpp)
18+
LOCAL_SRC_FILES := $(PROJ_SRC) $(KITTYMEMORY_SRC)
1719

1820
include $(BUILD_EXECUTABLE)
3.77 KB
Binary file not shown.
2.51 KB
Binary file not shown.
2.8 KB
Binary file not shown.
3.83 KB
Binary file not shown.

AndKittyInjector/runtest.bat

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@ECHO OFF
2+
3+
SET "INJECTOR_NAME=AndKittyInjector"
4+
SET "INJECTOR_PATH=/data/local/tmp/AndKittyInjector"
5+
6+
SET "APP=com.kiloo.subwaysurf"
7+
8+
:: test lib prints hello world to ( logcat -s "KittyMemoryEx" )
9+
SET "LIB_ARCH=arm64"
10+
SET "LIB_PATH=/data/local/tmp/injtest.so"
11+
12+
ECHO INJECTOR_ARCH = %INJECTOR_ARCH%
13+
ECHO APP = %APP%
14+
ECHO LIB_ARCH = %LIB_ARCH%
15+
ECHO LIB_PATH = %LIB_PATH%
16+
17+
IF "%LIB_ARCH%"=="arm" adb push injtest/armeabi-v7a/libinjtest.so %LIB_PATH%
18+
IF "%LIB_ARCH%"=="arm64" adb push injtest/arm64-v8a/libinjtest.so %LIB_PATH%
19+
IF "%LIB_ARCH%"=="x86" adb push injtest/x86/libinjtest.so %LIB_PATH%
20+
IF "%LIB_ARCH%"=="x86_64" adb push injtest/x86_64/libinjtest.so %LIB_PATH%
21+
22+
ECHO =========== INJECTOR ===========
23+
24+
adb shell "su -c 'kill $(pidof %INJECTOR_PATH%) > /dev/null 2>&1'"
25+
26+
:: exec perm
27+
adb shell "su -c 'chmod 755 %INJECTOR_PATH%'"
28+
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'"
31+
32+
ECHO ========= CHECKING MAPS =========
33+
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'"
36+
37+
PAUSE

AndKittyInjector/src/Injector/KittyInjector.cpp

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,6 @@
22

33
bool KittyInjector::init(pid_t pid, EKittyMemOP eMemOp)
44
{
5-
bool isLocal64bit = !KittyMemoryEx::getMapsContain(getpid(), "/lib64/").empty();
6-
bool isRemote64bit = !KittyMemoryEx::getMapsContain(pid, "/lib64/").empty();
7-
if (isLocal64bit != isRemote64bit)
8-
{
9-
KITTY_LOGE("KittyInjector: Injector is %sbit but target app is %sbit.",
10-
isLocal64bit ? "64" : "32", isRemote64bit ? "64" : "32");
11-
return false;
12-
}
13-
145
if (_kMgr.get())
156
_kMgr.reset();
167

@@ -22,6 +13,15 @@ bool KittyInjector::init(pid_t pid, EKittyMemOP eMemOp)
2213
return false;
2314
}
2415

16+
bool isLocal64bit = !KittyMemoryEx::getMapsContain(getpid(), "/lib64/").empty();
17+
bool isRemote64bit = !KittyMemoryEx::getMapsContain(pid, "/lib64/").empty();
18+
if (isLocal64bit != isRemote64bit)
19+
{
20+
KITTY_LOGE("KittyInjector: Injector is %sbit but target app is %sbit.",
21+
isLocal64bit ? "64" : "32", isRemote64bit ? "64" : "32");
22+
return false;
23+
}
24+
2525
if (!_remote_syscall.init(_kMgr.get()))
2626
{
2727
KITTY_LOGE("KittyInjector: Failed to initialize remote syscall.");
@@ -57,18 +57,24 @@ bool KittyInjector::init(pid_t pid, EKittyMemOP eMemOp)
5757
return true;
5858
}
5959

60-
uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
60+
uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags, bool use_memfd_dl)
6161
{
6262
if (!_kMgr.get() || !_kMgr->isMemValid())
6363
{
6464
KITTY_LOGE("injectLibrary: Not initialized.");
6565
return 0;
6666
}
6767

68+
if (!_kMgr->trace.isAttached())
69+
{
70+
KITTY_LOGE("injectLibrary: Not attached.");
71+
return 0;
72+
}
73+
6874
errno = 0;
69-
bool useMemfd = _remote_dlopen_ext && !(syscall(syscall_memfd_create_n) < 0 && errno == ENOSYS);
75+
bool canUseMemfd = use_memfd_dl && _remote_dlopen_ext && !(syscall(syscall_memfd_create_n) < 0 && errno == ENOSYS);
7076

71-
if (!_remote_dlopen && !useMemfd)
77+
if (!_remote_dlopen && !canUseMemfd)
7278
{
7379
KITTY_LOGE("injectLibrary: remote dlopen not found.");
7480
return 0;
@@ -126,17 +132,11 @@ uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
126132
}
127133
}
128134

129-
if (!_kMgr->trace.Attach())
130-
{
131-
KITTY_LOGE("injectLibrary: Failed to attach.");
132-
return 0;
133-
}
134-
135135
uintptr_t remoteLibPath = _remote_syscall.rmmap_str(libPath);
136136
if (!remoteLibPath)
137137
{
138138
KITTY_LOGE("injectLibrary: mmaping lib name failed, errno = %s.",
139-
_remote_syscall.getRemoteError().c_str());
139+
_remote_syscall.getRemoteError().c_str());
140140
return 0;
141141
}
142142

@@ -145,7 +145,7 @@ uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
145145
// native dlopen
146146
if (libHdr.e_machine == kNativeEM)
147147
{
148-
if (useMemfd)
148+
if (canUseMemfd)
149149
{
150150
do
151151
{
@@ -159,7 +159,7 @@ uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
159159

160160
auto libBuf = libFile.toBuffer();
161161

162-
int rmemfd = _remote_syscall.rmemfd_create(rmemfd_name, MFD_CLOEXEC | MFD_ALLOW_SEALING, libBuf.size());
162+
int rmemfd = _remote_syscall.rmemfd_create(rmemfd_name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
163163
if (rmemfd <= 0)
164164
{
165165
KITTY_LOGE("injectLibrary: memfd_create failed, errno = %s.",
@@ -176,16 +176,7 @@ uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
176176
break;
177177
}
178178

179-
// mmap remote memfd in our process
180-
void *rshmem = mmap(nullptr, libBuf.size(), PROT_READ | PROT_WRITE, MAP_SHARED, rmemfdFile.FD(), 0);
181-
if (!rshmem)
182-
{
183-
KITTY_LOGE("injectLibrary: Failed to map shared memfd file, errno = %s.", strerror(errno));
184-
break;
185-
}
186-
// copy lib to remote memfd
187-
memcpy(rshmem, libBuf.data(), libBuf.size());
188-
munmap(rshmem, libBuf.size());
179+
libFile.writeToFd(rmemfdFile.FD());
189180

190181
// restrict further modifications to remote memfd
191182
_remote_syscall.rmemfd_seal(rmemfd, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
@@ -205,11 +196,11 @@ uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
205196

206197
if (!remoteContainsMap(memfd_rand))
207198
{
208-
if (useMemfd)
199+
if (canUseMemfd)
209200
KITTY_LOGW("android_dlopen_ext failed, using legacy dlopen...");
210201

211-
_kMgr->trace.callFunction(_remote_dlopen, 2, remoteLibPath, flags);
212-
kINJ_WAIT;
202+
_kMgr->trace.callFunction(_remote_dlopen, 2, remoteLibPath, flags);
203+
kINJ_WAIT;
213204
}
214205
}
215206
// bridge dlopen
@@ -305,7 +296,5 @@ uintptr_t KittyInjector::injectLibrary(std::string libPath, int flags)
305296
// cleanup
306297
_remote_syscall.clearAllocatedMaps();
307298

308-
_kMgr->trace.Detach();
309-
310299
return libBase;
311300
}

AndKittyInjector/src/Injector/KittyInjector.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include <KittyMemoryEx/KittyMemoryMgr.hpp>
3+
#include <KittyMemoryMgr.hpp>
44

55
#include <dlfcn.h>
66
#include <android/dlext.h>
@@ -55,5 +55,8 @@ class KittyInjector
5555
*/
5656
bool init(pid_t pid, EKittyMemOP eMemOp);
5757

58-
uintptr_t injectLibrary(std::string libPath, int flags);
58+
inline bool attach() { return _kMgr.get() && _kMgr->isMemValid() && _kMgr->trace.Attach(); };
59+
inline bool detach() { return _kMgr.get() && _kMgr->isMemValid() && _kMgr->trace.Detach(); }
60+
61+
uintptr_t injectLibrary(std::string libPath, int flags, bool use_dl_memfd);
5962
};

AndKittyInjector/src/Injector/RemoteSyscall.hpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,30 @@
44

55
#ifdef __aarch64__
66
#define syscall_fcntl_n 25
7-
#define syscall_ftruncate_n 46
87
#define syscall_mmap_n 222
98
#define syscall_munmap_n 215
109
#define syscall_memfd_create_n 279
1110
#elif __arm__
1211
#define syscall_fcntl_n 221 // fcntl64
13-
#define syscall_ftruncate_n 194 // ftruncate64
1412
//#define syscall_fcntl_n 55
15-
//#define syscall_ftruncate_n 93
1613
#define syscall_mmap_n 192 // mmap2
1714
#define syscall_munmap_n 91
1815
#define syscall_memfd_create_n 385
1916
#elif __i386__
2017
#define syscall_fcntl_n 55
21-
#define syscall_ftruncate_n 93
2218
#define syscall_mmap_n 192 // mmap2
2319
#define syscall_munmap_n 91
2420
#define syscall_memfd_create_n 356
2521
#elif __x86_64__
2622
#define syscall_fcntl_n 72
27-
#define syscall_ftruncate_n 77
2823
#define syscall_mmap_n 9
2924
#define syscall_munmap_n 11
3025
#define syscall_memfd_create_n 319
3126
#else
3227
#error "Unsupported ABI"
3328
#endif
3429

35-
#include <KittyMemoryEx/KittyMemoryMgr.hpp>
30+
#include <KittyMemoryMgr.hpp>
3631

3732
#define IsValidRetPtr(x) (uintptr_t(x) > 0 && uintptr_t(x) != uintptr_t(-1) && uintptr_t(x) != uintptr_t(-4) && uintptr_t(x) != uintptr_t(-8))
3833

@@ -135,16 +130,12 @@ class RemoteSyscall
135130
return remoteMem;
136131
}
137132

138-
int rmemfd_create(uintptr_t rname, unsigned int flags, size_t size)
133+
int rmemfd_create(uintptr_t rname, unsigned int flags)
139134
{
140135
if (!_kMgr || !_kMgr->isMemValid())
141136
return 0;
142137

143-
int rmemfd = _kMgr->trace.callFunction(_remote_syscall, 3, syscall_memfd_create_n, rname, flags);
144-
if (rmemfd > 0)
145-
_kMgr->trace.callFunction(_remote_syscall, 3, syscall_ftruncate_n, rmemfd, size);
146-
147-
return rmemfd;
138+
return _kMgr->trace.callFunction(_remote_syscall, 3, syscall_memfd_create_n, rname, flags);
148139
}
149140

150141
int rmemfd_seal(int rmemfd, unsigned long seals)

0 commit comments

Comments
 (0)