trainerbase-injector 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. trainerbase_injector-1.0.0/LICENSE +23 -0
  2. trainerbase_injector-1.0.0/MANIFEST.in +6 -0
  3. trainerbase_injector-1.0.0/PKG-INFO +60 -0
  4. trainerbase_injector-1.0.0/README.md +41 -0
  5. trainerbase_injector-1.0.0/injector/include/injector.h +245 -0
  6. trainerbase_injector-1.0.0/injector/src/linux/elf.c +619 -0
  7. trainerbase_injector-1.0.0/injector/src/linux/injector.c +389 -0
  8. trainerbase_injector-1.0.0/injector/src/linux/injector_internal.h +193 -0
  9. trainerbase_injector-1.0.0/injector/src/linux/ptrace.c +149 -0
  10. trainerbase_injector-1.0.0/injector/src/linux/remote_call.c +821 -0
  11. trainerbase_injector-1.0.0/injector/src/linux/shellcode.S +70 -0
  12. trainerbase_injector-1.0.0/injector/src/linux/util.c +82 -0
  13. trainerbase_injector-1.0.0/injector/src/macos/exc_handler.c +314 -0
  14. trainerbase_injector-1.0.0/injector/src/macos/injector.c +295 -0
  15. trainerbase_injector-1.0.0/injector/src/macos/injector_internal.h +121 -0
  16. trainerbase_injector-1.0.0/injector/src/macos/mach.c +112 -0
  17. trainerbase_injector-1.0.0/injector/src/macos/mach_exc.h +330 -0
  18. trainerbase_injector-1.0.0/injector/src/macos/mach_excServer.c +828 -0
  19. trainerbase_injector-1.0.0/injector/src/macos/ptrace.c +81 -0
  20. trainerbase_injector-1.0.0/injector/src/macos/remote_call.c +228 -0
  21. trainerbase_injector-1.0.0/injector/src/macos/util.c +155 -0
  22. trainerbase_injector-1.0.0/injector/src/windows/injector.c +859 -0
  23. trainerbase_injector-1.0.0/injector/util/ya_getopt.h +77 -0
  24. trainerbase_injector-1.0.0/setup.cfg +28 -0
  25. trainerbase_injector-1.0.0/setup.py +34 -0
  26. trainerbase_injector-1.0.0/tests/test_pyinjector.py +52 -0
  27. trainerbase_injector-1.0.0/trainerbase_injector/__init__.py +30 -0
  28. trainerbase_injector-1.0.0/trainerbase_injector/__main__.py +32 -0
  29. trainerbase_injector-1.0.0/trainerbase_injector/api.py +101 -0
  30. trainerbase_injector-1.0.0/trainerbase_injector/injector.c +176 -0
  31. trainerbase_injector-1.0.0/trainerbase_injector/injector.pyi +14 -0
  32. trainerbase_injector-1.0.0/trainerbase_injector.egg-info/PKG-INFO +60 -0
  33. trainerbase_injector-1.0.0/trainerbase_injector.egg-info/SOURCES.txt +36 -0
  34. trainerbase_injector-1.0.0/trainerbase_injector.egg-info/dependency_links.txt +1 -0
  35. trainerbase_injector-1.0.0/trainerbase_injector.egg-info/entry_points.txt +2 -0
  36. trainerbase_injector-1.0.0/trainerbase_injector.egg-info/not-zip-safe +1 -0
  37. trainerbase_injector-1.0.0/trainerbase_injector.egg-info/top_level.txt +1 -0
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Maor Kleinberger
4
+ Copyright (c) 2025 v01d
5
+ Copyright (c) 2025 Doomayka
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ # Must include all injector headers and source files, so the source distribution could be installed on any platform,
2
+ # regardless of the platform where it was built.
3
+ recursive-include injector *.h
4
+ recursive-include injector/src *.c
5
+ recursive-include injector/src *.S
6
+ include LICENSE
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: trainerbase-injector
3
+ Version: 1.0.0
4
+ Summary: A tool/library allowing dynamic library injection into running processes (fork)
5
+ Home-page: https://gitlab.com/python-trainers/trainerbase-injector
6
+ Author: v01d
7
+ Author-email: v01d@v01d.ru
8
+ Keywords: injection dll so library
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.13
16
+ Description-Content-Type: text/markdown; charset=UTF-8
17
+ License-File: LICENSE
18
+ Dynamic: license-file
19
+
20
+ # Trainerbase Injector (forked Pyinjector)
21
+
22
+ Forked from [kmaork's Pyinjector](https://github.com/kmaork/pyinjector) in order to support Python 3.13.
23
+
24
+ [![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/trainerbase-injector.svg)](https://pypi.python.org/pypi/trainerbase-injector/)
25
+ [![PyPI version](https://badge.fury.io/py/trainerbase-injector.svg)](https://badge.fury.io/py/trainerbase-injector)
26
+ [![Downloads](https://pepy.tech/badge/trainerbase-injector)](https://pepy.tech/project/trainerbase-injector)
27
+
28
+ A cross-platform tool/library allowing dynamic library injection into running processes.
29
+ If you are looking for a way to inject *python* code into a running process, try the [hypno](https://github.com/kmaork/hypno) library.
30
+
31
+ Trainerbase Injector has no external python dependencies.
32
+ It is implemented as a python wrapper for [kubo/injector](https://github.com/kubo/injector).
33
+
34
+ ## Installation
35
+
36
+ ```shell script
37
+ uv add trainerbase-injector
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### CLI
43
+
44
+ ```shell script
45
+ uv run inject <pid> <path/to/shared/library>
46
+ ```
47
+
48
+ ### API
49
+
50
+ ```python
51
+ from trainerbase_injector import inject
52
+
53
+ inject(pid, path_to_so_file)
54
+ ```
55
+
56
+ ## How it works
57
+
58
+ We build [kubo/injector](https://github.com/kubo/injector) as a C-extension and use its interface using `ctypes`.
59
+ [kubo/injector](https://github.com/kubo/injector) is an awesome repo allowing to inject shared libraries into running
60
+ processes both on Windows (`CreateRemoteThread`), Linux (`ptrace`), and Mac (`task_for_pid`).
@@ -0,0 +1,41 @@
1
+ # Trainerbase Injector (forked Pyinjector)
2
+
3
+ Forked from [kmaork's Pyinjector](https://github.com/kmaork/pyinjector) in order to support Python 3.13.
4
+
5
+ [![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/trainerbase-injector.svg)](https://pypi.python.org/pypi/trainerbase-injector/)
6
+ [![PyPI version](https://badge.fury.io/py/trainerbase-injector.svg)](https://badge.fury.io/py/trainerbase-injector)
7
+ [![Downloads](https://pepy.tech/badge/trainerbase-injector)](https://pepy.tech/project/trainerbase-injector)
8
+
9
+ A cross-platform tool/library allowing dynamic library injection into running processes.
10
+ If you are looking for a way to inject *python* code into a running process, try the [hypno](https://github.com/kmaork/hypno) library.
11
+
12
+ Trainerbase Injector has no external python dependencies.
13
+ It is implemented as a python wrapper for [kubo/injector](https://github.com/kubo/injector).
14
+
15
+ ## Installation
16
+
17
+ ```shell script
18
+ uv add trainerbase-injector
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### CLI
24
+
25
+ ```shell script
26
+ uv run inject <pid> <path/to/shared/library>
27
+ ```
28
+
29
+ ### API
30
+
31
+ ```python
32
+ from trainerbase_injector import inject
33
+
34
+ inject(pid, path_to_so_file)
35
+ ```
36
+
37
+ ## How it works
38
+
39
+ We build [kubo/injector](https://github.com/kubo/injector) as a C-extension and use its interface using `ctypes`.
40
+ [kubo/injector](https://github.com/kubo/injector) is an awesome repo allowing to inject shared libraries into running
41
+ processes both on Windows (`CreateRemoteThread`), Linux (`ptrace`), and Mac (`task_for_pid`).
@@ -0,0 +1,245 @@
1
+ /* -*- indent-tabs-mode: nil -*-
2
+ *
3
+ * injector - Library for injecting a shared library into a Linux process
4
+ *
5
+ * URL: https://github.com/kubo/injector
6
+ *
7
+ * ------------------------------------------------------
8
+ *
9
+ * Copyright (C) 2018-2023 Kubo Takehiro <kubo@jiubao.org>
10
+ *
11
+ * This library is free software; you can redistribute it and/or
12
+ * modify it under the terms of the GNU Lesser General Public
13
+ * License as published by the Free Software Foundation; either
14
+ * version 2.1 of the License, or (at your option) any later version.
15
+ *
16
+ * This library is distributed in the hope that it will be useful,
17
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
+ * Lesser General Public License for more details.
20
+ *
21
+ * You should have received a copy of the GNU Lesser General Public
22
+ * License along with this library; if not, write to the Free Software
23
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
+ */
25
+
26
+ /*!
27
+ * \file injector.h
28
+ * \brief Library for injecting a shared library into a Linux, Windows and macOS process
29
+ */
30
+ #ifndef INJECTOR_H
31
+ #define INJECTOR_H
32
+
33
+ #if defined(_WIN32)
34
+ #include <windows.h>
35
+ typedef DWORD injector_pid_t;
36
+ #else
37
+ #include <sys/types.h>
38
+
39
+ /*!
40
+ * \brief Platform-dependent process id type (\c pid_t on Unix. \c DWORD on Windows)
41
+ */
42
+ typedef pid_t injector_pid_t;
43
+ #endif
44
+
45
+ #ifdef __cplusplus
46
+ extern "C" {
47
+ #endif
48
+ #if 0
49
+ }
50
+ #endif
51
+
52
+ #define INJERR_SUCCESS 0 /* linux, windows, macos */
53
+ #define INJERR_OTHER -1 /* linux, windows, macos */
54
+ #define INJERR_NO_MEMORY -2 /* linux, windows, macos */
55
+ #define INJERR_NO_PROCESS -3 /* linux, windows, macos */
56
+ #define INJERR_NO_LIBRARY -4 /* linux */
57
+ #define INJERR_NO_FUNCTION -4 /* linux */
58
+ #define INJERR_ERROR_IN_TARGET -5 /* linux, windows, macos */
59
+ #define INJERR_FILE_NOT_FOUND -6 /* linux, windows, macos */
60
+ #define INJERR_INVALID_MEMORY_AREA -7 /* linux, macos */
61
+ #define INJERR_PERMISSION -8 /* linux, windows, macos */
62
+ #define INJERR_UNSUPPORTED_TARGET -9 /* linux, windows, macos */
63
+ #define INJERR_INVALID_ELF_FORMAT -10 /* linux */
64
+ #define INJERR_WAIT_TRACEE -11 /* linux */
65
+ #define INJERR_FUNCTION_MISSING -12 /* linux, windows, macos */
66
+
67
+ typedef struct injector injector_t;
68
+
69
+ /*!
70
+ * \brief Attach to the specified process.
71
+ * \param[out] injector the address where the newly created injector handle will be stored
72
+ * \param[in] pid the process id to be attached
73
+ * \return zero on success. Otherwise, error code
74
+ */
75
+ int injector_attach(injector_t **injector, injector_pid_t pid);
76
+
77
+ /*!
78
+ * \brief Detach from the attached process and destroy the specified handle.
79
+ * \param[in] injector the injector handle to destroy
80
+ * \return zero on success. Otherwise, error code
81
+ */
82
+ int injector_detach(injector_t *injector);
83
+
84
+ /*!
85
+ * \brief Inject the specified shared library into the target process.
86
+ * \param[in] injector the injector handle specifying the target process
87
+ * \param[in] path the path name of the shared library
88
+ * \param[out] handle the address where the newly created module handle will be stored
89
+ * \return zero on success. Otherwise, error code
90
+ *
91
+ * Note on Linux:
92
+ * This calls functions inside of the target process interrupted by \c ptrace().
93
+ * If the target process is interrupted while holding a non-reentrant lock and
94
+ * injector calls a function requiring the same lock, the process stops forever.
95
+ * If the lock type is reentrant, the status guarded by the lock may become inconsistent.
96
+ * As far as I checked, \c dlopen() internally calls \c malloc() requiring non-reentrant
97
+ * locks. \c dlopen() also uses a reentrant lock to guard information about loaded files.
98
+ */
99
+ int injector_inject(injector_t *injector, const char *path, void **handle);
100
+
101
+ /*!
102
+ * \brief Uninject the shared library specified by \c handle.
103
+ * \param[in] injector the injector handle specifying the target process
104
+ * \param[in] handle the module handle created by \c injector_inject
105
+ * \return zero on success. Otherwise, error code
106
+ * \remarks This fearute isn't supported for musl-libc processes.
107
+ * See [Functional differences from glibc](https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading_libraries).
108
+ */
109
+ int injector_uninject(injector_t *injector, void *handle);
110
+
111
+ #if defined(INJECTOR_DOC) || defined(__linux__) || defined(__APPLE__)
112
+ /*!
113
+ * \brief Call the specified function taking no arguments in the target process (Linux and macOS only)
114
+ * \param[in] injector the injector handle specifying the target process
115
+ * \param[in] handle the module handle created by \c injector_inject or special-handles such as \c RTLD_DEFAULT
116
+ * \param[in] name the function name
117
+ *
118
+ * The \c handle and \c name arguments are passed to \c dlsym ([Linux](https://man7.org/linux/man-pages/man3/dlvsym.3.html), [macOS](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html)) and then the return value of \c dlsym is called without arguments in the target process.
119
+ *
120
+ * This is same with the combination of injector_remote_func_addr() and injector_remote_call() without extra arguments.
121
+ *
122
+ * \note
123
+ * (Linux only)
124
+ * If the function in the target process internally calls non-[async-signal-safe]((https://man7.org/linux/man-pages/man7/signal-safety.7.html))
125
+ * functions, it may stop the target process or cause unexpected behaviour.
126
+ * \sa injector_remote_func_addr(), injector_remote_call(), injector_remote_vcall()
127
+ */
128
+ int injector_call(injector_t *injector, void *handle, const char* name);
129
+ #endif
130
+
131
+ /*!
132
+ * \brief Get the message of the last error.
133
+ * \remarks The message is updated only when \c injector functions return non-zero.
134
+ */
135
+ const char *injector_error(void);
136
+
137
+ #if defined(INJECTOR_DOC) || defined(__linux__) || defined(_WIN32)
138
+ #define INJECTOR_HAS_REMOTE_CALL_FUNCS 1
139
+ #include <stdarg.h>
140
+ #include <stdint.h>
141
+
142
+ /*!
143
+ * \brief Get the function address in the target process (Linux and Windows only)
144
+ * \param[in] injector the injector handle specifying the target process
145
+ * \param[in] handle the module handle created by \c injector_inject or special-handles such as \c RTLD_DEFAULT
146
+ * \param[in] name the function name
147
+ * \param[out] func_addr_out the address where the function address in the target process will be stored
148
+ * \return zero on success. Otherwise, error code
149
+ *
150
+ * \b Example
151
+ *
152
+ * Inject libfoo.so and then call foo_func(1, 2, 3) in it.
153
+ * \code
154
+ * void *handle;
155
+ * // inject libfoo.so and get the handle
156
+ * if (injector_inject(injector, "libfoo.so", &handle) != 0) {
157
+ * return;
158
+ * }
159
+ * size_t func_addr;
160
+ * // get the address of foo_func in the handle
161
+ * if (injector_remote_func_addr(injector, handle, "foo_func", &func_addr) != 0) {
162
+ * return;
163
+ * }
164
+ * intptr_t retval;
165
+ * // call foo_func
166
+ * if (injector_remote_call(injector, &retval, func_addr, 1, 2, 3) != 0) {
167
+ * return;
168
+ * }
169
+ * printf("The return value of foo_func(1, 2, 3) is %ld.\n", retval);
170
+ * \endcode
171
+ */
172
+ int injector_remote_func_addr(injector_t *injector, void *handle, const char* name, size_t *func_addr_out);
173
+
174
+ /*!
175
+ * \brief Call the function in the target process (Linux and Windows only)
176
+ * \param[in] injector the injector handle specifying the target process
177
+ * \param[out] retval \c NULL or the address where the return value of the function call will be stored
178
+ * \param[in] func_addr the function address in the target process
179
+ * \param[in] ... arguments passed to the function
180
+ * \return zero on success. Otherwise, error code
181
+ * \remarks
182
+ * The types of the arguments must be integer or pointer.
183
+ * If it is a pointer, it must point to a valid address in the target process.
184
+ * The number of arguments must be less than or equal to six.
185
+ * \note
186
+ * If the function in the target process internally calls non-[async-signal-safe]((https://man7.org/linux/man-pages/man7/signal-safety.7.html))
187
+ * functions, it may stop the target process or cause unexpected behaviour.
188
+ * \sa injector_remote_func_addr(), injector_remote_vcall()
189
+ */
190
+ int injector_remote_call(injector_t *injector, intptr_t *retval, size_t func_addr, ...);
191
+
192
+ /*!
193
+ * \brief Call the function in the target process (Linux and Windows only)
194
+ * \param[in] injector the injector handle specifying the target process
195
+ * \param[out] retval \c NULL or the address where the return value of the function call will be stored
196
+ * \param[in] func_addr the function address in the target process
197
+ * \param[in] ap arguments passed to the function
198
+ * \return zero on success. Otherwise, error code
199
+ * \remarks
200
+ * The types of the arguments must be integer or pointer.
201
+ * If it is a pointer, it must point to a valid address in the target process.
202
+ * The number of arguments must be less than or equal to six.
203
+ * \note
204
+ * If the function in the target process internally calls non-[async-signal-safe]((https://man7.org/linux/man-pages/man7/signal-safety.7.html))
205
+ * functions, it may stop the target process or cause unexpected behaviour.
206
+ * \sa injector_remote_func_addr(), injector_remote_call()
207
+ */
208
+ int injector_remote_vcall(injector_t *injector, intptr_t *retval, size_t func_addr, va_list ap);
209
+ #endif
210
+
211
+ #if defined(INJECTOR_DOC) || defined(_WIN32)
212
+ /*!
213
+ * \brief Same with \c injector_inject except the type of the \c path argument. (Windows only)
214
+ * \param[in] injector the injector handle specifying the target process
215
+ * \param[in] path the path name of the shared library
216
+ * \param[out] handle the address where the newly created module handle will be stored
217
+ * \return zero on success. Otherwise, error code
218
+ */
219
+ int injector_inject_w(injector_t *injector, const wchar_t *path, void **handle);
220
+ #endif
221
+
222
+ #if defined(INJECTOR_DOC) || (defined(__linux__) && defined(__x86_64__))
223
+ #define INJECTOR_HAS_INJECT_IN_CLONED_THREAD 1 // feature test macro
224
+ /*!
225
+ * \brief Inject the specified shared library into the target process by the \c clone system call. (Linux x86_64 only)
226
+ * \param[in] injector the injector handle specifying the target process
227
+ * \param[in] path the path name of the shared library
228
+ * \param[out] handle the address where the newly created module handle will be stored
229
+ * \return zero on success. Otherwise, error code
230
+ *
231
+ * This calls `dlopen()` in a thread created by \c [clone()](https://man7.org/linux/man-pages/man2/clone.2.html). Note that no wonder there are unexpected
232
+ * pitfalls because some resources allocated in \c [pthread_create()](https://man7.org/linux/man-pages/man3/pthread_create.3.html) lack in the \c clone()-ed thread.
233
+ * Use it at your own risk.
234
+ */
235
+ int injector_inject_in_cloned_thread(injector_t *injector, const char *path, void **handle);
236
+ #endif
237
+
238
+ #if 0
239
+ {
240
+ #endif
241
+ #ifdef __cplusplus
242
+ }; /* extern "C" */
243
+ #endif
244
+
245
+ #endif