簡體   English   中英

導入kernel32函數以在C#中分配虛擬內存?

[英]Importing kernel32 functions for allocating virtual memory in C#?

我的硬盤上有幾個DLL文件。 服務器上的進程包含重要的文件數據,我想通過在進程內部分配虛擬內存來記錄這些數據。 我沒有該過程的源代碼,因此我需要保留更多的措施。 我希望它啟動DLL主要功能。 由於我想將其與WPF一起使用,因此需要使用C#編寫外部的內存分配。

您如何使用C#在另一個進程中執行自己的源代碼?

為了在進程內執行自己的源代碼,您需要為進程虛擬分配內存 ,並在分配的內存地址內寫入DLL的路徑。 您將使用該DLL路徑,使用kernel32.dll LoadLibraryW的導出函數在進程內部彈跳dll。


Windows平台上的每個進程都有一個專用於該進程的指定內存大小。 原因之一是出於安全性考慮,一個進程不能向其他進程讀取或寫入數據。 因此,為了能夠編寫/注入您的DLL,您需要打開一個HANDLE 如果從kernel32.dll導入OpenProcess函數,則可以執行此OpenProcess 這簡短的意思是您正在使用Windows API。 這是在C#中導入kernel32 DLL的方法

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(
  uint dwDesiredAccess, 
  int  bInheritHandle, 
  uint dwProcessId
);

您可以在聖經中找到Windows API的完整文檔

現在,您想使用OpenProcess函數將內存分配給您從中獲得處理的進程。 使用VirtualAllocEx函數,讓我們咨詢MSDN

您如何分配記憶?

LPVOID WINAPI VirtualAllocEx(
  _In_     HANDLE hProcess,
  _In_opt_ LPVOID lpAddress,
  _In_     SIZE_T dwSize,
  _In_     DWORD  flAllocationType,
  _In_     DWORD  flProtect
);

如我們所見,它需要5個參數。 您之前收集的HANDLE對象。 我們不會使用的可選參數。 如果將DLL轉換為字節數組,則可以獲得DLL的大小。 內存分配的類型,我們既要保留又要提交分配,因此請使用(0x1000 | 0x2000)並最后對分配的內存進行保護,該保護將在寫入0x40時進行

步驟1分配內存✓
步驟2寫入DLL路徑
STEP 3使用LoadLibraryW

第二步涉及使用WriteProcessMemory簡單地將dll路徑寫入內存。 將字符串轉換為字節數組

byte[] bytes = Encoding.ASCII.GetBytes(DllPath);

像這樣,將字節數組寫在使用Windows api函數WriteProcessMemory分配的內存上。

WriteProcessMemory(processHandle, allocatedMemory, bytes, (uint)bytes.Length, 0)

步驟1分配內存✓
步驟2寫入DLL路徑✓
STEP 3使用LoadLibraryW

如果您不知道哪些導出函數是錯誤的,這將很難解釋。

創建應用程序時,您需要導入Windows提供的DLL,以便使用某些功能。 例如,您要在應用程序中發送HTTP請求。 即使您不知道,也需要加載Windows ws2.dll (Windows套接字)庫。 Windows操作系統提供了一個方便的函數,該函數將按字面意義加載一個名為LoadLibraryW的庫。 在哪里可以找到這個出色的功能? 好吧,不用擔心孩子,kernel32.dll讓您滿意。 您需要做的就是找到一個指向LoadLibraryW函數的指針。 再次,對MSDN表現出信心,它會回報您。

FARPROC WINAPI GetProcAddress(
  _In_ HMODULE hModule,
  _In_ LPCSTR  lpProcName
);

HMODULE WINAPI GetModuleHandle(
  _In_opt_ LPCTSTR lpModuleName
);

您可以閱讀文檔以獲取更多信息。 簡單地說,這將在kernel32.dll中找到您的LoadLibraryW函數,因為它是導出的函數。

IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");

步驟1分配內存✓
步驟2寫入DLL路徑✓
STEP 3使用LoadLibraryW✓

在您的進程內啟動一個遠程線程,該線程將僅執行您的負載庫代碼

CreateRemoteThread(hndProc, (IntPtr)null, (IntPtr)null, lpLLAddress, lpAddress, 0, (IntPtr)null)

之后,只需關閉進程的句柄,您的dll應該被“ 注入 ”到進程內。 無論如何,如果您仍然沒有弄清楚它,或者只是想要一個可以為您完成此任務的類,那么這里是一些源代碼

DLL注入器

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace dllInjectExample
{
    public enum DllInjectionResult
    {
        DllNotFound,
        GameProcessNotFound,
        InjectionFailed,
        Success
    }

    public static class DllInjector
    {
        static readonly IntPtr INTPTR_ZERO = (IntPtr)0;

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern int CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr GetModuleHandle(string lpModuleName);

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

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
            IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

        public static DllInjectionResult Inject(string sProcName, string sDllPath)
        {
            if (!File.Exists(sDllPath))
            {
                return DllInjectionResult.DllNotFound;
            }

            uint _procId = 0;

            Process[] _procs = Process.GetProcesses();
            for (int i = 0; i < _procs.Length; i++)
            {
                if (_procs[i].ProcessName == sProcName)
                {
                    _procId = (uint)_procs[i].Id;
                    break;
                }
            }

            if (_procId == 0)
            {
                return DllInjectionResult.GameProcessNotFound;
            }

            if (!bInject(_procId, sDllPath))
            {
                return DllInjectionResult.InjectionFailed;
            }

            return DllInjectionResult.Success;
        }

        private static bool bInject(uint pToBeInjected, string sDllPath)
        {
            IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);

            if (hndProc == INTPTR_ZERO)
            {
                return false;
            }

            IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);

            if (lpAddress == INTPTR_ZERO)
            {
                return false;
            }

            byte[] bytes = Encoding.ASCII.GetBytes(sDllPath);

            if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
            {
                return false;
            }

            IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");

            if (lpLLAddress == INTPTR_ZERO)
            {
                return false;
            }

            if (CreateRemoteThread(hndProc, (IntPtr)null, INTPTR_ZERO, lpLLAddress, lpAddress, 0, (IntPtr)null) == INTPTR_ZERO)
            {
                return false;
            }

            CloseHandle(hndProc);

            return true;
        }
    }
}

注入csgo的示例,因為我不知道為什么要注入dll?

if (Process.GetProcessesByName("csgo").Count() == 0)
            {
                Process Proc = new Process();
                ProcessStartInfo startInfo = new ProcessStartInfo(@"D:\Application\Steam\Steam.exe");

                Proc.StartInfo = startInfo;
                Proc.StartInfo.Arguments = "-applaunch 730";
                Proc.StartInfo.UseShellExecute = false;
                Proc.StartInfo.CreateNoWindow = false;
                Proc.Start();
                Thread.Sleep(15000);
            }

            while (Process.GetProcessesByName("csgo").Count() == 0)
            {

            }

            var something = DllInjector.Inject("csgo", @"C:\Visual Studio 2015\Projects\XGame\Debug\XGamedll.dll");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM