Skip to content

Commit 2518fa7

Browse files
committed
Refine protect_pytransform function
1 parent 96e4094 commit 2518fa7

File tree

2 files changed

+41
-85
lines changed

2 files changed

+41
-85
lines changed

docs/security.rst

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -104,67 +104,48 @@ need to inserted into the script. Here is sample code::
104104
from hashlib import md5
105105

106106
MD5SUM_LIB_PYTRANSFORM = 'ca202268bbd76ffe7df10c9ef1edcb6c'
107-
108107
CO_SELF_SIZES = 46, 36
109-
CO_DECORATOR_SIZES = 135, 122, 89, 86, 60
110-
CO_DLLMETHOD_SIZES = 22, 19, 16
111-
CO_LOAD_LIBRARY_SIZES = 662, 648, 646, 634, 628, 456
112-
CO_PYARMOR_INIT_SIZES = 58, 56, 40
113-
CO_PYARMOR_RUNTIME_SIZES = 146, 144, 138, 127, 121, 108
114-
CO_INIT_PYTRANSFORM_SIZES = 83, 80, 58
115-
CO_INIT_RUNTIME_SIZES = 74, 52
116-
117108
CO_SELF_NAMES = ('pytransform', 'pyarmor_runtime', '__pyarmor__', '__name__', '__file__')
118-
CO_DECORATOR_NAMES = ('isinstance', 'str', 'encode', 'int', '_get_error_msg', 'PytransformError')
119-
CO_DLLMETHOD_NAMES = ()
120-
CO_LOAD_LIBRARY_NAMES = ('None', 'os', 'path', 'dirname', '__file__', 'normpath', 'platform', 'system',
121-
'lower', 'abspath', 'join', 'PytransformError', 'exists', 'struct', 'calcsize',
122-
'encode', 'format_platname', 'basename', 'cdll', 'LoadLibrary', 'Exception', 'set_option',
123-
'sys', 'byteorder', 'c_char_p', '_debug_mode')
124-
CO_PYARMOR_INIT_NAMES = ('_pytransform', 'None', '_load_library', 'get_error_msg', '_get_error_msg', 'c_char_p', 'restype', 'init_pytransform')
125-
CO_PYARMOR_RUNTIME_NAMES = ('_pytransform', 'None', 'PytransformError', 'pyarmor_init', 'init_runtime', 'print', 'sys', 'exit')
126-
CO_INIT_PYTRANSFORM_NAMES = ('sys', 'version_info', 'PYFUNCTYPE', 'c_int', 'c_void_p', '_pytransform', 'pythonapi', '_handle')
127-
CO_INIT_RUNTIME_NAMES = ('pyarmor_init', 'PYFUNCTYPE', 'c_int', '_pytransform')
109+
CO_PYTRANSFORM_NAMES = ('Exception', 'LoadLibrary', 'None', 'PYFUNCTYPE',
110+
'PytransformError', '__file__', '_debug_mode',
111+
'_get_error_msg', '_handle', '_load_library',
112+
'_pytransform', 'abspath', 'basename', 'byteorder',
113+
'c_char_p', 'c_int', 'c_void_p', 'calcsize', 'cdll',
114+
'dirname', 'encode', 'exists', 'exit',
115+
'format_platname', 'init_pytransform', 'init_runtime',
116+
'int', 'isinstance', 'join', 'lower', 'normpath', 'os',
117+
'path', 'platform', 'print', 'pyarmor_init',
118+
'pythonapi', 'restype', 'set_option', 'str', 'struct',
119+
'sys', 'system', 'version_info')
128120

129121
def check_lib_pytransform(filename):
130122
expected = MD5SUM_LIB_PYTRANSFORM
131123
with open(filename, 'rb') as f:
132124
if not md5(f.read()).hexdigest() == expected:
133125
sys.exit(1)
134126

135-
def check_code_object(f_code, sizes, names):
136-
return set(f_code.co_names) <= set(names) and len(f_code.co_code) in sizes
137-
138127
def check_obfuscated_script():
139128
co = sys._getframe(3).f_code
140-
if not check_code_object(co, CO_SELF_SIZES, CO_SELF_NAMES):
129+
if not (set(co.co_names) <= set(CO_SELF_NAMES) and len(f_code.co_code) in CO_SELF_SIZES):
141130
sys.exit(1)
142131

143132
def check_mod_pytransform():
144133
code = '__code__' if sys.version_info[0] == 3 else 'func_code'
145134
closure = '__closure__' if sys.version_info[0] == 3 else 'func_closure'
146135

147136
co = getattr(pytransform.dllmethod, code).co_consts[1]
148-
if not check_code_object(co, CO_DECORATOR_SIZES, CO_DECORATOR_NAMES):
137+
if not (set(co.co_names) < set(CO_PYTRANSFORM_NAMES)):
149138
sys.exit(1)
150139

151-
for item in [
152-
('dllmethod', CO_DLLMETHOD_SIZES, CO_DLLMETHOD_NAMES),
153-
('init_pytransform', CO_DECORATOR_SIZES, CO_DECORATOR_NAMES),
154-
('init_runtime', CO_DECORATOR_SIZES, CO_DECORATOR_NAMES),
155-
('_load_library', CO_LOAD_LIBRARY_SIZES, CO_LOAD_LIBRARY_NAMES),
156-
('pyarmor_init', CO_PYARMOR_INIT_SIZES, CO_PYARMOR_INIT_NAMES),
157-
('pyarmor_runtime', CO_PYARMOR_RUNTIME_SIZES, CO_PYARMOR_RUNTIME_NAMES)]:
158-
co = getattr(getattr(pytransform, item[0]), code)
159-
if not check_code_object(co, item[1], item[2]):
140+
for name in ('dllmethod', 'init_pytransform', 'init_runtime', '_load_library', 'pyarmor_init', 'pyarmor_runtime'):
141+
co = getattr(getattr(pytransform, name), code)
142+
if not (set(co.co_names) < set(CO_PYTRANSFORM_NAMES)):
160143
sys.exit(1)
161144

162-
for item in [
163-
('init_pytransform', CO_INIT_PYTRANSFORM_SIZES, CO_INIT_PYTRANSFORM_NAMES),
164-
('init_runtime', CO_INIT_RUNTIME_SIZES, CO_INIT_RUNTIME_NAMES)]:
145+
for item in ('init_pytransform', 'init_runtime'):
165146
co_closures = getattr(getattr(pytransform, item[0]), closure)
166147
co = getattr(co_closures[0].cell_contents, code)
167-
if not check_code_object(co, item[1], item[2]):
148+
if not (set(co.co_names) < set(CO_PYTRANSFORM_NAMES)):
168149
sys.exit(1)
169150

170151
def protect_pytransform():

src/examples/helloworld/foo.py

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,19 @@
2121
}
2222

2323
CO_SELF_SIZES = 46, 36
24-
CO_DECORATOR_SIZES = 135, 122, 89, 86, 60
25-
CO_DLLMETHOD_SIZES = 22, 19, 16
26-
CO_LOAD_LIBRARY_SIZES = 662, 648, 646, 634, 628, 456
27-
CO_PYARMOR_INIT_SIZES = 58, 56, 40
28-
CO_PYARMOR_RUNTIME_SIZES = 146, 144, 138, 127, 121, 108
29-
CO_INIT_PYTRANSFORM_SIZES = 83, 80, 58
30-
CO_INIT_RUNTIME_SIZES = 74, 52
31-
3224
CO_SELF_NAMES = ('pytransform', 'pyarmor_runtime', '__pyarmor__',
3325
'__name__', '__file__')
34-
CO_DECORATOR_NAMES = ('isinstance', 'str', 'encode', 'int',
35-
'_get_error_msg', 'PytransformError')
36-
CO_DLLMETHOD_NAMES = ()
37-
CO_LOAD_LIBRARY_NAMES = ('None', 'os', 'path', 'dirname', '__file__',
38-
'normpath', 'platform', 'system', 'lower',
39-
'abspath', 'join', 'PytransformError', 'exists',
40-
'struct', 'calcsize', 'encode', 'format_platname',
41-
'basename', 'cdll', 'LoadLibrary', 'Exception',
42-
'set_option', 'sys', 'byteorder', 'c_char_p',
43-
'_debug_mode')
44-
CO_PYARMOR_INIT_NAMES = ('_pytransform', 'None', '_load_library',
45-
'get_error_msg', '_get_error_msg', 'c_char_p',
46-
'restype', 'init_pytransform')
47-
CO_PYARMOR_RUNTIME_NAMES = ('_pytransform', 'None', 'PytransformError',
48-
'pyarmor_init', 'init_runtime', 'print', 'sys',
49-
'exit')
50-
CO_INIT_PYTRANSFORM_NAMES = ('sys', 'version_info', 'PYFUNCTYPE', 'c_int',
51-
'c_void_p', '_pytransform', 'pythonapi', '_handle')
52-
CO_INIT_RUNTIME_NAMES = ('pyarmor_init', 'PYFUNCTYPE', 'c_int', '_pytransform')
26+
CO_PYTRANSFORM_NAMES = ('Exception', 'LoadLibrary', 'None', 'PYFUNCTYPE',
27+
'PytransformError', '__file__', '_debug_mode',
28+
'_get_error_msg', '_handle', '_load_library',
29+
'_pytransform', 'abspath', 'basename', 'byteorder',
30+
'c_char_p', 'c_int', 'c_void_p', 'calcsize', 'cdll',
31+
'dirname', 'encode', 'exists', 'exit',
32+
'format_platname', 'init_pytransform', 'init_runtime',
33+
'int', 'isinstance', 'join', 'lower', 'normpath', 'os',
34+
'path', 'platform', 'print', 'pyarmor_init',
35+
'pythonapi', 'restype', 'set_option', 'str', 'struct',
36+
'sys', 'system', 'version_info')
5337

5438
def check_lib_pytransform(filename):
5539
print("Check md5sum for %s..." % filename)
@@ -60,13 +44,11 @@ def check_lib_pytransform(filename):
6044
sys.exit(1)
6145
print("Check OK.")
6246

63-
def check_code_object(f_code, sizes, names):
64-
return set(f_code.co_names) <= set(names) and len(f_code.co_code) in sizes
65-
6647
def check_obfuscated_script():
6748
print('Check obfuscated script %s ...' % __file__)
6849
co = sys._getframe(3).f_code
69-
if not check_code_object(co, CO_SELF_SIZES, CO_SELF_NAMES):
50+
if not (set(co.co_names) <= set(CO_SELF_NAMES)
51+
and len(f_code.co_code) in CO_SELF_SIZES):
7052
print('Obfuscated script has been changed by others')
7153
sys.exit(1)
7254
print('Check OK.')
@@ -77,32 +59,25 @@ def check_mod_pytransform():
7759

7860
print('Check decorator dllmethod ...')
7961
co = getattr(pytransform.dllmethod, code).co_consts[1]
80-
if not check_code_object(co, CO_DECORATOR_SIZES, CO_DECORATOR_NAMES):
62+
if not (set(co.co_names) < set(CO_PYTRANSFORM_NAMES)):
8163
print('Check failed')
8264
sys.exit(1)
8365
print('Check OK.')
8466

85-
for item in [
86-
('dllmethod', CO_DLLMETHOD_SIZES, CO_DLLMETHOD_NAMES),
87-
('init_pytransform', CO_DECORATOR_SIZES, CO_DECORATOR_NAMES),
88-
('init_runtime', CO_DECORATOR_SIZES, CO_DECORATOR_NAMES),
89-
('_load_library', CO_LOAD_LIBRARY_SIZES, CO_LOAD_LIBRARY_NAMES),
90-
('pyarmor_init', CO_PYARMOR_INIT_SIZES, CO_PYARMOR_INIT_NAMES),
91-
('pyarmor_runtime', CO_PYARMOR_RUNTIME_SIZES, CO_PYARMOR_RUNTIME_NAMES)]:
92-
print('Check function %s ...' % item[0])
93-
co = getattr(getattr(pytransform, item[0]), code)
94-
if not check_code_object(co, item[1], item[2]):
67+
for name in ('dllmethod', 'init_pytransform', 'init_runtime',
68+
'_load_library', 'pyarmor_init', 'pyarmor_runtime'):
69+
print('Check function %s ...' % name)
70+
co = getattr(getattr(pytransform, name), code)
71+
if not (set(co.co_names) < set(CO_PYTRANSFORM_NAMES)):
9572
print('Check failed')
9673
sys.exit(1)
9774
print('Check OK.')
9875

99-
for item in [
100-
('init_pytransform', CO_INIT_PYTRANSFORM_SIZES, CO_INIT_PYTRANSFORM_NAMES),
101-
('init_runtime', CO_INIT_RUNTIME_SIZES, CO_INIT_RUNTIME_NAMES)]:
102-
print('Check wrapped function %s ...' % item[0])
103-
co_closures = getattr(getattr(pytransform, item[0]), closure)
76+
for name in ('init_pytransform', 'init_runtime'):
77+
print('Check wrapped function %s ...' % name)
78+
co_closures = getattr(getattr(pytransform, name), closure)
10479
co = getattr(co_closures[0].cell_contents, code)
105-
if not check_code_object(co, item[1], item[2]):
80+
if not (set(co.co_names) < set(CO_PYTRANSFORM_NAMES)):
10681
print('Check failed')
10782
sys.exit(1)
10883
print('Check OK.')

0 commit comments

Comments
 (0)