PythonObfuscator.psm1
|
################################################################################ # # Python Obfuscator is a source code obfuscator for the Python programming # language. Obfuscate and protect your Python source code and algorithms # against analysis, reverse engineering and technology theft. # # Python Obfuscator provides advanced Python source code parsing based on # AST trees, multiple advanced obfuscation, virtualization and protection # strategies are available. # # Version : PowerShell SDK v1.0.0 # PowerShell : Windows PowerShell 5.1 / PowerShell 7+ # Author : Bartosz Wójcik (support@pelock.com) # Project : https://www.pelock.com/products/python-obfuscator # Homepage : https://www.pelock.com # ################################################################################ Set-StrictMode -Version Latest if ($PSVersionTable.PSVersion.Major -lt 6) { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 } Add-Type -AssemblyName System.IO.Compression | Out-Null $script:PoApiUrl = 'https://www.pelock.com/api/python-obfuscator/v1' $script:PoUserAgent = 'PELock Python Obfuscator' $script:PoTimeoutSec = 3600 enum CodeVirtualization { vm fsa flat } enum RenameStyle { il o0 confusable hex homoglyph mangled } function Get-PoApiValue { param($Value) if ($null -eq $Value) { return $null } if ($Value -is [Enum]) { return $Value.ToString() } return [string]$Value } function Get-PoAdler32 { param([Parameter(Mandatory)] [byte[]]$Data) $modAdler = 65521 $a = 1 $b = 0 foreach ($byte in $Data) { $a = ($a + $byte) % $modAdler $b = ($b + $a) % $modAdler } return [uint32](($b -shl 16) -bor $a) } function Compress-PoZlib { param([Parameter(Mandatory)] [string]$Source) $bytes = [System.Text.Encoding]::UTF8.GetBytes($Source) $ms = New-Object System.IO.MemoryStream try { $deflate = New-Object System.IO.Compression.DeflateStream($ms, [System.IO.Compression.CompressionMode]::Compress, $true) try { $deflate.Write($bytes, 0, $bytes.Length) } finally { $deflate.Dispose() } $deflated = $ms.ToArray() } finally { $ms.Dispose() } $adler = Get-PoAdler32 -Data $bytes $output = New-Object byte[] ($deflated.Length + 6) $output[0] = 0x78 $output[1] = 0xDA [Buffer]::BlockCopy($deflated, 0, $output, 2, $deflated.Length) $output[$output.Length - 4] = [byte](($adler -shr 24) -band 0xFF) $output[$output.Length - 3] = [byte](($adler -shr 16) -band 0xFF) $output[$output.Length - 2] = [byte](($adler -shr 8) -band 0xFF) $output[$output.Length - 1] = [byte]($adler -band 0xFF) return [Convert]::ToBase64String($output) } function Expand-PoZlib { param([Parameter(Mandatory)] [string]$CompressedBase64) $data = [Convert]::FromBase64String($CompressedBase64) if ($data.Length -lt 6) { throw 'Invalid zlib payload.' } $payloadLength = $data.Length - 6 $ms = New-Object System.IO.MemoryStream($data, 2, $payloadLength) try { $deflate = New-Object System.IO.Compression.DeflateStream($ms, [System.IO.Compression.CompressionMode]::Decompress) try { $reader = New-Object System.IO.StreamReader($deflate, [System.Text.Encoding]::UTF8) try { return $reader.ReadToEnd() } finally { $reader.Dispose() } } finally { $deflate.Dispose() } } finally { $ms.Dispose() } } function ConvertTo-PoFormBody { param([Parameter(Mandatory)] [hashtable]$Fields) $parts = foreach ($key in $Fields.Keys) { $name = [uri]::EscapeDataString([string]$key) $value = [uri]::EscapeDataString([string]$Fields[$key]) '{0}={1}' -f $name, $value } return ($parts -join '&') } function Invoke-PoApiRequest { param([Parameter(Mandatory)] [hashtable]$Fields) $body = ConvertTo-PoFormBody -Fields $Fields $headers = @{ 'User-Agent' = $script:PoUserAgent } try { return Invoke-RestMethod -Uri $script:PoApiUrl -Method Post -Body $body ` -ContentType 'application/x-www-form-urlencoded' -Headers $headers ` -TimeoutSec $script:PoTimeoutSec } catch { return $false } } class PythonObfuscator { static [string] $API_URL = 'https://www.pelock.com/api/python-obfuscator/v1' hidden [string] $_api_key = '' [bool] $enable_compression = $false [object] $seed = $null [object] $randomization_density = $null [object] $rename_style = $null [object] $code_virtualization = [CodeVirtualization]::vm [bool] $self_defending = $false [bool] $protection_linker = $false [bool] $rename_variables = $true [bool] $rename_parameters = $true [bool] $rename_functions = $true [bool] $rename_function_calls = $true [bool] $shuffle_functions = $true [bool] $resolve_constants = $true [bool] $split_strings = $true [bool] $modify_strings = $true [bool] $encrypt_strings = $true [bool] $string_char_array_vault = $true [bool] $encrypt_integers = $true [bool] $encrypt_floating = $true [bool] $mba_binops = $true [bool] $integers_to_floating = $true [bool] $integers_to_arrays = $true [bool] $floats_to_arrays = $true [bool] $affine_integer_mask = $true [bool] $array_int_crypt = $true [bool] $array_char_crypt = $true [bool] $array_double_crypt = $true [bool] $array_string_crypt = $true [bool] $insert_random_value_bucket = $true [bool] $random_bucket_integers = $true [bool] $random_bucket_arrays = $true [bool] $random_bucket_functions = $true [bool] $random_bucket_characters = $true [bool] $random_bucket_anti_regex = $true [bool] $random_bucket_autostart = $true [bool] $insert_ternary_operators = $true [bool] $complexify_booleans = $true [bool] $opaque_branches = $true [bool] $opaque_mixer_chain = $true [bool] $insert_dead_code = $true [bool] $try_finally_noise = $true [bool] $decoy_functions = $true [bool] $lambda_decoys = $true [bool] $literal_padding = $true [bool] $fake_import_markers = $true [bool] $dynamic_getattr_calls = $true [bool] $obfuscate_imports = $true [bool] $callback_registration_stubs = $true [bool] $detect_debugger = $false [bool] $anti_vm = $false [bool] $anti_sandbox = $false [bool] $anti_emulator = $false [bool] $remove_comments = $true static [int] $ERROR_SUCCESS = 0 static [int] $ERROR_INPUT_SIZE = 1 static [int] $ERROR_INPUT = 2 static [int] $ERROR_PARSING = 3 static [int] $ERROR_OBFUSCATION = 4 static [int] $ERROR_OUTPUT = 5 PythonObfuscator() { $this.Initialize($null, $true) } PythonObfuscator([string]$ApiKey) { $this.Initialize($ApiKey, $true) } PythonObfuscator([string]$ApiKey, [bool]$EnableAllObfuscationOptions) { $this.Initialize($ApiKey, $EnableAllObfuscationOptions) } hidden [void] Initialize([string]$ApiKey, [bool]$EnableAllObfuscationOptions) { $this._api_key = $ApiKey $this.enable_compression = $false $this.seed = $null $this.randomization_density = $null $this.rename_style = $null $this.code_virtualization = if ($EnableAllObfuscationOptions) { [CodeVirtualization]::vm } else { $null } $this.rename_variables = $EnableAllObfuscationOptions $this.rename_parameters = $EnableAllObfuscationOptions $this.rename_functions = $EnableAllObfuscationOptions $this.rename_function_calls = $EnableAllObfuscationOptions $this.shuffle_functions = $EnableAllObfuscationOptions $this.resolve_constants = $EnableAllObfuscationOptions $this.split_strings = $EnableAllObfuscationOptions $this.modify_strings = $EnableAllObfuscationOptions $this.encrypt_strings = $EnableAllObfuscationOptions $this.string_char_array_vault = $EnableAllObfuscationOptions $this.encrypt_integers = $EnableAllObfuscationOptions $this.encrypt_floating = $EnableAllObfuscationOptions $this.mba_binops = $EnableAllObfuscationOptions $this.integers_to_floating = $EnableAllObfuscationOptions $this.integers_to_arrays = $EnableAllObfuscationOptions $this.floats_to_arrays = $EnableAllObfuscationOptions $this.affine_integer_mask = $EnableAllObfuscationOptions $this.array_int_crypt = $EnableAllObfuscationOptions $this.array_char_crypt = $EnableAllObfuscationOptions $this.array_double_crypt = $EnableAllObfuscationOptions $this.array_string_crypt = $EnableAllObfuscationOptions $this.insert_random_value_bucket = $EnableAllObfuscationOptions $this.random_bucket_integers = $EnableAllObfuscationOptions $this.random_bucket_arrays = $EnableAllObfuscationOptions $this.random_bucket_functions = $EnableAllObfuscationOptions $this.random_bucket_characters = $EnableAllObfuscationOptions $this.random_bucket_anti_regex = $EnableAllObfuscationOptions $this.random_bucket_autostart = $EnableAllObfuscationOptions $this.insert_ternary_operators = $EnableAllObfuscationOptions $this.complexify_booleans = $EnableAllObfuscationOptions $this.opaque_branches = $EnableAllObfuscationOptions $this.opaque_mixer_chain = $EnableAllObfuscationOptions $this.insert_dead_code = $EnableAllObfuscationOptions $this.try_finally_noise = $EnableAllObfuscationOptions $this.decoy_functions = $EnableAllObfuscationOptions $this.lambda_decoys = $EnableAllObfuscationOptions $this.literal_padding = $EnableAllObfuscationOptions $this.fake_import_markers = $EnableAllObfuscationOptions $this.dynamic_getattr_calls = $EnableAllObfuscationOptions $this.obfuscate_imports = $EnableAllObfuscationOptions $this.callback_registration_stubs = $EnableAllObfuscationOptions $this.remove_comments = $EnableAllObfuscationOptions $this.self_defending = $false $this.protection_linker = $false $this.detect_debugger = $false $this.anti_vm = $false $this.anti_sandbox = $false $this.anti_emulator = $false } [object] Login() { $params = @{ command = 'login' } return $this.PostRequest($params) } [object] ObfuscateScriptFile([string]$ScriptFilePath) { if (-not (Test-Path -LiteralPath $ScriptFilePath -PathType Leaf)) { return $false } try { $source = [System.IO.File]::ReadAllText((Resolve-Path -LiteralPath $ScriptFilePath).Path) } catch { return $false } if ([string]::IsNullOrEmpty($source)) { return $false } return $this.ObfuscateScriptSource($source) } [object] obfuscate_script_file([string]$script_file_path) { return $this.ObfuscateScriptFile($script_file_path) } [object] ObfuscateScriptSource([string]$ScriptSource) { $params = @{ command = 'obfuscate' source = $ScriptSource } return $this.PostRequest($params) } [object] obfuscate_script_source([string]$script_source) { return $this.ObfuscateScriptSource($script_source) } [object] PostRequest([hashtable]$ParamsArray) { if ($this._api_key) { $ParamsArray['key'] = $this._api_key } if ($null -ne $this.seed) { $ParamsArray['seed'] = [string]$this.seed } if ($null -ne $this.randomization_density) { $ParamsArray['randomization_density'] = [string]$this.randomization_density } if ($this.rename_style) { $ParamsArray['rename_style'] = Get-PoApiValue -Value $this.rename_style } if ($this.code_virtualization) { $ParamsArray['code_virtualization'] = Get-PoApiValue -Value $this.code_virtualization } $flags = @( 'self_defending', 'protection_linker', 'rename_variables', 'rename_parameters', 'rename_functions', 'rename_function_calls', 'shuffle_functions', 'resolve_constants', 'split_strings', 'modify_strings', 'encrypt_strings', 'string_char_array_vault', 'encrypt_integers', 'encrypt_floating', 'mba_binops', 'integers_to_floating', 'integers_to_arrays', 'floats_to_arrays', 'affine_integer_mask', 'array_int_crypt', 'array_char_crypt', 'array_double_crypt', 'array_string_crypt', 'insert_random_value_bucket', 'random_bucket_integers', 'random_bucket_arrays', 'random_bucket_functions', 'random_bucket_characters', 'random_bucket_anti_regex', 'random_bucket_autostart', 'insert_ternary_operators', 'complexify_booleans', 'opaque_branches', 'opaque_mixer_chain', 'insert_dead_code', 'try_finally_noise', 'decoy_functions', 'lambda_decoys', 'literal_padding', 'fake_import_markers', 'dynamic_getattr_calls', 'obfuscate_imports', 'callback_registration_stubs', 'detect_debugger', 'anti_vm', 'anti_sandbox', 'anti_emulator', 'remove_comments' ) foreach ($flag in $flags) { if ($this.$flag) { $ParamsArray[$flag] = '1' } } if ($ParamsArray.ContainsKey('source') -and $this.enable_compression -and $ParamsArray['source']) { $ParamsArray['source'] = Compress-PoZlib -Source ([string]$ParamsArray['source']) $ParamsArray['compression'] = '1' } $result = Invoke-PoApiRequest -Fields $ParamsArray if ($result -eq $false -or $null -eq $result) { return $false } $errorCode = 0 $errorProperty = $result.PSObject.Properties['error'] if ($null -ne $errorProperty) { $errorCode = [int]$errorProperty.Value } $outputProperty = $result.PSObject.Properties['output'] if ($null -ne $outputProperty -and $this.enable_compression -and $errorCode -eq [PythonObfuscator]::ERROR_SUCCESS) { $result.output = Expand-PoZlib -CompressedBase64 ([string]$outputProperty.Value) } return $result } [object] post_request([hashtable]$params_array) { return $this.PostRequest($params_array) } } function New-PythonObfuscator { <# .SYNOPSIS Creates a Python Obfuscator Web API client. .DESCRIPTION Factory for the PythonObfuscator class. Empty or invalid keys run demo mode, which ignores strategy flags and always applies integers_to_arrays, mba_binops, and encrypt_strings (no virtualization; 1000 character limit). .PARAMETER ApiKey Activation key from PELock. .PARAMETER EnableAllObfuscationOptions Enable or disable all of the obfuscation options. Protection strategies stay opt-in even when this is $true. .EXAMPLE $client = New-PythonObfuscator -ApiKey 'ABCD-ABCD-ABCD-ABCD' $result = $client.ObfuscateScriptSource($source) #> [CmdletBinding()] [OutputType([PythonObfuscator])] param( [string]$ApiKey, [bool]$EnableAllObfuscationOptions = $true ) if ([string]::IsNullOrWhiteSpace($ApiKey)) { return [PythonObfuscator]::new($null, $EnableAllObfuscationOptions) } return [PythonObfuscator]::new($ApiKey, $EnableAllObfuscationOptions) } Export-ModuleMember -Function @('New-PythonObfuscator') |