C#DLL注入未加载DLL

弗雷德里克·霍夫特(Frederik Hoeft)

我知道这里有一些关于stackoverflow的类似问题,但是没有一个问题解决了我的问题。

因此,我正在为低级进程间操作(包括dll注入功能)编写ac#框架。

使用前打电话给我注射,我已经连接到目标进程(在这种情况下,记事本++。exe文件)OpenProcess()PROCESS_ALL_ACCESS权限。以下是我的注入器代码(由于所有调试打印,我知道可读性受到很大影响):

public void Inject(string dllName, bool printDebugInfo)
{
    // Check if we are attached to the process.
    target.Assertions.AssertProcessAttached();
    target.Assertions.AssertInjectionPermissions();

    // searching for the address of LoadLibraryA and storing it in a pointer
    IntPtr kernel32Handle = WinAPI.GetModuleHandle("kernel32.dll");
    if (kernel32Handle == IntPtr.Zero)
    {
        uint errorCode = WinAPI.GetLastError();
        throw new Win32Exception((int)errorCode, "Encountered error " + errorCode.ToString() + " (0x" + errorCode.ToString("x") + ") - FATAL: Could not get handle of kernel32.dll: was NULL.");
    }
    UIntPtr loadLibraryAddr = WinAPI.GetProcAddress(kernel32Handle, "LoadLibraryA");
    if (loadLibraryAddr == UIntPtr.Zero)
    {
        uint errorCode = WinAPI.GetLastError();
        throw new Win32Exception((int)errorCode, "Encountered error " + errorCode.ToString() + " (0x" + errorCode.ToString("x") + ") - FATAL: Could not get address of LoadLibraryA: was NULL.");
    }
    HelperMethods.Debug("LoadLibraryA is at 0x" + loadLibraryAddr.ToUInt64().ToString("x"), printDebugInfo);

    // alocating some memory on the target process - enough to store the name of the dll
    // and storing its address in a pointer
    uint size = (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char)));
    IntPtr allocMemAddress = WinAPI.VirtualAllocEx(target.Handle, IntPtr.Zero, size, (uint)Permissions.MemoryPermission.MEM_COMMIT | (uint)Permissions.MemoryPermission.MEM_RESERVE, (uint)Permissions.MemoryPermission.PAGE_READWRITE);
    HelperMethods.Debug("Allocated memory at 0x" + allocMemAddress.ToInt64().ToString("x"), printDebugInfo);

    int bytesWritten = 0;
    // writing the name of the dll there
    byte[] buffer = new byte[size];
    byte[] bytes = Encoding.ASCII.GetBytes(dllName);
    Array.Copy(bytes, 0, buffer, 0, bytes.Length);
    buffer[buffer.Length - 1] = 0;
    bool success = WinAPI.WriteProcessMemory((uint)target.Handle, allocMemAddress.ToInt64(), buffer, size, ref bytesWritten);
    if (success)
    {
        HelperMethods.Debug("Successfully wrote \"" + dllName + "\" to 0x" + allocMemAddress.ToInt64().ToString("x"), printDebugInfo);
    }
    else
    {
        HelperMethods.Debug("FAILED to write dll name!", printDebugInfo);
    }
    // creating a thread that will call LoadLibraryA with allocMemAddress as argument
    HelperMethods.Debug("Injecting dll ...", printDebugInfo);
    IntPtr threadHandle = WinAPI.CreateRemoteThread(target.Handle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, out IntPtr threadId);
    HelperMethods.Debug("CreateRemoteThread returned the following handle: 0x" + threadHandle.ToInt32().ToString("x"), printDebugInfo);
    uint errCode = WinAPI.GetLastError();
    if (threadHandle == IntPtr.Zero)
    {
        throw new Win32Exception((int)errCode, "Encountered error " + errCode.ToString() + " (0x" + errCode.ToString("x") + ") - FATAL: CreateRemoteThread returned NULL pointer as handle.");
    }
    Console.WriteLine("CreateRemoteThread threw errorCode 0x" + errCode.ToString("x"));
    Console.WriteLine("Currently the following modules are LOADED:");
    ProcessModuleCollection processModules = target.Process.Modules;
    foreach (ProcessModule module in processModules)
    {
        Console.WriteLine("  - " + module.FileName);
    }
    uint waitExitCode = WinAPI.WaitForSingleObject(threadHandle, 10 * 1000);
    HelperMethods.Debug("Waiting for thread to exit ...", printDebugInfo);
    HelperMethods.Debug("WaitForSingleObject returned 0x" + waitExitCode.ToString("x"), printDebugInfo);
    Thread.Sleep(1000);
    Console.WriteLine("Currently the following modules are LOADED:");
    processModules = target.Process.Modules;
    foreach (ProcessModule module in processModules)
    {
        Console.WriteLine("  - " + module.FileName);
    }
    success = WinAPI.GetExitCodeThread(threadHandle, out uint exitCode);
    if (!success)
    {
        uint errorCode = WinAPI.GetLastError();
        throw new Win32Exception((int)errorCode, "Encountered error " + errorCode.ToString() + " (0x" + errorCode.ToString("x") + ") - FATAL: Non-zero exit code of GetExitCodeThread.");
    }
    Console.WriteLine("Currently the following modules are LOADED:");
    processModules = target.Process.Modules;
    foreach (ProcessModule module in processModules)
    {
        Console.WriteLine("  - " + module.FileName);
    }
    HelperMethods.Debug("Remote thread returned 0x" + exitCode.ToString("x"), printDebugInfo);
    success = WinAPI.CloseHandle(threadHandle);
    if (!success)
    {
        uint errorCode = WinAPI.GetLastError();
        throw new Win32Exception((int)errorCode, "Encountered error " + errorCode.ToString() + " (0x" + errorCode.ToString("x") + ") - FATAL: Failed calling CloseHandle on 0x" + threadHandle.ToInt64().ToString("x") + ".");
    }
    HelperMethods.Debug("Called CloseHandle on 0x" + threadHandle.ToInt64().ToString("x") + ".", printDebugInfo);
    success = WinAPI.VirtualFreeEx(target.Handle, allocMemAddress, 0, 0x8000);
    if (!success)
    {
        uint errorCode = WinAPI.GetLastError();
        throw new Win32Exception((int)errorCode, "Encountered error " + errorCode.ToString() + " (0x" + errorCode.ToString("x") + ") - FATAL: Failed calling VirtualFreeEx on 0x" + allocMemAddress.ToInt64().ToString("x") + ".");
    }
    HelperMethods.Debug("Released all previously allocated resources!", printDebugInfo);
}

所有WinAPI函数均按照Microsoft官方文档的指定进行了调用(经过三重检查)。

我正在按以下方式调用我的代码

Target target = Target.CreateFromName("notepad++");
target.Attach(Permissions.ProcessPermission.PROCESS_ALL_ACCESS);
target.Injector.Inject(@"L:\Programming\C\test\newdll.dll",true);

Target该类的完整源代码GitHub上,但与该问题无关。

可能最有趣的newdll.dll是用本机C编写的,如下所示:

#include<Windows.h>
#include<stdbool.h>
__declspec(dllexport) bool WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            break;
        }

        case DLL_PROCESS_DETACH:
        {
            break;
        }

        case DLL_THREAD_ATTACH:
        {
            break;
        }

        case DLL_THREAD_DETACH:
        {
            break;
        }
    }
    return true;
}

这段代码显然做不了什么,但是从DllMain生成诸如消息框之类的消息显然被认为是“不好的”,所以我就这样保留了它。但是,如果注入工作正常,则将在Process.Modules其中列出dll (不是)。

但是,在运行我的代码时,我从所有调试打印中得到以下输出:

LoadLibraryA is at 0x778f60b0
Allocated memory at 0x9c0000
Successfully wrote "L:\Programming\C\test\newdll.dll" to 0x9c0000
Injecting dll ...
CreateRemoteThread returned the following handle: 0x22c
CreateRemoteThread threw errorCode 0x0
Currently the following modules are LOADED:
  - J:\TOOLS\Notepad++\notepad++.exe
  - C:\Windows\SYSTEM32\ntdll.dll
  - C:\Windows\SYSTEM32\wow64.dll
  - C:\Windows\SYSTEM32\wow64win.dll
  - C:\Windows\SYSTEM32\wow64cpu.dll
Waiting for thread to exit ...
WaitForSingleObject returned 0x0
Currently the following modules are LOADED:
  - J:\TOOLS\Notepad++\notepad++.exe
  - C:\Windows\SYSTEM32\ntdll.dll
  - C:\Windows\SYSTEM32\wow64.dll
  - C:\Windows\SYSTEM32\wow64win.dll
  - C:\Windows\SYSTEM32\wow64cpu.dll
Currently the following modules are LOADED:
  - J:\TOOLS\Notepad++\notepad++.exe
  - C:\Windows\SYSTEM32\ntdll.dll
  - C:\Windows\SYSTEM32\wow64.dll
  - C:\Windows\SYSTEM32\wow64win.dll
  - C:\Windows\SYSTEM32\wow64cpu.dll
Remote thread returned 0x0
Called CloseHandle on 0x22c.
Released all previously allocated resources!
Press any key to continue . . .

可以看出,没有错误代码或注入指示真正出错的指示,除了newdll.dll从未加载过,因为它没有显示在已加载的模块中Process.Modules

那么我的代码有什么问题呢?

快速概述:我确实遵循以下步骤:

  • OpenProcess()PROCESS_ALL_ACCESS
  • GetModuleHandle("kernel32.dll")
  • GetProcAddress(kernel32Handle, "LoadLibraryA")
  • VirtualAllocEx(...)WriteProcessMemory()写下我的dll名称和路径。
  • CreateRemoteThread() 加载DLL
  • WaitForSingleObject() 等待DLL被加载
  • 释放先前分配的所有资源
弗雷德里克·霍夫特(Frederik Hoeft)

正确指出,这种注入技术仅在从32位进程-> 32位进程或从64位进程-> 64位进程进行注入时才有效。我将代码编译为64位可执行文件,试图将dll注入32位notepad ++。exe。

另外,我还不得不修改该WriteProcessMemory调用以符合32位内存空间。因此,从更改bool success = WinAPI.WriteProcessMemory((uint)target.Handle, allocMemAddress.ToInt64(), buffer, size, ref bytesWritten);bool success = WinAPI.WriteProcessMemory((uint)target.Handle, allocMemAddress.ToInt32(), buffer, size, ref bytesWritten);成功。

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章