Reputation: 39
I'm getting this error when I try to load a program in memory
error:
GAC Version Location
--- ------- --------
False v2.0.50727
here my code:
$Path = "D:\calc.exe"
$bytes = [System.IO.File]::ReadAllBytes($Path)
$string = [System.Convert]::ToBase64String($bytes)
$bytees = [System.Convert]::FromBase64String($string)
[System.Reflection.Assembly]::Load($bytees)
Upvotes: 1
Views: 7105
Reputation: 437783
As Maximilian Burszley points out, what you're seeing is not an error.
In fact, it indicates that your assembly was successfully loaded from your byte array:
The System.Reflection.Assembly.Load
method returns a System.Reflection.Assembly
instance representing the loaded assembly, and since you're not assigning that return value to a variable, PowerShell implicitly prints a friendly representation of the object to the console, and this is what you're seeing; if you append | Format-List
to your [System.Reflection.Assembly]::Load($bytees)
call, you'll see more detailed information about the newly loaded assembly.
Any public types defined in the assembly should now be available in your PowerShell session; however, given that you're indicating an *.exe
files as the source, perhaps you want to execute the assembly as you would the original executable, possibly with command-line arguments.
To provide a full example:
# Note: This must be an executable or DLL compiled for .NET
$Path = "D:\calc.exe"
# Get Base64-encoded representation of the bytes that make up the assembly.
$bytes = [System.IO.File]::ReadAllBytes($Path)
$string = [System.Convert]::ToBase64String($bytes)
# ...
# Convert the Base64-encoded string back to a byte array, load
# the byte array as an assembly, and save the object representing the
# loaded assembly for later use.
$bytes = [System.Convert]::FromBase64String($string)
$assembly = [System.Reflection.Assembly]::Load($bytes)
# Get the static method that is the executable's entry point.
# Note:
# * Assumes 'Program' as the class name,
# and a static method named 'Main' as the entry point.
# * Should there be several classes by that name, the *first*
# - public or non-public - type returned is used.
# If you know the desired type's namespace, use, e.g.
# $assembly.GetType('MyNameSpace.Program').GetMethod(...)
$entryPointMethod =
$assembly.GetTypes().Where({ $_.Name -eq 'Program' }, 'First').
GetMethod('Main', [Reflection.BindingFlags] 'Static, Public, NonPublic')
# Now you can call the entry point.
# This example passes two arguments, 'foo' and 'bar'
$entryPointMethod.Invoke($null, (, [string[]] ('foo', 'bar')))
Note: A generalization of the above - which doesn't require you to know the class name and invokes the CLI entry point without arguments - can be found in this answer.
Upvotes: 3