I came across a script that obfuscated its calls using the dot sourcing operator.
$ORMEFyak=.('n' 'ew-obje' 'ct') NeT.WebcLIENt;
This seems to be equivalent to:
$var = New-Object Net.WebClient
Running . "help"
returns the contents of the help
cmdlet.
Why exactly does the dot source operator act like this?
CodePudding user response:
The behavior is not specific to .
, the dot-sourcing operator; it equally applies to &
, the call operator.
Only when you're invoking a script file (
*.ps1
) (or, less commonly, function or script block) do.
and&
behave differently:.
runs the code directly in the caller's scope, whereas&
, which is more typical, runs it in a child scope - see this answer for more information.In the case of
New-Object
, as a cmdlet, you can technically use them interchangeably (or omit them altogether - see below), but for conceptual clarity it's better to use&
unless actual dot-sourcing is performed.
It isn't so much that they convert a string to a command, it is that their purpose is to execute a command given by its name.
The specific syntax used to provide or construct this name for .
or &
is incidental, and in your case a string-concatenation expression was used to obscure the name of the command being invoked.
- However, specifying the name of a command unquoted, verbatim (if syntactically possible) is special in that you can then invoke without an operator -
&
is then implied; see below for an example.
Therefore, all of the following variations are equivalent (for the reasons stated above, I'm using &
):
# Bareword (unquoted, verbatim) command name
# If you don't need dot-sourcing, you can invoke *as-is* -
# use of & is implied.
New-Object regex 'foo?'
# Optionally, use &
& New-Object regex 'foo?'
# If the command name *needs quoting*, is *(based on) a variable* or
# *built by an expression*, & is *required*
$cmd = 'New-Object'
& $cmd regex 'foo?'
& ('New-' 'Object') regex 'foo?'
Note that in addition to acting on command names (strings), .
and &
can also invoke script blocks (e.g. & { New-Object regex 'foo?' }
) and command-information objects returned by Get-Command
(e.g., & (Get-Command New-Object) regex 'foo?'
)