导入kernel32函数以在C#中分配虚拟内存?

VTMan

我的硬盘上有几个DLL文件。服务器上的进程包含重要的文件数据,我想通过在进程内部分配虚拟内存来记录这些数据。我没有该过程的源代码,因此我需要保留更多的外部措施。我希望它启动DLL主要功能。由于我想将其与WPF一起使用,因此需要使用C#编写外部的内存分配。

您如何使用C#在另一个进程中执行自己的源代码?

弗朗切斯科·文图拉(Francesco Ventura)

为了在进程内执行您自己的源代码,您需要为进程虚拟分配内存,并将DLL的路径写入分配的内存地址内。您将使用该DLL路径,使用kernel32.dll中 的导出函数在进程内部弹跳dll LoadLibraryW


Windows平台上的每个进程都有一个专用于该进程的指定内存大小。原因之一是出于安全性考虑,一个进程无法读取数据或将数据写入其他进程。因此,为了能够编写/注入您的DLL,您需要打开一个HANDLE如果OpenProcesskernel32.dll导入函数,则可以执行此操作这简短的意思是您正在使用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路径
步骤3使用LoadLibraryW

第二步涉及使用WriteProcessMemory来简单地将dll路径写入内存中。将字符串转换为字节数组

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

像这样,将字节数组写在使用Windows api函数WriteProcessMemory分配的内存上。

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

步骤1分配内存✓
步骤2写入DLL路径✓
步骤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
);

您可以阅读文档以获取更多信息。简单地说,这将LoadLibraryWkernel32.dll中找到您的函数,因为它是导出的函数。

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

步骤1分配内存✓
步骤2写入DLL路径✓
步骤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");

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

导入kernel32函数以在C#中分配虚拟内存?

来自分类Dev

C ++:在函数中分配内存

来自分类Dev

为什么虚拟内存中分配的块在一次运行之间差异很大?

来自分类Dev

分配给进程的虚拟内存

来自分类Dev

分配给进程的虚拟内存

来自分类Dev

无法分配大量虚拟内存

来自分类Dev

windbg帮助缺少kernel32函数

来自分类Dev

虚拟内存混乱

来自分类Dev

什么是虚拟内存?

来自分类Dev

每次在C#中运行程序时如何使用相同的虚拟内存块

来自分类Dev

如何释放在C ++中分配的C#中的内存

来自分类Dev

从 C# 代码访问在 C 代码中分配的结构内存

来自分类Dev

在 C++ dll 中分配内存,在 C# 中免费

来自分类Dev

函数的char指针是否需要在C中分配内存

来自分类Dev

C在函数中分配动态内存-相同的结果

来自分类Dev

在函数C ++中分配内存2D数组

来自分类Dev

虚拟内存或物理内存

来自分类Dev

物理内存与虚拟内存

来自分类Dev

取消分配函数中分配的内存

来自分类Dev

C3859:超出了PCH的虚拟内存范围

来自分类Dev

c-访问虚拟内存时出现分段错误

来自分类Dev

与C语言中的指针和虚拟内存的混淆

来自分类Dev

指针和虚拟内存

来自分类Dev

Android清理虚拟内存

来自分类Dev

虚拟内存和SSD

来自分类Dev

虚拟内存的简单定义

来自分类Dev

Ubuntu上的虚拟内存

来自分类Dev

VLC虚拟内存问题

来自分类Dev

仅在使用调试标志进行编译时,“虚拟内存耗尽:无法分配内存”