Search code examples
powershellobfuscationdot-source

Is it possible to dot source a string variable in PowerShell?


I know I can dot source a file:

. .\MyFunctions.ps1

But, I would like to dot source the commands in a string variable:

. $myFuctions

I see that this is possible:

.{$x=2}

And $x equals 2 after the script block is sourced.

But... .{$myFunctions} does not work.

I tried $myFunctions | Invoke-Expression, but it doesn't keep the source function in the current scope. The closest I have been able to come up with is to write the variable to a temporary file, dot source the file, and then remove the file.

Inevitably, someone will ask: "What are you trying to do?" So here is my use case:

I want to obfuscate some functions I intend to call from another script. I don't want to obfuscate the master script, just my additional functions. I have a user base that will need to adjust the master script to their network, directory structure and other local factors, but I don't want certain functions modified. I would also like to protect the source code. So, an alternate question would be: What are some good ways to protect PowerShell script code?

I started with the idea that PowerShell will execute a Base64-encoded string, but only when passed on the command line with -EncodedCommand. I first wanted to dot source an encoded command, but I couldn't figure that out. I then decided that it would be "obfuscated" enough for my purposes if I converted by Base64 file into a decode string and dot sourced the value of the string variable. However, without writing the decoded source to a file, I cannot figure out how to dot source it.

It would satisfy my needs if I could Import-Module -EncodedCommand .\MyEncodedFile.dat


Solution

  • Actually, there is a way to achieve that and you were almost there.

    First, as you already stated, the source or dot operator works either by providing a path (as string) or a script block. See also: . (source or dot operator).

    So, when trying to dot-source a string variable, PowerShell thinks it is a path. But, thanks to the possibility of dot-sourcing script blocks, you could do the following:

    # Make sure everything is properly escaped.
    $MyFunctions = "function Test-DotSourcing { Write-Host `"Worked`" }"
    
    . { Invoke-Expression $MyFunctions }
    
    Test-DotSourcing
    

    Dot-Sourced Functions as String

    And you successfully dot-sourced your functions from a string variable!

    Explanation:

    • With Invoke-Expression the string is evaluated and run in the child scope (script block).
    • Then with . the evaluated expressions are added to the current scope.

    See also: