Skip to content

Commit

Permalink
Using hook script in pack
Browse files Browse the repository at this point in the history
  • Loading branch information
jondy committed May 9, 2023
1 parent 8142a61 commit ed4afea
Showing 1 changed file with 65 additions and 3 deletions.
68 changes: 65 additions & 3 deletions docs/how-to/protection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

.. program:: pyarmor gen

Pyarmor focus on protecting Python scripts, by several irreversible obfuscation methods, now Pyarmor make sure the obfuscated scripts can't be restored by any way.
Pyarmor focus on protecting Python scripts, by several irreversible obfuscation methods, now Pyarmor makes sure the obfuscated scripts can't be restored by any way.

But it isn't good at memory protection and anti-debug. If you care about runtime memory data, or runtime key verification, generally it need extra methods to prevent debugger from hacking dynamic libraries.

Pyarmor could make sure hacker can't get runtime data by valid Python C API and other Python ways, only if Python interpreter and extension module ``pyarmor_runtime`` are not hacked. This is what extra tools need to do, the common methods include
Pyarmor could prevent hacker from querying runtime data by valid Python C API and other Python ways, only if Python interpreter and extension module ``pyarmor_runtime`` are not hacked. This is what extra tools need to protect, the common methods include

- Signing the binary file to make sure they're not changed by others
- Using third-party binary protection tools to protect Python interpreter and extension module ``pyarmor_runtime``
Expand Down Expand Up @@ -50,13 +50,75 @@ Available external tools: codesign, VMProtect
.. [#] Do not use ``check_interp`` in 32-bit x86 platforms, it doesn't work
**Hook Scripts**

Expert users could write :term:`hook script` to check PyInstaller bootstrap modules to improve security.

Here it's an example to show how to do, note that it may not work in different PyInstaller version, do not use it directly.

.. code-block:: python
:linenos:
:emphasize-lines: 12-14
# Hook script ".pyarmor/hooks/foo.py"
def protect_self():
from sys import modules
def check_module(name, checklist):
m = modules[name]
for attr, value in checklist.items():
if value != sum(getattr(m, attr).__code__.co_code):
raise RuntimeError('unexpected %s' % m)
checklist__frozen_importlib = {}
checklist__frozen_importlib_external = {}
checklist_pyimod03_importers = {}
check_module('_frozen_importlib', checklist__frozen_importlib)
check_module('_frozen_importlib_external', checklist__frozen_importlib_external)
check_module('pyimod03_importers', checklist_pyimod03_importers)
protect_self()
The highlight lines need to be replaced with real check list. In order to get baseline, first replace function ``check_module`` with this fake function

.. code-block:: python
def check_module(name, checklist):
m = modules[name]
refs = {}
for attr in dir(m):
value = getattr(m, attr)
if hasattr(value, '__code__'):
refs[attr] = sum(value.__code__.co_code)
print(' checklist_%s = %s' % (name, refs))
Run the following command to get baseline::

$ pyinstaller foo.py
$ pyarmor gen --pack dist/foo/foo foo.py

...
checklist__frozen_importlib = {'__import__': 9800, ...}
checklist__frozen_importlib_external = {'_calc_mode': 2511, ...}
checklist_pyimod03_importers = {'imp_lock': 183, 'imp_unlock': 183, ...}

Edit hook script to restore ``check_module`` and replace empty check lists with real ones.

Using this real hook script to generate the final bundle::

$ pyinstaller foo.py
$ pyarmor gen --pack dist/foo/foo foo.py

**Runtime Patch**

.. versionadded:: 8.x

It's not implemented.

Pyarmor provides runtime patch feature so that users could write one C or python script to do any anti-debug or other works. It will be embedded into :term:`runtime files`, and called on extension module ``pyarmor_runtime`` initialization.
Pyarmor provides runtime patch feature so that users could write one C or python script to do any anti-debug or other checks. It will be embedded into :term:`runtime files`, and called on extension module ``pyarmor_runtime`` initialization.

The idea is to make a file :file:`.pyarmor/hooks/pyarmor_runtime.py` or :file:`.pyarmor/hooks/pyarmor_runtime.c`, it will be inserted into runtime files when building obfuscated scripts.

Expand Down

0 comments on commit ed4afea

Please sign in to comment.