PyQBDI 0.11.0__cp38-cp38-win_amd64.whl → 0.12.0__cp38-cp38-win_amd64.whl
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.
Potentially problematic release.
This version of PyQBDI might be problematic. Click here for more details.
- {PyQBDI-0.11.0.dist-info → pyqbdi-0.12.0.dist-info}/LICENSE.txt +1 -1
- {PyQBDI-0.11.0.dist-info → pyqbdi-0.12.0.dist-info}/METADATA +13 -16
- pyqbdi-0.12.0.dist-info/RECORD +9 -0
- {PyQBDI-0.11.0.dist-info → pyqbdi-0.12.0.dist-info}/WHEEL +1 -1
- pyqbdi.pyd +0 -0
- pyqbdiWinPreloader.exe +0 -0
- pyqbdipreload.py +160 -0
- pyqbdipreloadlib.cp38-win_amd64.pyd +0 -0
- PyQBDI-0.11.0.dist-info/RECORD +0 -6
- {PyQBDI-0.11.0.dist-info → pyqbdi-0.12.0.dist-info}/top_level.txt +0 -0
|
@@ -210,7 +210,7 @@ QBDI source code is under the Apache License v2.0
|
|
|
210
210
|
same "printed page" as the copyright notice for easier
|
|
211
211
|
identification within third-party archives.
|
|
212
212
|
|
|
213
|
-
Copyright 2017 -
|
|
213
|
+
Copyright 2017 - 2025 Quarkslab
|
|
214
214
|
|
|
215
215
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
216
216
|
you may not use this file except in compliance with the License.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyQBDI
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: Python binding for QBDI
|
|
5
5
|
Author: Nicolas Surbayrole
|
|
6
6
|
Author-email: qbdi@quarkslab.com
|
|
@@ -9,7 +9,6 @@ Project-URL: Documentation, https://qbdi.readthedocs.io/
|
|
|
9
9
|
Project-URL: Source, https://github.com/QBDI/QBDI
|
|
10
10
|
Project-URL: Homepage, https://qbdi.quarkslab.com/
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
12
|
Classifier: Operating System :: Microsoft :: Windows
|
|
14
13
|
Classifier: Operating System :: MacOS
|
|
15
14
|
Classifier: Operating System :: POSIX :: Linux
|
|
@@ -19,6 +18,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
23
|
Classifier: Topic :: Security
|
|
23
24
|
Classifier: Topic :: Software Development :: Debuggers
|
|
24
25
|
Requires-Python: >=3.8
|
|
@@ -66,16 +67,16 @@ Status
|
|
|
66
67
|
.. role:: orange
|
|
67
68
|
.. role:: red
|
|
68
69
|
|
|
69
|
-
======= ==============================
|
|
70
|
-
CPU Operating Systems Execution
|
|
71
|
-
======= ==============================
|
|
72
|
-
x86-64 Android, Linux, macOS, Windows :green:`Supported`
|
|
73
|
-
x86 Android, Linux, macOS, Windows :green:`Supported`
|
|
74
|
-
ARM Android, Linux :
|
|
75
|
-
AArch64 Android, Linux, macOS
|
|
76
|
-
======= ==============================
|
|
70
|
+
======= ============================== ================== =========================
|
|
71
|
+
CPU Operating Systems Execution Memory Access Information
|
|
72
|
+
======= ============================== ================== =========================
|
|
73
|
+
x86-64 Android, Linux, macOS, Windows :green:`Supported` :green:`Supported`
|
|
74
|
+
x86 Android, Linux, macOS, Windows :green:`Supported` :green:`Supported`
|
|
75
|
+
ARM Android, Linux :green:`Supported` :green:`Supported`
|
|
76
|
+
AArch64 Android, Linux, macOS, IOs (*) :green:`Supported` :green:`Supported`
|
|
77
|
+
======= ============================== ================== =========================
|
|
77
78
|
|
|
78
|
-
\*
|
|
79
|
+
\* IOs support is unstable and need a jailbroken device.
|
|
79
80
|
|
|
80
81
|
Installation
|
|
81
82
|
============
|
|
@@ -94,11 +95,7 @@ Devel packages
|
|
|
94
95
|
|
|
95
96
|
There is no strict development timeline or scheduled release plan for the QBDI project.
|
|
96
97
|
All the new features and fixes are merged onto the ``dev-next`` branch.
|
|
97
|
-
Devel packages can be downloaded in the artefacts of
|
|
98
|
-
|
|
99
|
-
- `Github Actions <https://github.com/QBDI/QBDI/actions/workflows/python_linux.yml?query=branch%3Adev-next>`__ for Linux PyQBDI
|
|
100
|
-
- `Github Actions <https://github.com/QBDI/QBDI/actions/workflows/python_osx.yml?query=branch%3Adev-next>`__ for OSX PyQBDI
|
|
101
|
-
- `Github Actions <https://github.com/QBDI/QBDI/actions/workflows/python_windows.yml?query=branch%3Adev-next>`__ for windows PyQBDI
|
|
98
|
+
Devel packages can be downloaded in the artefacts of `Github Actions <https://github.com/QBDI/QBDI/actions/workflows/python.yml?query=branch%3Adev-next>`__.
|
|
102
99
|
|
|
103
100
|
Compilation
|
|
104
101
|
===========
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pyqbdi.pyd,sha256=RpWVWYqiiqo_YuBYqbM3Qm_YFJeOqlhYmcJfgsfmkHg,7683072
|
|
2
|
+
pyqbdiWinPreloader.exe,sha256=CljHgeukMqLiLOpn_Y-azDW435Bsx0shyT7ipYASNt8,13824
|
|
3
|
+
pyqbdipreload.py,sha256=hANOaHha85XUt4Kub8f2lsKZhIErsfkKNAq4O6PZ3lA,5814
|
|
4
|
+
pyqbdipreloadlib.cp38-win_amd64.pyd,sha256=NTrAIreDzgJtr-bKg7k42borQip6tqC76OyhcOP_f4Y,7698944
|
|
5
|
+
pyqbdi-0.12.0.dist-info/LICENSE.txt,sha256=gOUvR_mAOk85D4IBVtoFVh5kieG_u0_0yKXHcETHd34,12687
|
|
6
|
+
pyqbdi-0.12.0.dist-info/METADATA,sha256=rt49sozAd2e1cpT30Q4We4CqHdaSdHEmeQPQ0eUnakc,4978
|
|
7
|
+
pyqbdi-0.12.0.dist-info/WHEEL,sha256=2M046GvC9RLU1f1TWyM-2sB7cRKLhAC7ucAFK8l8f24,99
|
|
8
|
+
pyqbdi-0.12.0.dist-info/top_level.txt,sha256=vaVfPcyi2OkulsN7QdaZiIKzq2GbFV2q24OujHZlbRc,7
|
|
9
|
+
pyqbdi-0.12.0.dist-info/RECORD,,
|
pyqbdi.pyd
CHANGED
|
Binary file
|
pyqbdiWinPreloader.exe
ADDED
|
Binary file
|
pyqbdipreload.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# This file is part of pyQBDI (python binding for QBDI).
|
|
4
|
+
#
|
|
5
|
+
# Copyright 2017 - 2025 Quarkslab
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
|
|
19
|
+
import platform
|
|
20
|
+
import pyqbdi
|
|
21
|
+
from ctypes import util as ctypesutil
|
|
22
|
+
import sys
|
|
23
|
+
import os
|
|
24
|
+
import argparse
|
|
25
|
+
import subprocess
|
|
26
|
+
|
|
27
|
+
def get_preloadlib():
|
|
28
|
+
if platform.system() == 'Windows':
|
|
29
|
+
import importlib
|
|
30
|
+
# ['.py', '.pyw', '.pyc', '.cp310-win_amd64.pyd', '.pyd']
|
|
31
|
+
# find correct extension on windows like .cp310-win_amd64.pyd
|
|
32
|
+
for ext in importlib.machinery.all_suffixes():
|
|
33
|
+
preloadlib = os.path.join(
|
|
34
|
+
os.path.dirname(pyqbdi.__file__),
|
|
35
|
+
f"pyqbdipreloadlib{ext}")
|
|
36
|
+
if os.path.isfile(preloadlib):
|
|
37
|
+
return preloadlib
|
|
38
|
+
else:
|
|
39
|
+
preloadlib = os.path.join(
|
|
40
|
+
os.path.dirname(pyqbdi.__file__),
|
|
41
|
+
os.path.basename(pyqbdi.__file__).replace("pyqbdi", "pyqbdipreloadlib"))
|
|
42
|
+
|
|
43
|
+
if not os.path.isfile(preloadlib):
|
|
44
|
+
print("Cannot find pyqbdi preload library : {}".format(preloadlib))
|
|
45
|
+
exit(1)
|
|
46
|
+
return preloadlib
|
|
47
|
+
|
|
48
|
+
def find_binary(environ, binary, canFail=False):
|
|
49
|
+
# https://docs.python.org/3.8/library/os.html#os.execve:
|
|
50
|
+
# "execve will not use the PATH variable to locate the executable; path must contain an appropriate absolute or relative path."
|
|
51
|
+
# seach the binary path in PATH if needed
|
|
52
|
+
binarypath = None
|
|
53
|
+
if '/' in binary or '\\' in binary:
|
|
54
|
+
# absolute or relative path
|
|
55
|
+
binarypath = binary
|
|
56
|
+
else:
|
|
57
|
+
if os.path.isfile(binary): # case for current dir on windows
|
|
58
|
+
return binary
|
|
59
|
+
if "PATH" in environ:
|
|
60
|
+
for p in environ["PATH"].split(os.pathsep):
|
|
61
|
+
if os.path.isfile(os.path.join(p, binary)):
|
|
62
|
+
binarypath = os.path.join(p, binary)
|
|
63
|
+
break
|
|
64
|
+
|
|
65
|
+
if not binarypath or not os.path.isfile(binarypath):
|
|
66
|
+
if canFail:
|
|
67
|
+
return None
|
|
68
|
+
print("Cannot find binary {} make sure its in your PATH env".format(binary))
|
|
69
|
+
exit(1)
|
|
70
|
+
|
|
71
|
+
return binarypath
|
|
72
|
+
|
|
73
|
+
def find_windows_inject_binary(environ):
|
|
74
|
+
|
|
75
|
+
listPreloader = [
|
|
76
|
+
os.path.join(os.path.dirname(pyqbdi.__file__), "pyqbdiWinPreloader.exe"),
|
|
77
|
+
"QBDIWinPreloader.exe"]
|
|
78
|
+
|
|
79
|
+
for binary in listPreloader:
|
|
80
|
+
binarypath = find_binary(environ, binary, True)
|
|
81
|
+
if binarypath is not None:
|
|
82
|
+
return binarypath
|
|
83
|
+
|
|
84
|
+
print("Cannot find Windows injector binary (within {}), make sure one of them are available".format(listPreloader))
|
|
85
|
+
exit(1)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def run():
|
|
89
|
+
|
|
90
|
+
parser = argparse.ArgumentParser()
|
|
91
|
+
|
|
92
|
+
parser.add_argument("script", type=str, help="PyQBDI script")
|
|
93
|
+
parser.add_argument("target", type=str, help="command to instrument")
|
|
94
|
+
parser.add_argument("args", type=str, help="command arguments", nargs='*')
|
|
95
|
+
|
|
96
|
+
args = parser.parse_args()
|
|
97
|
+
|
|
98
|
+
script = args.script
|
|
99
|
+
binary = args.target
|
|
100
|
+
execargs = [args.target] + args.args
|
|
101
|
+
environ = os.environ.copy()
|
|
102
|
+
|
|
103
|
+
preloadlib = get_preloadlib()
|
|
104
|
+
binarypath = find_binary(environ, binary)
|
|
105
|
+
|
|
106
|
+
# add LD_PRELOAD or DYLD_INSERT_LIBRARIES
|
|
107
|
+
if platform.system() == 'Darwin':
|
|
108
|
+
|
|
109
|
+
environ["DYLD_INSERT_LIBRARIES"] = preloadlib
|
|
110
|
+
environ["DYLD_LIBRARY_PATH"] = os.path.join(sys.base_prefix, 'lib')
|
|
111
|
+
environ["DYLD_BIND_AT_LAUNCH"] = "1"
|
|
112
|
+
elif platform.system() == 'Linux':
|
|
113
|
+
libpythonname = "python{}.{}".format(
|
|
114
|
+
sys.version_info.major, sys.version_info.minor)
|
|
115
|
+
libpython = ctypesutil.find_library(libpythonname)
|
|
116
|
+
if not libpython:
|
|
117
|
+
libpythonname = "python{}.{}{}".format(
|
|
118
|
+
sys.version_info.major, sys.version_info.minor, sys.abiflags)
|
|
119
|
+
libpython = ctypesutil.find_library(libpythonname)
|
|
120
|
+
if not libpython:
|
|
121
|
+
print("PyQBDI in PRELOAD mode need lib{}.so".format(libpythonname))
|
|
122
|
+
exit(1)
|
|
123
|
+
|
|
124
|
+
for s in [libpython, preloadlib]:
|
|
125
|
+
for c in [" ", ";", os.pathsep]:
|
|
126
|
+
if c in s:
|
|
127
|
+
print(f"Error: found character '{c}' in {s}")
|
|
128
|
+
print(f"PyQBDIPrelaod is based on ld.so, which didn't accept '{c}' in LD_PRELOAD.")
|
|
129
|
+
print("Please check your installation to avoid ' ' and ';' in file path")
|
|
130
|
+
exit(1)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
environ["LD_PRELOAD"] = os.pathsep.join([libpython, preloadlib])
|
|
134
|
+
environ["LD_BIND_NOW"] = "1"
|
|
135
|
+
elif platform.system() == 'Windows':
|
|
136
|
+
targetbinary = binarypath
|
|
137
|
+
binarypath = find_windows_inject_binary(environ)
|
|
138
|
+
execargs = [binarypath, preloadlib, targetbinary] + execargs[1:]
|
|
139
|
+
else:
|
|
140
|
+
print("PyQBDI in PRELOAD mode is not supported on this platform")
|
|
141
|
+
exit(1)
|
|
142
|
+
|
|
143
|
+
# add PYQBDI_TOOL
|
|
144
|
+
if not os.path.isfile(script):
|
|
145
|
+
print("Cannot find {} script".format(script))
|
|
146
|
+
exit(1)
|
|
147
|
+
else:
|
|
148
|
+
environ["PYQBDI_TOOL"] = script
|
|
149
|
+
|
|
150
|
+
if platform.system() == 'Windows':
|
|
151
|
+
proc = subprocess.run(execargs, env=environ)
|
|
152
|
+
exit(proc.returncode)
|
|
153
|
+
else:
|
|
154
|
+
os.execve(binarypath, execargs, environ)
|
|
155
|
+
print("Fail execve")
|
|
156
|
+
exit(1)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
if __name__ == "__main__":
|
|
160
|
+
run()
|
|
Binary file
|
PyQBDI-0.11.0.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
pyqbdi.pyd,sha256=7P4JtPMc3jIvKBfxSZc_BaXSgJ6gi010YMAgiHJEX_s,6753792
|
|
2
|
-
PyQBDI-0.11.0.dist-info/LICENSE.txt,sha256=c3MbxkvPUYAKDGu3vKCTHdPE6ehviH0FoB1M3bYTBwM,12687
|
|
3
|
-
PyQBDI-0.11.0.dist-info/METADATA,sha256=Uf-zANEM6e2Sjka9sURk9AxV_ymjpG6ngJURpx1_eGk,5325
|
|
4
|
-
PyQBDI-0.11.0.dist-info/WHEEL,sha256=Wb4yjwIXVKEpht4JWFUZNCzpG7JLBNZnqtK2YNdqLkI,100
|
|
5
|
-
PyQBDI-0.11.0.dist-info/top_level.txt,sha256=vaVfPcyi2OkulsN7QdaZiIKzq2GbFV2q24OujHZlbRc,7
|
|
6
|
-
PyQBDI-0.11.0.dist-info/RECORD,,
|
|
File without changes
|