pyarmor 8.4.4__zip → 8.4.5__zip
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.
- {pyarmor-8.4.4 → pyarmor-8.4.5}/PKG-INFO +8 -14
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/README.rst +6 -12
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/__init__.py +1 -1
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/context.py +10 -1
- pyarmor-8.4.5/pyarmor/cli/core.data.1 +0 -0
- pyarmor-8.4.5/pyarmor/cli/core.data.2 +0 -0
- pyarmor-8.4.5/pyarmor/cli/core.data.3 +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/default.cfg +2 -2
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/docker.py +25 -6
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/register.py +16 -4
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/resource.py +10 -4
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/config.py +1 -1
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor.egg-info/PKG-INFO +8 -14
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor.egg-info/SOURCES.txt +0 -1
- {pyarmor-8.4.4 → pyarmor-8.4.5}/setup.py +2 -0
- pyarmor-8.4.4/pyarmor/cli/core.data.1 +0 -0
- pyarmor-8.4.4/pyarmor/cli/core.data.2 +0 -0
- pyarmor-8.4.4/pyarmor/cli/core.data.3 +0 -0
- pyarmor-8.4.4/pyarmor/cli/group.py +0 -101
- {pyarmor-8.4.4 → pyarmor-8.4.5}/MANIFEST.in +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/README.md +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/__init__.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/benchmark.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/build_meta.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/__main__.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/bootstrap.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/config.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/generate.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/merge.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/mixer.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/plugin.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/public_capsule.zip +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/repack.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cli/shell.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/cobuilder.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/README-ZH.md +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/README.md +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/build-for-exe.bat +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/build-for-freeze.bat +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/build-with-project.bat +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/build-with-project.sh +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/cx_Freeze/hello.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/cx_Freeze/queens.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/cx_Freeze/setup.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/helloworld/foo.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/obfuscate-app.bat +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/obfuscate-app.sh +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/obfuscate-pkg.bat +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/obfuscate-pkg.sh +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pack-obfuscated-scripts.bat +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pack-obfuscated-scripts.sh +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/py2exe/hello.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/py2exe/queens.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/py2exe/setup.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Arithmetic.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Calls.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/CommandLine.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Constructs.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Dict.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Exceptions.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Imports.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Instances.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Lists.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Lookups.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/NewInstances.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Numbers.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Setup.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Strings.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/Tuples.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/With.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/clockres.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/package/__init__.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/package/submodule.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/pybench.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/pybench/systimes.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/simple/queens.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/testmod/hello.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/testmod/queens.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/testpkg/main.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/testpkg/mypkg/__init__.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/examples/testpkg/mypkg/foo.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/__init__.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/build_data_module.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/buildext.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/get_bind_key.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/get_license_info.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/get_platform_name.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/merge.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/repack.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/helper/superuntime.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/license.tri +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/packer.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/platforms/darwin/x86_64/_pytransform.dylib +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/platforms/linux/x86/_pytransform.so +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/platforms/linux/x86_64/_pytransform.so +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/platforms/windows/x86/_pytransform.dll +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/platforms/windows/x86_64/_pytransform.dll +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/plugins/README.md +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/plugins/check_ntp_time.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/polyfills/__init__.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/polyfills/argparse.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/product.key +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/project.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/protect_code.pt +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/protect_code2.pt +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/public.key +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/public_capsule.zip +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pyarmor-deprecated.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pyarmor-webui.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pyarmor.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pyimcore.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pyshield.key +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pyshield.lic +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/pytransform.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/reform.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/register.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/sppmode.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor/utils.py +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor.egg-info/dependency_links.txt +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor.egg-info/entry_points.txt +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor.egg-info/requires.txt +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/pyarmor.egg-info/top_level.txt +0 -0
- {pyarmor-8.4.4 → pyarmor-8.4.5}/setup.cfg +0 -0
|
@@ -1,36 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: pyarmor
|
|
3
|
-
Version: 8.4.
|
|
3
|
+
Version: 8.4.5
|
|
4
4
|
Summary: A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
5
5
|
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
6
|
Author: Jondy Zhao
|
|
7
7
|
Author-email: pyarmor@163.com
|
|
8
|
-
License:
|
|
8
|
+
License: Free To Use But Restricted
|
|
9
9
|
Description: Protect Python Scripts By Pyarmor
|
|
10
10
|
=================================
|
|
11
11
|
|
|
12
|
-
Pyarmor is a command line tool used to obfuscate python scripts, bind
|
|
13
|
-
obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
12
|
+
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
14
13
|
|
|
15
14
|
Key Features
|
|
16
15
|
------------
|
|
17
16
|
|
|
18
|
-
* The obfuscated scritpt is still a normal `.py` script, in most of
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
performance
|
|
23
|
-
* Rename functions/methods/classes/variables/arguments, irreversible
|
|
24
|
-
obfuscation
|
|
25
|
-
* Convert part of Python functions to C function, compile to binary by
|
|
26
|
-
high optimize option, irreversible obfuscation
|
|
17
|
+
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
18
|
+
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
19
|
+
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
20
|
+
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
27
21
|
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
28
22
|
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
29
23
|
|
|
30
24
|
Support Platforms
|
|
31
25
|
-----------------
|
|
32
26
|
|
|
33
|
-
* Python 3.7~3.
|
|
27
|
+
* Python 3.7~3.12
|
|
34
28
|
* Windows
|
|
35
29
|
* Many linuxs, include embedded systems
|
|
36
30
|
* Apple Intel and Apple Silicon
|
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
Protect Python Scripts By Pyarmor
|
|
2
2
|
=================================
|
|
3
3
|
|
|
4
|
-
Pyarmor is a command line tool used to obfuscate python scripts, bind
|
|
5
|
-
obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
4
|
+
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
6
5
|
|
|
7
6
|
Key Features
|
|
8
7
|
------------
|
|
9
8
|
|
|
10
|
-
* The obfuscated scritpt is still a normal `.py` script, in most of
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
performance
|
|
15
|
-
* Rename functions/methods/classes/variables/arguments, irreversible
|
|
16
|
-
obfuscation
|
|
17
|
-
* Convert part of Python functions to C function, compile to binary by
|
|
18
|
-
high optimize option, irreversible obfuscation
|
|
9
|
+
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
10
|
+
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
11
|
+
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
12
|
+
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
19
13
|
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
20
14
|
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
21
15
|
|
|
22
16
|
Support Platforms
|
|
23
17
|
-----------------
|
|
24
18
|
|
|
25
|
-
* Python 3.7~3.
|
|
19
|
+
* Python 3.7~3.12
|
|
26
20
|
* Windows
|
|
27
21
|
* Many linuxs, include embedded systems
|
|
28
22
|
* Apple Intel and Apple Silicon
|
|
@@ -100,6 +100,7 @@ def format_platform(plat, arch):
|
|
|
100
100
|
('windows', ('windows', 'cygwin*')),
|
|
101
101
|
('darwin', ('darwin',)),
|
|
102
102
|
('linux', ('linux*',)),
|
|
103
|
+
('freebsd', ('freebsd*', 'openbsd*', 'isilon onefs')),
|
|
103
104
|
)
|
|
104
105
|
|
|
105
106
|
arch_table = (
|
|
@@ -124,6 +125,9 @@ def format_platform(plat, arch):
|
|
|
124
125
|
else:
|
|
125
126
|
raise RuntimeError('unsupported arch "%s"' % arch)
|
|
126
127
|
|
|
128
|
+
if plat == 'linux' and hasattr(sys, 'getandroidapilevel'):
|
|
129
|
+
plat = 'android'
|
|
130
|
+
|
|
127
131
|
if plat == 'windows' and mach == 'x86_64':
|
|
128
132
|
bitness = calcsize('P'.encode()) * 8
|
|
129
133
|
if bitness == 32:
|
|
@@ -199,7 +203,12 @@ class Context(object):
|
|
|
199
203
|
|
|
200
204
|
def save_token(self, data):
|
|
201
205
|
with open(self.license_token, 'wb') as f:
|
|
202
|
-
|
|
206
|
+
if data.endswith(b'=='):
|
|
207
|
+
f.write(data)
|
|
208
|
+
else:
|
|
209
|
+
n = data.rfind(b'==')
|
|
210
|
+
assert n > 0
|
|
211
|
+
f.write(data[:n+2])
|
|
203
212
|
|
|
204
213
|
def clear_token(self):
|
|
205
214
|
if os.path.exists(self.license_token):
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -35,27 +35,46 @@ class DockerAuthHandler(socketserver.BaseRequestHandler):
|
|
|
35
35
|
self.request.send(struct.pack('!HH', 1, len(msg)) + msg)
|
|
36
36
|
|
|
37
37
|
def process(self, packet):
|
|
38
|
-
|
|
38
|
+
cmd = packet[:4]
|
|
39
|
+
if cmd == b'PADH':
|
|
39
40
|
response = b'\n'.join(CONFIG['machid']) + b'\x00'
|
|
40
41
|
self.request.send(response)
|
|
41
|
-
|
|
42
|
-
userdata =
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
elif cmd == b'PADI':
|
|
43
|
+
userdata = packet[4:].decode('utf-8')
|
|
44
|
+
rtkey = self.generate_outer_key(userdata, outer=False)
|
|
45
|
+
magic = b'DockerRuntimeKey'
|
|
46
|
+
response = magic + struct.pack('!HH', 0, len(rtkey)) + rtkey
|
|
47
|
+
self.request.send(response)
|
|
48
|
+
elif cmd == b'PADK':
|
|
49
|
+
userdata = self.parse_packet(packet).decode('utf-8')
|
|
50
|
+
rtkey = self.generate_runtime_key(userdata)
|
|
51
|
+
response = struct.pack('!HH', 0, len(rtkey)) + rtkey
|
|
45
52
|
self.request.send(response)
|
|
53
|
+
else:
|
|
54
|
+
raise RuntimeError('unknown packet %r' % packet)
|
|
46
55
|
return response
|
|
47
56
|
|
|
48
57
|
def parse_packet(self, packet):
|
|
49
58
|
if len(packet) == 32 and packet[:4] == b'PADK':
|
|
50
59
|
return packet[12:]
|
|
51
|
-
raise RuntimeError('invalid auth request')
|
|
60
|
+
raise RuntimeError('invalid auth request: %r' % packet)
|
|
52
61
|
|
|
53
62
|
def generate_runtime_key(self, userdata):
|
|
54
63
|
ctx = CONFIG['ctx']
|
|
55
64
|
ctx.cmd_options['user_data'] = userdata
|
|
65
|
+
ctx.cmd_options['expired'] = '.3'
|
|
66
|
+
ctx.cmd_options['outer'] = 0
|
|
56
67
|
Pytransform3._pytransform3.init_ctx(ctx)
|
|
57
68
|
return Pytransform3.generate_runtime_key(ctx)
|
|
58
69
|
|
|
70
|
+
def generate_outer_key(self, userdata, outer=True):
|
|
71
|
+
ctx = CONFIG['ctx']
|
|
72
|
+
ctx.cmd_options['user_data'] = userdata
|
|
73
|
+
ctx.cmd_options['expired'] = '.3'
|
|
74
|
+
ctx.cmd_options['outer'] = 1
|
|
75
|
+
Pytransform3._pytransform3.init_ctx(ctx)
|
|
76
|
+
return Pytransform3.generate_runtime_key(ctx, outer=outer)
|
|
77
|
+
|
|
59
78
|
|
|
60
79
|
def register_pyarmor(ctx, regfile):
|
|
61
80
|
reg = Register(ctx)
|
|
@@ -111,9 +111,10 @@ class Register(object):
|
|
|
111
111
|
|
|
112
112
|
def update_token(self):
|
|
113
113
|
from .core import Pytransform3
|
|
114
|
+
assert Pytransform3._pytransform3 is None
|
|
114
115
|
with open(self.ctx.license_token, 'wb') as f:
|
|
115
116
|
f.close()
|
|
116
|
-
Pytransform3.
|
|
117
|
+
Pytransform3.init(self.ctx)
|
|
117
118
|
|
|
118
119
|
@property
|
|
119
120
|
def license_info(self):
|
|
@@ -318,7 +319,8 @@ $notes
|
|
|
318
319
|
if lictype == 'trial':
|
|
319
320
|
self.notes.append('* Can\'t obfuscate big script and mix str')
|
|
320
321
|
elif lictype in ('bacic', 'pro'):
|
|
321
|
-
self.notes.append('*
|
|
322
|
+
self.notes.append('* Need verify license online '
|
|
323
|
+
'when obfuscating scripts')
|
|
322
324
|
elif lictype == 'group':
|
|
323
325
|
self.notes.append('* Offline obfuscation')
|
|
324
326
|
|
|
@@ -369,10 +371,16 @@ class WebRegister(Register):
|
|
|
369
371
|
logger.debug('remove old token')
|
|
370
372
|
os.remove(self.ctx.license_token)
|
|
371
373
|
|
|
374
|
+
def _check_product_name(self, name):
|
|
375
|
+
if len(name) == 1 or name.count(name[0]) == len(name):
|
|
376
|
+
raise RuntimeError('invalid product name "%s"' % name)
|
|
377
|
+
|
|
372
378
|
def prepare(self, keyfile, product, upgrade=False):
|
|
373
379
|
reginfo = self.parse_keyfile(keyfile)
|
|
374
380
|
logger.info('prepare "%s"', keyfile)
|
|
375
381
|
|
|
382
|
+
self._check_product_name(product)
|
|
383
|
+
|
|
376
384
|
rcode = self._get_old_rcode() if upgrade else None
|
|
377
385
|
if upgrade and not rcode and keyfile.endswith('regcode-to-pro.txt'):
|
|
378
386
|
logger.error('please use `pyarmor-7 -v` to check old license')
|
|
@@ -395,7 +403,7 @@ class WebRegister(Register):
|
|
|
395
403
|
if pname in ('', 'TBD'):
|
|
396
404
|
info['product'] = product
|
|
397
405
|
elif pname != product:
|
|
398
|
-
logger.warning('this license
|
|
406
|
+
logger.warning('this license has bound to product "%s"', pname)
|
|
399
407
|
logger.warning('it can not be changed to "%s"', product)
|
|
400
408
|
|
|
401
409
|
lines = []
|
|
@@ -427,7 +435,7 @@ class WebRegister(Register):
|
|
|
427
435
|
])
|
|
428
436
|
if info['product'] == 'non-profits':
|
|
429
437
|
lines.append('This license is about to be used for non-profits')
|
|
430
|
-
|
|
438
|
+
if info['product'] in ('', 'TBD'):
|
|
431
439
|
lines.append('This license is bind to non-profits(TBD) '
|
|
432
440
|
'for the time being')
|
|
433
441
|
lines.append('If not change "TBD" to product name in 6 months, '
|
|
@@ -435,6 +443,10 @@ class WebRegister(Register):
|
|
|
435
443
|
else:
|
|
436
444
|
lines.append('This license is about to be used for product "%s"'
|
|
437
445
|
% info['product'])
|
|
446
|
+
if info['product'] not in ('', 'TBD'):
|
|
447
|
+
lines.append('')
|
|
448
|
+
lines.append('IMPORTANT: PRODUCT NAME CAN NOT BE CHANGED '
|
|
449
|
+
'AFTER INITIAL REGISTRATION')
|
|
438
450
|
|
|
439
451
|
lines.extend(['', ''])
|
|
440
452
|
return info, '\n'.join(lines)
|
|
@@ -78,6 +78,8 @@ class FileResource(Resource):
|
|
|
78
78
|
self.mtree = None
|
|
79
79
|
self.mco = None
|
|
80
80
|
|
|
81
|
+
self.shebang = ''
|
|
82
|
+
|
|
81
83
|
# Do not touch these nodes in final protector
|
|
82
84
|
self.exclude_nodes = set()
|
|
83
85
|
# Do not touch these code objects in final patcher
|
|
@@ -131,7 +133,10 @@ class FileResource(Resource):
|
|
|
131
133
|
|
|
132
134
|
with open(self.fullpath, encoding=self._get_encoding(encoding)) as f:
|
|
133
135
|
# file.read() can't read the whole data of big files
|
|
134
|
-
|
|
136
|
+
lines = f.readlines()
|
|
137
|
+
if lines and lines[0].startswith('#!'):
|
|
138
|
+
self.shebang = lines[0]
|
|
139
|
+
return lines
|
|
135
140
|
|
|
136
141
|
def reparse(self, lines=None, encoding=None):
|
|
137
142
|
if lines is None:
|
|
@@ -149,7 +154,7 @@ class FileResource(Resource):
|
|
|
149
154
|
|
|
150
155
|
if mtree is None:
|
|
151
156
|
mtree = self.mtree
|
|
152
|
-
assert mtree is not None
|
|
157
|
+
assert (mtree is not None)
|
|
153
158
|
self.mco = compile(mtree, self.frozenname, 'exec', optimize=optimize)
|
|
154
159
|
|
|
155
160
|
def clean(self):
|
|
@@ -168,19 +173,20 @@ class FileResource(Resource):
|
|
|
168
173
|
elif relative == 1:
|
|
169
174
|
prefix = '.' * self.fullname.count('.')
|
|
170
175
|
else:
|
|
171
|
-
assert(isinstance(relative, str))
|
|
176
|
+
assert (isinstance(relative, str))
|
|
172
177
|
prefix = relative + '.'
|
|
173
178
|
if self.fullname.startswith(prefix):
|
|
174
179
|
prefix = '.' * self.fullname.count('.')
|
|
175
180
|
elif prefix.startswith(self.pkgname + '.'):
|
|
176
181
|
prefix = prefix[len(self.pkgname):]
|
|
177
182
|
|
|
178
|
-
|
|
183
|
+
source = Template(tpl).safe_substitute(
|
|
179
184
|
timestamp=datetime.now().isoformat(),
|
|
180
185
|
package=prefix + pkgname,
|
|
181
186
|
path=bootpath,
|
|
182
187
|
code=repr(code),
|
|
183
188
|
rev=rev)
|
|
189
|
+
return (self.shebang + source) if self.shebang else source
|
|
184
190
|
|
|
185
191
|
|
|
186
192
|
class PycResource(FileResource):
|
|
@@ -1,36 +1,30 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: pyarmor
|
|
3
|
-
Version: 8.4.
|
|
3
|
+
Version: 8.4.5
|
|
4
4
|
Summary: A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
5
5
|
Home-page: https://github.com/dashingsoft/pyarmor
|
|
6
6
|
Author: Jondy Zhao
|
|
7
7
|
Author-email: pyarmor@163.com
|
|
8
|
-
License:
|
|
8
|
+
License: Free To Use But Restricted
|
|
9
9
|
Description: Protect Python Scripts By Pyarmor
|
|
10
10
|
=================================
|
|
11
11
|
|
|
12
|
-
Pyarmor is a command line tool used to obfuscate python scripts, bind
|
|
13
|
-
obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
12
|
+
Pyarmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.
|
|
14
13
|
|
|
15
14
|
Key Features
|
|
16
15
|
------------
|
|
17
16
|
|
|
18
|
-
* The obfuscated scritpt is still a normal `.py` script, in most of
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
performance
|
|
23
|
-
* Rename functions/methods/classes/variables/arguments, irreversible
|
|
24
|
-
obfuscation
|
|
25
|
-
* Convert part of Python functions to C function, compile to binary by
|
|
26
|
-
high optimize option, irreversible obfuscation
|
|
17
|
+
* The obfuscated scritpt is still a normal `.py` script, in most of cases the original python scripts can be replaced with obfuscated scripts seamlessly.
|
|
18
|
+
* Provide many ways to obfuscate the scripts to balance security and performance
|
|
19
|
+
* Rename functions/methods/classes/variables/arguments, irreversible obfuscation
|
|
20
|
+
* Convert part of Python functions to C function, compile to binary by high optimize option, irreversible obfuscation
|
|
27
21
|
* Bind obfuscated scripts to fixed machine or expire obfuscted scripts
|
|
28
22
|
* Protect obfuscated scripts by Themida (Only for Windows)
|
|
29
23
|
|
|
30
24
|
Support Platforms
|
|
31
25
|
-----------------
|
|
32
26
|
|
|
33
|
-
* Python 3.7~3.
|
|
27
|
+
* Python 3.7~3.12
|
|
34
28
|
* Windows
|
|
35
29
|
* Many linuxs, include embedded systems
|
|
36
30
|
* Apple Intel and Apple Silicon
|
|
@@ -63,6 +63,8 @@ setup(
|
|
|
63
63
|
' scripts to fixed machine or expire obfuscated scripts.',
|
|
64
64
|
long_description=long_description,
|
|
65
65
|
|
|
66
|
+
license='Free To Use But Restricted',
|
|
67
|
+
|
|
66
68
|
url='https://github.com/dashingsoft/pyarmor',
|
|
67
69
|
author='Jondy Zhao',
|
|
68
70
|
author_email='pyarmor@163.com',
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import logging
|
|
3
|
-
import os
|
|
4
|
-
import socketserver
|
|
5
|
-
import struct
|
|
6
|
-
import sys
|
|
7
|
-
|
|
8
|
-
from .context import Context
|
|
9
|
-
from .generate import Builder, Pytransform3
|
|
10
|
-
from .register import Register
|
|
11
|
-
|
|
12
|
-
PORT = 29092
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class DockerAuthHandler(socketserver.BaseRequestHandler):
|
|
16
|
-
|
|
17
|
-
WORKPATH = os.path.expanduser(os.path.join('~', '.pyarmor', 'docker'))
|
|
18
|
-
CTX = None
|
|
19
|
-
|
|
20
|
-
def handle(self):
|
|
21
|
-
data = self.request.recv(64)
|
|
22
|
-
logging.info('receive request from %s', self.client_address)
|
|
23
|
-
try:
|
|
24
|
-
logging.debug('data (%d): %s', len(data), data)
|
|
25
|
-
self.process(data)
|
|
26
|
-
logging.info('send auth result to %s', self.client_address)
|
|
27
|
-
except Exception as e:
|
|
28
|
-
logging.error('%s', str(e))
|
|
29
|
-
msg = 'failed to verify docker, please check host console'.encode()
|
|
30
|
-
msg += b'\00'
|
|
31
|
-
self.request.send(struct.pack('!HH', 1, len(msg)) + msg)
|
|
32
|
-
|
|
33
|
-
def process(self, packet):
|
|
34
|
-
if packet[:4] == b'PADH':
|
|
35
|
-
self.request.send(self.MACHID)
|
|
36
|
-
else:
|
|
37
|
-
userdata = self.parse_packet(packet)
|
|
38
|
-
keydata = self.generate_runtime_key(userdata.decode('utf-8'))
|
|
39
|
-
self.request.send(struct.pack('!HH', 0, len(keydata)) + keydata)
|
|
40
|
-
|
|
41
|
-
def parse_packet(self, packet):
|
|
42
|
-
if len(packet) == 32 and packet[:4] == b'PADK':
|
|
43
|
-
return packet[12:]
|
|
44
|
-
raise RuntimeError('invalid auth request')
|
|
45
|
-
|
|
46
|
-
def generate_runtime_key(self, userdata):
|
|
47
|
-
ctx = self.CTX
|
|
48
|
-
ctx.cmd_options['user_data'] = userdata
|
|
49
|
-
return Builder(ctx).generate_runtime_key()
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def register_pyarmor(ctx, regfile):
|
|
53
|
-
reg = Register(ctx)
|
|
54
|
-
logging.info('register "%s"', regfile)
|
|
55
|
-
reg.register_regfile(regfile)
|
|
56
|
-
if reg.license_info['features'] < 15:
|
|
57
|
-
raise RuntimeError('this feature is only for group license')
|
|
58
|
-
|
|
59
|
-
machid = reg._get_machine_id()
|
|
60
|
-
logging.debug('machine id: %s', machid)
|
|
61
|
-
DockerAuthHandler.MACHID = machid
|
|
62
|
-
|
|
63
|
-
Pytransform3._update_token(ctx)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def main_entry():
|
|
67
|
-
parser = argparse.ArgumentParser()
|
|
68
|
-
parser.add_argument('-p', '--port', type=int, default=PORT)
|
|
69
|
-
parser.add_argument('-s', '--sock', default='/var/run/docker.sock',
|
|
70
|
-
help=argparse.SUPPRESS)
|
|
71
|
-
parser.add_argument('--home', help=argparse.SUPPRESS)
|
|
72
|
-
parser.add_argument('regfile', nargs=1,
|
|
73
|
-
help='group device registration file for this machine')
|
|
74
|
-
args = parser.parse_args(sys.argv[1:])
|
|
75
|
-
|
|
76
|
-
home = DockerAuthHandler.WORKPATH
|
|
77
|
-
if args.home:
|
|
78
|
-
DockerAuthHandler.WORKPATH = args.home
|
|
79
|
-
home = args.home
|
|
80
|
-
logging.info('work path: %s', home)
|
|
81
|
-
|
|
82
|
-
ctx = Context(home=os.path.expanduser(home))
|
|
83
|
-
register_pyarmor(ctx, args.regfile[0])
|
|
84
|
-
DockerAuthHandler.CTX = ctx
|
|
85
|
-
|
|
86
|
-
host, port = '0.0.0.0', args.port
|
|
87
|
-
with socketserver.TCPServer((host, port), DockerAuthHandler) as server:
|
|
88
|
-
logging.info('listen docker auth request on %s:%s', host, args.port)
|
|
89
|
-
server.serve_forever()
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def main():
|
|
93
|
-
logging.basicConfig(
|
|
94
|
-
level=logging.INFO,
|
|
95
|
-
format='%(asctime)s: %(message)s',
|
|
96
|
-
)
|
|
97
|
-
main_entry()
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if __name__ == '__main__':
|
|
101
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|