如何从PowerShell获取CreateTransaction地址

问题描述 投票:0回答:1

我想在PowerShell中获取函数CreateTransaction的地址。

我知道如何用C ++做到这一点:

#include "stdafx.h"
#include <Windows.h>

typedef NTSTATUS(NTAPI *CreateTransaction)
(
    IN LPSECURITY_ATTRIBUTES lpTransactionAttributes OPTIONAL,
    IN LPGUID                UOW OPTIONAL,
    IN DWORD                 CreateOptions OPTIONAL,
    IN DWORD                 IsolationLevel OPTIONAL,
    IN DWORD                 IsolationFlags OPTIONAL,
    IN DWORD                 Timeout OPTIONAL,
    IN LPWSTR                Description OPTIONAL
    );

int main()
{
    HMODULE hKtmw32 = GetModuleHandle(L"Ktmw32.dll");
    CreateTransaction createTransaction = (CreateTransaction)GetProcAddress(hKtmw32, "CreateTransaction");

    return 0;
}

我怎么能在PowerShell中做到这一点? 我试着用下面的功能来做。 它适用于其他功能,但不适用于CreateTransaction

function Local:Get-ProcAddress
{
    Param
    (
        [OutputType([IntPtr])]

        [Parameter( Position = 0, Mandatory = $True )]
        [String]
        $Module,

        [Parameter( Position = 1, Mandatory = $True )]
        [String]
        $Procedure
    )

    # Get a reference to System.dll in the GAC
    $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
        Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
    $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
    # Get a reference to the GetModuleHandle and GetProcAddress methods
    $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
    $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
    # Get a handle to the module specified
    $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
    $hexAddrs = [convert]::ToString($Kern32Handle.ToInt32(), 16)
    Write-Host "[*] Got $($Module) at 0x$($hexAddrs)"
    $tmpPtr = New-Object IntPtr
    $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)

    # Return the address of the function
    Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}

Get-ProcAddress Ktmw32.dll CreateTransaction # => DOES NOT WORK
Get-ProcAddress ntdll.dll NtCreateSection    # => WORKS

参考: https://github.com/HarmJ0y/Misc-PowerShell/blob/master/Get-System.ps1

我不知道为什么它没有给我回CreateTransaction的地址。

我有解决方法来调用该函数,但我仍然感兴趣的是如何使用PowerShell获取函数地址:

Add-Type -TypeDefinition @"
    using System;
    using System.Runtime.InteropServices;
namespace PInvoke {

    public class Program
    {
        [StructLayout(LayoutKind.Sequential)] 
        public struct SECURITY_ATTRIBUTES { 
            int nLength;  
            IntPtr lpSecurityDescriptor; 
            int bInheritHandle;
        }
        [DllImport("Ktmw32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
        public static extern IntPtr CreateTransaction( 
                 SECURITY_ATTRIBUTES securityAttributes, 
                 IntPtr guid, int options, int isolationLevel, int isolationFlags, 
                 int milliSeconds, string description
        ); 
    }
}
"@  

$Class1 = New-Object PInvoke.Program
$struct = New-Object PInvoke.Program+SECURITY_ATTRIBUTES
[PInvoke.Program]::CreateTransaction($struct, 0, 0, 0, 0, 0, "notepad.exe")
c++ powershell pinvoke
1个回答
2
投票

我不知道为什么它不会返回CreateTransaction的地址。

很可能,它不会返回地址,因为它不存在 - 我想不到PowerShell中依赖于KtmW32.dll的单个模块或工具,所以假设它本来是由powershell.exe加载的,似乎很幼稚。

您可以通过询问当前进程的Modules属性来检查它:

(Get-Process -Id $PID).Modules

作为Add-Type的替代方案,您可以通过SafeNativeMethods.LoadLibrary()手动将库加载到流程中:

$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
    Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } |Select -First 1
$SafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.SafeNativeMethods')
$KtmW32 = $SafeNativeMethods::LoadLibrary('KtmW32.dll')

现在您可以在示例中使用Get-ProcAddress,或直接使用LoadLibrary返回的模块句柄:

# Same as before
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')

$tmpPtr = New-Object IntPtr

# Now use the module handle from LoadLibrary instead
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $KtmW32)

$GetProcAddress.Invoke($null,@([System.Runtime.InteropServices.HandleRef]$handleref,'CreateTransaction'))
© www.soinside.com 2019 - 2024. All rights reserved.