首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CreateRemoteThread运行时没有错误,但什么也没有发生。

CreateRemoteThread运行时没有错误,但什么也没有发生。
EN

Stack Overflow用户
提问于 2021-06-30 18:57:27
回答 1查看 349关注 0票数 0

我正在尝试向进程中注入一个C++ dll,并且我使用一个C#控制台应用程序来运行它。我的问题是,程序运行,但似乎什么都没有发生,写成功,没有引发win32错误。

代码语言:javascript
复制
 class Program
{
    static void Main()
    {
        var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        var bootstrapperSettingsFilePath = Path.Combine(currentFolder, "bootstrapperSettings.json");
        var bootstrapperSettings = JsonConvert.DeserializeObject<BootstrapperSettings>(File.ReadAllText(bootstrapperSettingsFilePath));

        var startupInfo = new STARTUPINFO();

        CreateProcess(
            bootstrapperSettings.TargetPath,
            null,
            IntPtr.Zero,
            IntPtr.Zero,
            false,
            ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,
            IntPtr.Zero,
            null, 
            ref startupInfo,
            out PROCESS_INFORMATION processInfo);

        Thread.Sleep(1000);
        var processHandle = Process.GetProcessById((int)processInfo.dwProcessId).Handle;
        var loaderPath = Path.Combine(currentFolder, "Loader.dll");
        var loaderPathPtr = VirtualAllocEx(
            processHandle, 
            (IntPtr)0, 
            loaderPath.Length, 
            MemoryAllocationType.MEM_COMMIT, 
            MemoryProtectionType.PAGE_EXECUTE_READWRITE);
        Thread.Sleep(500);

        int error = Marshal.GetLastWin32Error();
        if (error > 0)
            throw new InvalidOperationException($"Failed to allocate memory for Loader.dll, error code: {error}");
        var bytes = Encoding.Unicode.GetBytes(loaderPath);
        var bytesWritten = 0;
        WriteProcessMemory(processHandle, loaderPathPtr, bytes, bytes.Length, ref bytesWritten);
        Thread.Sleep(1000);

        error = Marshal.GetLastWin32Error();
        if (error > 0 || bytesWritten == 0)
            throw new InvalidOperationException($"Failed to write Loader.dll into the process, error code: {error}");

        var loaderDllPointer = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");

        Thread.Sleep(1000);

        error = Marshal.GetLastWin32Error();
        if (error > 0)
            throw new InvalidOperationException($"Failed to get memory address to Loader.dll in the process, error code: {error}");

        CreateRemoteThread(processHandle, (IntPtr)null, (IntPtr)0, loaderDllPointer, loaderPathPtr, 0, (IntPtr)null);

        Thread.Sleep(1000);

        error = Marshal.GetLastWin32Error();
        if (error > 0)
            throw new InvalidOperationException($"Failed to create remote thread to start execution of Loader.dll in the process, error code: {error}");

        VirtualFreeEx(processHandle, loaderPathPtr, 0, MemoryFreeType.MEM_RELEASE);
    }
}

还有C++。这负责在WPF应用程序上调用方法,并在CLR启动和运行后初始化它。我希望至少点击其中的一个messagebox调用,但是没有显示任何内容。

代码语言:javascript
复制
#define WIN32_LEAN_AND_MEAN
#define FOR_DOTNET_4
#include <Windows.h>
#include <process.h>
#include <string>
#ifdef FOR_DOTNET_4
#include <metahost.h>
#else
#include <mscoree.h>
#endif
#include "CorError.h"

#pragma comment( lib, "mscoree" )

#define LOAD_DLL_FILE_NAME L"InjectionTest1.exe"
#define NAMESPACE_AND_CLASS L"InjectionTest1.Loader"
#define MAIN_METHOD L"Load"
#define MAIN_METHOD_ARGS L"NONE"

HMODULE g_myDllModule = NULL;

ICLRMetaHostPolicy* g_pMetaHost = NULL;
ICLRRuntimeInfo* g_pRuntimeInfo = NULL;
ICLRRuntimeHost* g_clrHost = NULL;

HANDLE g_hThread = NULL;
wchar_t* dllLocation = NULL;

#define MB(s) MessageBoxW(NULL, s, NULL, MB_OK);

unsigned __stdcall ThreadMain(void* pParam)
{
    MB(L"Test");
    HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&g_pMetaHost);

    if (FAILED(hr))
    {
        MB(L"Could not create instance of ICLRMetaHost");
        return 1;
    }
    
    DWORD pcchVersion = 0;
    DWORD dwConfigFlags = 0;

    hr = g_pMetaHost->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT,
        dllLocation, NULL,
        NULL, &pcchVersion,
        NULL, NULL,
        &dwConfigFlags,
        IID_ICLRRuntimeInfo,
        (LPVOID*)&g_pRuntimeInfo);

    if (FAILED(hr))
    {
        if (hr == E_POINTER)
        {
            MB(L"Could not get an instance of ICLRRuntimeInfo -- E_POINTER");
        }
        else if (hr == E_INVALIDARG)
        {
            MB(L"Could not get an instance of ICLRRuntimeInfo -- E_INVALIDARG");
        }
        else
        {
            wchar_t buff[1024];
            wsprintf(buff, L"Could not get an instance of ICLRRuntimeInfo -- hr = 0x%lx -- Is DomainManager.dll present?", hr);
            MB(buff);
        }

        return 1;
    }
    
    hr = g_pRuntimeInfo->BindAsLegacyV2Runtime();

    if (FAILED(hr))
    {
        MB(L"Failed to bind as legacy v2 runtime! (.NET 3.5 Mixed-Mode Support)");
        return 1;
    }

    hr = g_pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&g_clrHost);

    if (FAILED(hr))
    {
        MB(L"Could not get an instance of ICLRRuntimeHost!");
        return 1;
    }

    hr = g_clrHost->Start();

    if (FAILED(hr))
    {
        MB(L"Failed to start the CLR!");
        return 1;
    }

    DWORD dwRet = 0;
    hr = g_clrHost->ExecuteInDefaultAppDomain(dllLocation, NAMESPACE_AND_CLASS, MAIN_METHOD, MAIN_METHOD_ARGS, &dwRet);

    if (FAILED(hr))
    {
        MB(L"Failed to execute in the default app domain!");


        switch (hr)
        {
        case HOST_E_CLRNOTAVAILABLE:
            MB(L"CLR Not available");
            break;

        case HOST_E_TIMEOUT:
            MB(L"Call timed out");
            break;

        case HOST_E_NOT_OWNER:
            MB(L"Caller does not own lock");
            break;

        case HOST_E_ABANDONED:
            MB(L"An event was canceled while a blocked thread or fiber was waiting on it");
            break;

        case E_FAIL:
            MB(L"Unspecified catastrophic failure");
            break;

        default:
            char buff[128];
            sprintf(buff, "Result is: 0x%lx", hr);
            MessageBoxA(NULL, buff, "Info", 0);
            break;
        }

        return 1;
    }

    return 0;
}

void LoadClr()
{
    wchar_t buffer[255];
    if (!GetModuleFileNameW(g_myDllModule, buffer, 255))
        return;

    std::wstring modulePath(buffer);
    modulePath = modulePath.substr(0, modulePath.find_last_of('\\') + 1);
    modulePath = modulePath.append(LOAD_DLL_FILE_NAME);
    dllLocation = new wchar_t[modulePath.length() + 1];
    MB((modulePath).c_str());
    wcscpy(dllLocation, modulePath.c_str());
    dllLocation[modulePath.length()] = '\0';

    g_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadMain, NULL, 0, NULL);
}

BOOL WINAPI DllMain(HMODULE hDll, DWORD dwReason, LPVOID lpReserved)
{
    g_myDllModule = hDll;
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        MB(L"Loading");
        LoadClr();
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        if (g_clrHost)
        {
            g_clrHost->Stop();
            g_clrHost->Release();
        }
        
        if (g_hThread)
        {
            TerminateThread(g_hThread, 0);
            CloseHandle(g_hThread);
        }
    }

    return TRUE;
}

进口:

代码语言:javascript
复制
using System;
using System.Runtime.InteropServices;

namespace Bootstrapper
{
    static class WinImports
    {
        [DllImport("kernel32.dll")]
        internal static extern bool CreateProcess(
            string lpApplicationName,
            string lpCommandLine,
            IntPtr lpProcessAttributes,
            IntPtr lpThreadAttributes,
            bool bInheritHandles,
            ProcessCreationFlag dwCreationFlags,
            IntPtr lpEnvironment,
            string lpCurrentDirectory,
            ref STARTUPINFO lpStartupInfo,
            out PROCESS_INFORMATION lpProcessInformation);

        [DllImport("kernel32.dll")]
        internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll")]
        internal static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern bool CloseHandle(IntPtr hHandle);


        [DllImport("kernel32.dll")]
        internal static extern IntPtr VirtualAllocEx(
            IntPtr hProcess,
            IntPtr dwAddress,
            int nSize,
            MemoryAllocationType dwAllocationType,
            MemoryProtectionType dwProtect);

        [DllImport("kernel32.dll")]
        internal static extern bool WriteProcessMemory(
            IntPtr hProcess,
            IntPtr lpBaseAddress,
            byte[] lpBuffer,
            int dwSize,
            ref int lpNumberOfBytesWritten);

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

        [DllImport("kernel32.dll")]
        internal static extern bool VirtualFreeEx(
            IntPtr hProcess,
            IntPtr dwAddress,
            int nSize,
            MemoryFreeType dwFreeType);

        internal enum MemoryAllocationType
        {
            MEM_COMMIT = 0x1000
        }

        internal enum MemoryProtectionType
        {
            PAGE_EXECUTE_READWRITE = 0x40
        }

        internal enum MemoryFreeType
        {
            MEM_RELEASE = 0x8000
        }

        internal enum ProcessCreationFlag
        {
            CREATE_DEFAULT_ERROR_MODE = 0x04000000
        }

        internal struct STARTUPINFO
        {
            public uint cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        internal struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-30 19:37:34

您的注入器代码有许多问题:

CreateRemoteThread().

  • 通过CreateProcess() (您可以使用CreateProcess()代替Process.GetProcessById())泄漏HANDLE的输出

  • 没有在远程进程中分配足够的字节来保存loaderPath字符串,也没有将足够的字节复制到远程进程中。在分配内存时,需要将loaderPath.Length乘以2(System.Char大小)。更好的解决方案是在调用Encoding.Unicode.GetString()之前调用VirtualAllocEx(),然后分配bytes.length字节数。但是,请注意,LoadLibraryW()需要一个以空结尾的字符串,但您不会将空终止符复制到远程进程.

中。

  • 没有等待LoadLibraryW()在释放分配的内存之前实际完成运行(即远程线程终止)。

  • 错误处理错误处理.

  • Thread.Sleep()的调用是不必要的,应该删除.

尝试更像这样的东西:

代码语言:javascript
复制
class Program
{
    static void Main()
    {
        var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        var bootstrapperSettingsFilePath = Path.Combine(currentFolder, "bootstrapperSettings.json");
        var bootstrapperSettings = JsonConvert.DeserializeObject<BootstrapperSettings>(File.ReadAllText(bootstrapperSettingsFilePath));

        var startupInfo = new STARTUPINFO();

        if (!CreateProcess(
            bootstrapperSettings.TargetPath,
            null,
            IntPtr.Zero,
            IntPtr.Zero,
            false,
            ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,
            IntPtr.Zero,
            null, 
            ref startupInfo,
            out PROCESS_INFORMATION processInfo))
        {
            throw new InvalidOperationException($"Failed to start process, error code: {Marshal.GetLastWin32Error()}");
        }

        CloseHandle(processInfo.hThread);

        try
        {
            var loaderPath = Path.Combine(currentFolder, "Loader.dll") + "\0";
            var bytes = Encoding.Unicode.GetBytes(loaderPath);

            var loaderPathPtr = VirtualAllocEx(
                processInfo.hProcess,
                IntPtr.Zero,
                bytes.Length,
                MemoryAllocationType.MEM_COMMIT,
                MemoryProtectionType.PAGE_EXECUTE_READWRITE);

            if (loaderPathPtr == IntPtr.Zero)
                throw new InvalidOperationException($"Failed to allocate memory for Loader.dll, error code: {Marshal.GetLastWin32Error()}");

            try
            {
                var bytesWritten = 0;
                if (!WriteProcessMemory(processHandle, loaderPathPtr, bytes, bytes.Length, ref bytesWritten))
                {
                    throw new InvalidOperationException($"Failed to write Loader.dll path into the process, error code: {Marshal.GetLastWin32Error()}");
                }

                if (bytesWritten != bytes.Length)
                    throw new InvalidOperationException("Failed to write all bytes of Loader.dll path into the process");

                var loaderDllPointer = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");

                if (loaderDllPointer == IntPtr.Zero)
                    throw new InvalidOperationException($"Failed to get memory address to Loader.dll in the process, error code: {Marshal.GetLastWin32Error()}");

                var hRemoteThread = CreateRemoteThread(
                    processInfo.hProcess,
                    IntPtr.Zero,
                    0,
                    loaderDllPointer,
                    loaderPathPtr,
                    0,
                    IntPtr.Zero);

                if (hRemoteThread == IntPtr.Zero)
                {
                    throw new InvalidOperationException($"Failed to create remote thread to start execution of Loader.dll in the process, error code: {Marshal.GetLastWin32Error()}");
                }

                WaitForSingleObject(hRemoteThread, INFINITE);
                CloseHandle(hRemoteThread);
            }
            finally
            {
                VirtualFreeEx(processInfo.hProcess, loaderPathPtr, 0, MemoryFreeType.MEM_RELEASE);
            }
        }
        finally
        {
            CloseHandle(processInfo.hProcess);
        }
    }
}

也就是说,您的C++ DLL也是doing things it shouldn't be doing in DllMain()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68200288

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档