To modify the implementation of a function persistently without changing the source code directly, we have to manipulate the bytecode generated from source.
Here is an extremely simplified workflow of Python:
---------- ------------
| source | compiled | bytecode | executed by VM
| (.py) | -------> | (.pyc) | ------------->
---------- ------------
↑ inject our payload here
There is a sample module foobarbuzz created for demonstration, you play with it by running the script demo/run_patch_module.py. (or you can just check it on repl.it)
In the module foobarbuzz, there is a function foo which will call another function verification for some purposes (although it does nothing here).
In our scenario, we want to change the behavior of verification called by foo. So that we create a new implementation:
# in 'demo/run_patch_module.py'
def new_verification():
print('... Content has been modified ...')Then, we use COManipulator.patch_module() to inject our new implementation to replace the original verification called by foo, and dump the modified module to a .pyc file by COWriter.to_pyc().
And here is the output after the script is executed:
--- original version ---
foo
--- modified version ---
... Content has been modified ...
foo