Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Globale Hooks mit c# (nichtnur lowlevel)
Floste
myCSharp.de - Member

Avatar #avatar-2376.jpg


Dabei seit:
Beiträge: 1158
Herkunft: Norddeutschland

Themenstarter:

Globale Hooks mit c# (nichtnur lowlevel)

beantworten | zitieren | melden

Beschreibung:

Eine Bootstrapper-dll, die eine c#-dll nachlädt und die Hookproc-Aufrufe daran weiterleitet.


Die zu ladende Dll muss eine Klasse namens "Hook", die in keinem namespace ist und die Funktionen "public static int Init(string empty)","public static int GetHookProc(string empty)" und "public static int Run(string empty)" enthält enthalten:


using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class Hook
{
    [STAThread]
    public static int Init(string empty)
    {
        return 0;
    }

    public delegate int HookProcDelegate(int code, IntPtr wParam, IntPtr lParam);

    [STAThread]
    public static int GetHookProc(string empty)
    {
        HookProcDelegate del = new HookProcDelegate(HookProc);
        
        GCHandle.Alloc(del, GCHandleType.Normal);//Edit

        IntPtr result = Marshal.GetFunctionPointerForDelegate(del);
        return (int)result;
    }

    [DllImport("user32.dll")]
    static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    static unsafe int HookProc(int code, IntPtr wParam, IntPtr lParam)
    {
        MSG* pmsg = (MSG*)lParam;
        //Hook-Code
        return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
    }

    public static int Run(string empty)
    {
        return 0;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct MSG
    {
        public IntPtr hwnd;
        public UInt32 message;
        public IntPtr wParam;
        public IntPtr lParam;
        public UInt32 time;
        public POINT pt;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;

        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }

        public static implicit operator System.Drawing.Point(POINT p)
        {
            return new System.Drawing.Point(p.X, p.Y);
        }

        public static implicit operator POINT(System.Drawing.Point p)
        {
            return new POINT(p.X, p.Y);
        }
    }
}

Hook erstellen (die c#dll "inject.dll" mit der Hook-klasse und die loaderDll.dll müssen sich im gleichen Ordner befinden):


[DllImport("kernel32.dll",EntryPoint="LoadLibraryW")]
        static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPWStr)]string str);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(HookType hook, IntPtr callback,
        IntPtr hMod, int dwThreadId);

        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hhk);

        public enum HookType : int
        {
            WH_JOURNALRECORD = 0,
            WH_JOURNALPLAYBACK = 1,
            WH_KEYBOARD = 2,
            WH_GETMESSAGE = 3,
            WH_CALLWNDPROC = 4,
            WH_CBT = 5,
            WH_SYSMSGFILTER = 6,
            WH_MOUSE = 7,
            WH_HARDWARE = 8,
            WH_DEBUG = 9,
            WH_SHELL = 10,
            WH_FOREGROUNDIDLE = 11,
            WH_CALLWNDPROCRET = 12,
            WH_KEYBOARD_LL = 13,
            WH_MOUSE_LL = 14
        }

       
        IntPtr hHook=IntPtr.Zero;
        IntPtr hDll = LoadLibrary("LoaderDll.dll");
        if(hDll==IntPtr.Zero)throw new Exception("LoaderDll.dll nicht gefunden");
        IntPtr hookProc = GetProcAddress(hDll, "[email protected]@[email protected]");
        hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, hookProc, hDll, 0);
        ...
        //zurückkehern zu Application.Run()
        ....
        UnhookWindowsHookEx(hHook);
        

Schlagwörter: Globaler Hook Hoocproc Keyboard

[EDIT] 2 bugs behoben und etwas aufgeräumt:
1. GC.KeepAlive durch GCHandle .Alloc ersetzt: führte zum zufälligen Abstürtzen belibiger Programme mit gui.
2. Für x86 statt Anycpu compiliert: führte zu Fehlfunktionen auf x64
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von Floste am .
Attachments
Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!
private Nachricht | Beiträge des Benutzers
Floste
myCSharp.de - Member

Avatar #avatar-2376.jpg


Dabei seit:
Beiträge: 1158
Herkunft: Norddeutschland

Themenstarter:

beantworten | zitieren | melden

[Edit] die binarys sind jetzt in den Unterordnern .\Release\ und .\Injecter\bin\Release\
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Floste am .
Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!
private Nachricht | Beiträge des Benutzers
Floste
myCSharp.de - Member

Avatar #avatar-2376.jpg


Dabei seit:
Beiträge: 1158
Herkunft: Norddeutschland

Themenstarter:

beantworten | zitieren | melden

Wenn man in einen bestimmten Prozess eine c#-Assebmbly einschleusen will, ohne gleich einen systemeiten hook zu setzen geht es mir der Bibliothek auch. (Die Assembly muss auch eine Klasse namens Hook enthalten, die hookproc wird allerdings nie aufgerufen, sondern nur "init" und "run"):


        unsafe private static void InjectCore(uint processId)
        {
            IntPtr hKernel32 = Kernel32.LoadLibrary("kernel32.dll");
            IntPtr loadLibraryProc = Kernel32.GetProcAddress(hKernel32, "LoadLibraryW");
            IntPtr hprocess = Kernel32.OpenProcess(Kernel32.ProcessAccessFlags.CreateThread | Kernel32.ProcessAccessFlags.Synchronize |
                Kernel32.ProcessAccessFlags.VMWrite | Kernel32.ProcessAccessFlags.VMOperation | Kernel32.ProcessAccessFlags.VMRead
            , false, processId);

            IntPtr foreigenMemory = IntPtr.Zero;
            {
                string paramstr = Program.GetLocalPath() + "LoaderDll.dll\0";
                byte[] bytes = Encoding.Unicode.GetBytes(paramstr);
                foreigenMemory = Kernel32.VirtualAllocEx(hprocess, IntPtr.Zero, (uint)bytes.Length,
                    Kernel32.AllocationType.RESERVE | Kernel32.AllocationType.COMMIT, Kernel32.MemoryProtection.EXECUTE_READWRITE);
                int written = 0;
                Kernel32.WriteProcessMemory(hprocess, foreigenMemory, bytes, (uint)bytes.Length, out written);
            }
            uint id = 0;
            Kernel32.CreateRemoteThread(hprocess, IntPtr.Zero, 0, loadLibraryProc, foreigenMemory, 0, &id);
            Kernel32.CloseHandle(hprocess);
        }

public class Kernel32
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
           uint dwProcessId);

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();

        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle,
           uint dwThreadId);

        [DllImport("kernel32.dll")]
        public static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

        [Flags]
        public enum ThreadAccess : int
        {
            TERMINATE = (0x0001),
            SUSPEND_RESUME = (0x0002),
            GET_CONTEXT = (0x0008),
            SET_CONTEXT = (0x0010),
            SET_INFORMATION = (0x0020),
            QUERY_INFORMATION = (0x0040),
            SET_THREAD_TOKEN = (0x0080),
            IMPERSONATE = (0x0100),
            DIRECT_IMPERSONATION = (0x0200)
        }

        [DllImport("kernel32.dll")]
        public static extern uint SuspendThread(IntPtr hThread);

        [DllImport("kernel32.dll")]
        public static extern uint ResumeThread(IntPtr hThread);

        [DllImport("kernel32.dll")]
        public static unsafe extern IntPtr CreateRemoteThread(IntPtr hProcess,
           IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, uint* lpThreadId);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
           byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);


        [Flags()]
        public enum AllocationType : uint
        {
            COMMIT = 0x1000,
            RESERVE = 0x2000,
            RESET = 0x80000,
            LARGE_PAGES = 0x20000000,
            PHYSICAL = 0x400000,
            TOP_DOWN = 0x100000,
            WRITE_WATCH = 0x200000
        }

        [Flags()]
        public enum MemoryProtection : uint
        {
            EXECUTE = 0x10,
            EXECUTE_READ = 0x20,
            EXECUTE_READWRITE = 0x40,
            EXECUTE_WRITECOPY = 0x80,
            NOACCESS = 0x01,
            READONLY = 0x02,
            READWRITE = 0x04,
            WRITECOPY = 0x08,
            GUARD_Modifierflag = 0x100,
            NOCACHE_Modifierflag = 0x200,
            WRITECOMBINE_Modifierflag = 0x400
        }

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
           uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr LoadLibrary(String InPath);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr GetProcAddress(IntPtr InModule, String InProcName);
    }
Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!
private Nachricht | Beiträge des Benutzers
Floste
myCSharp.de - Member

Avatar #avatar-2376.jpg


Dabei seit:
Beiträge: 1158
Herkunft: Norddeutschland

Themenstarter:

Anmerkungen

beantworten | zitieren | melden

1.Wenn man ein Programm mit dem Debugger startet, wird es mit anderen Benutzerrechten ausgeführt, als normale Programme. Deshalb funktioniert der Code nicht, solange man mit dem Debugger startet. Uac kann ebenfalls ein Problem darstellen, sofern das Programm mit geringeren Rechten als andere des selben Benutzers gestartet wird.

2. Die Bootstrapperdll ist nicht für x64 geeignet. Deshalb muss man seine c#-Exe für x86 compilieren. Die direkte dll-injektion von x86 in x64-Prozesse (und umgekehrt) scheitert. Globale hooks funktionieren auf x64 aus irgebndeinem Grund nicht. Wahrscheinlich wurden sie aus Sicherheitsgründen vom m$ deaktiviert..

Wenn jemand Inetresse an einer x64-dll hat, kann er sich bei mir melden. Es muss aber um beide Systeme zu unterstützen ein Prozess pro System gestartet werden. Also müssten ein Prozess für x64 und einer für x86 parallel laufen.

3. Ich habe die Runtimeversion des 2.0er Frameworks hardcoded einprogrammiert. Injezierte dlls dürfen also nur die Frameworkversionen von 2.0 bis 3.x verwenden, da diese auf der selben Runtimeversion beruhen. Um das zu umgehen kann man selbstverständlich die Runtimeversion im Code ändern und die c++ -Dll neu Compilieren.

4. Nicht die alte ver verwenden

5. Bestimmte Programme mögen es nicht besonders, wenn man dlls injeziert: In seltensten Fällen Av-Software b.z.w firewalls (Das sie anschlagen ist aber die absolute Ausnahme, solange man nur Programme des lokalen Benutzers und keine Systemdienste manipuliert) und bestimmte Onlinespiele (Insbesondere gewisse MMORPGS) haben was dagegen.
Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!
private Nachricht | Beiträge des Benutzers