C# Konvertieren von IntPtr in int

Bin ich dynamisch aufrufen der Windows-API. Ich fand einige code online, die dies tun können, und ich nahm eine ganze Menge von Interesse zu Sie. Die Idee an sich ist Brillant, gelinde gesagt. Aber ich kann nicht scheinen, um es Arbeit für meinen code. Die Parameter für den dynamischen Aufruf der Art string, string int[], und ich möchte die API zu verwenden GetThreadContext mit den Parametern der pInfo.hThred und ref ctx (siehe unten).

API-Aufruf

GetThreadContext(pInfo.hThread, ref ctx);

Dem obigen code wird ein Aufruf an die GetThreadContext API (da ist erklärt in meinem Projekt) - und arbeitet völlig in Ordnung. Die Schönheit der dynamische Aufruf, jedoch, ist, dass keine Anmeldung erforderlich ist. So, mein Versuch, den dynamischen Aufruf:

ctx = new CONTEXT {ContextFlags = 0x10007};
PROCESS_INFORMATION pInfo;

CInvokeAPI.Invoke("kernel32","GetThreadContext",pInfo.hThread, ctx);

Hier das Problem ist, dass ich habe keine Ahnung, wie kann ich pass parameter ctx als Typ " int " angesichts der Tatsache, dass es ein struct.

Bitte siehe unten für weitere code

    [StructLayout(LayoutKind.Sequential)]
    struct CONTEXT
    {
        public uint ContextFlags;
        unsafe fixed byte unused[160];
        public uint Ebx;
        public uint Edx;
        public uint Ecx;
        public uint Eax;
        unsafe fixed byte unused2[24];
    }

    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

Aufrufen von API-Dynamisch-Klasse

using System;
using System.Runtime.InteropServices;
using System.Text;

/* 
 * Title: CInvokeAPI.cs
 * Description: Call API by name implementation in purely managed C# (no 'unsafe' mess here).
 * 
 * Developed by: affixiate 
 * Comments: If you use this code, I require you to give me credits. 
 */

public static class CInvokeAPI
{
    ///<summary>
    ///Generates a new, non-garbage collectable string in memory. Use this with Unicode "W" API.
    ///</summary>
    ///<param name="theString">A Unicode string.</param>
    ///<returns>Address of newly allocated string in memory. Remember to free it after use.</returns>
    public static int StringToPtrW(string theString)
    {
        return StringToPtr(Encoding.Unicode.GetBytes(theString));
    }

    ///<summary>
    ///Generates a new, non-garbage collectable string in memory. Use this with ANSI "A" API.
    ///</summary>
    ///<param name="theString">An ANSII string.</param>
    ///<returns>Address of newly allocated string in memory. Remember to free it after use.</returns>
    public static int StringToPtrA(string theString)
    {
        return StringToPtr(Encoding.ASCII.GetBytes(theString));
    }

    ///<summary>
    ///Internal method used to allocate memory.
    ///</summary>
    ///<param name="buf">A byte buffer.</param>
    ///<returns>Address of newly allocated memory. Remember to free it after use.</returns>
    private static int StringToPtr(byte[] buf)
    {
        return (int)GCHandle.Alloc(buf, GCHandleType.Pinned).AddrOfPinnedObject();
    }

    ///<summary>
    ///Invokes the specified Windows API.
    ///</summary>
    ///<param name="libraryName">Name of the library.</param>
    ///<param name="functionName">Name of the function.</param>
    ///<param name="args">The arguments.</param>
    ///<returns>True if function succeeds, otherwise false.</returns>
    public static bool Invoke(string libraryName, string functionName, params int[] args)
    {
        /* Sanity checks. */
        IntPtr hLoadLibrary = LoadLibrary(libraryName);
        if (hLoadLibrary == IntPtr.Zero) return false;

        IntPtr hGetProcAddress = GetProcAddress(hLoadLibrary, functionName);
        if (hGetProcAddress == IntPtr.Zero) return false;

        //Allocates more than enough  memory for an stdcall and the parameters of a WinAPI function
        IntPtr hMemory = VirtualAlloc(IntPtr.Zero, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, MEM_EXECUTE_READWRITE);
        if (hMemory == IntPtr.Zero)
            return false;

        IntPtr hMemoryItr = hMemory;

        //Prepends the stdcall header signature
        Marshal.Copy(new byte[] {0x55, 0x89, 0xE5}, 0, hMemoryItr, 0x3);
        hMemoryItr = (IntPtr)((int)hMemoryItr + 0x3);

        //Loop through the passed in arguments and place them on the stack in reverse order
        for (int i = (args.Length - 1); i >= 0; i--) 
        {
            Marshal.Copy(new byte[] {0x68}, 0, hMemoryItr, 0x1); 
            hMemoryItr = (IntPtr)((int)hMemoryItr + 0x1);
            Marshal.Copy(BitConverter.GetBytes(args[i]), 0, hMemoryItr, 0x4);
            hMemoryItr = (IntPtr)((int)hMemoryItr + 0x4);
        }

        Marshal.Copy(new byte[] {0xE8}, 0, hMemoryItr, 0x1);
        hMemoryItr = (IntPtr)((int)hMemoryItr + 0x1);
        Marshal.Copy(BitConverter.GetBytes((int)hGetProcAddress - (int)hMemoryItr - 0x4), 0, hMemoryItr, 0x4);
        hMemoryItr = (IntPtr)((int)hMemoryItr + 0x4);

        //Cleaning up the stack
        Marshal.Copy(new byte[] {0x5D, 0xC2, 0x4, 0x0 /* <= I made a LOL. */}, 0, hMemoryItr, 0x4);
        //Don't forget to increment if you are adding more ASM code here: hMemoryItr = (IntPtr)((int)hMemoryItr + 0x4);

        try
        {
            var executeAsm = (RunAsm) Marshal.GetDelegateForFunctionPointer(hMemory, typeof (RunAsm));
            executeAsm();
        }
        catch { return false; }

        //Clean up the memory we allocated to do the dirty work
        VirtualFree(hMemory, 0, MEM_RELEASE);
        return true;
    }

    //ReSharper disable InconsistentNaming
    private const uint MEM_RELEASE = 0x8000;
    private const uint MEM_COMMIT = 0x1000;
    private const uint MEM_RESERVE = 0x2000;
    private const uint MEM_EXECUTE_READWRITE = 0x40;
    //ReSharper restore InconsistentNaming

    //My own sexy delegate:
    [UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
    private delegate void RunAsm();

    //WinAPI used:
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, uint dwFreeType);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UInt32 dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr LoadLibrary(string lpFileName);

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
}
  • Könnten Sie die REALEN Parameter erwartet myVoid auf der nicht verwalteten Seite ? ist es wirklich ein GRIFF und ein KONTEXT* ? Wenn ja, müssen Sie die Zuordnung von bestimmten verwalteten Speicher für diese eine Kopie einer CONTEXT-Instanz im inneren, finden Sie unter msdn.microsoft.com/en-us/library/..., wenn statt einem Griff, die Sie brauchen eine PROCESS_INFORMATION* Sie müssen das gleiche zu tun für diesen parameter.
  • Aktualisiert ...
  • Hüten Sie sich vor 64-bit
  • Mit 32-bit-Maschine. Danke aber.
InformationsquelleAutor | 2011-08-03
Schreibe einen Kommentar