首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用CreateRemoteThread运行本机代码

使用CreateRemoteThread运行本机代码
EN

Stack Overflow用户
提问于 2022-07-13 17:46:43
回答 1查看 200关注 0票数 2

有点背景,这是我第一个关于堆栈溢出的问题,所以如果这是很难回答的,因为我的问题的质量,我很抱歉。

运行在:Windows1110.0.22000Build 22000,Intel x64,C++20,Mono4.5,VisualStudio2022(如果你需要知道别的什么,那就问)

我在这个问题上挣扎了几天。我一直在使用C++ Mono尝试将一个方法从C#类库(C#类库)注入到另一个进程。已经有一段时间了,我从要注入的方法中获得了MonoMethod对象,并且找到了多种执行它的方法,例如:

mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc)

mono_method_get_unmanaged_thunk(MonoMethod* method) (返回C/C++函数指针)

mono_compile_method(MonoMethod* method) (我一会儿再谈这个)

但问题是,所有这些都没有让我远程执行。我认为我最擅长的就是mono_compile_method(MonoMethod* method),因为文档告诉我This JIT-compiles the method, and returns the pointer to the native code produced.

博士:http://docs.go-mono.com/

mono_runtime_invoke和mono_method_get_unmanaged_thunk:http://docs.go-mono.com/?link=xhtml%3Adeploy%2Fmono-api-methods.html (向下滚动)

mono_compile_method位于左侧的“未排序”部分。

我想我可以在目标进程中分配一些内存,使用VirtualAllocExWriteProcessMemory将代码放入目标程序的地址空间,然后使用CreateRemoteThread执行它。

VirtualAllocExWriteProcessMemory总是成功的,就像CreateRemoteThread一样,不会抛出错误,但是它只做了一件事,那就是由于访问冲突而使目标进程崩溃。

这是我的尝试(注入代码):

代码语言:javascript
运行
复制
MonoAssembly* Manager::Inject(const char* dllpath, char *ass, UINT len)
{

    MonoClass* classs;
    MonoMethod* method;

    MonoDomain* domain = mono_jit_init("ass");

    
    MonoAssembly* asse = mono_domain_assembly_open(domain, dllpath);
    if (!asse)
    {
        std::cout << "Failed to open assembly.";
        return NULL;
    }

    MonoImage* monoImage = mono_assembly_get_image(asse);
    if (!monoImage)
    {
        std::cout << "Failed to get image from assembly.";
        return NULL;
    }
    classs = mono_class_from_name(monoImage, this->namespaceName.c_str(), this->className.c_str());
    if (!classs)
    {
        std::cout << "Failed to get class from name.";
        return NULL;
    }
    
    method = mono_class_get_method_from_name(classs, this->method.c_str(), -1);
    if (!method)
    {
        std::cout << "Failed to get method from name.";
        return NULL;
    }

    
    MonoObject* excPtr = nullptr;

    int size = 1024 * 8;
    void* code;
    code = mono_compile_method(method);

    if (handle)
    {

        void* loc = VirtualAllocEx(handle, NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        

        if (!loc)
        {
            std::cout << "VirtualAllocEx failed # " << GetLastError();
            return NULL;
        }


        SIZE_T written = 0;


        if (!WriteProcessMemory(handle, loc, code, size, &written))
        {
            std::cout << "WriteProcessMemory failed # " << GetLastError();
            return NULL;
        }
        std::cout << written << " bytes written.\n";


        HANDLE h = CreateRemoteThread(handle, NULL, 0, (LPTHREAD_START_ROUTINE)loc, NULL, 0, NULL);

        if (!h)
        {
            std::cout << "Failed to create remote thread # " << GetLastError();
            return NULL;
        }


        DWORD waitResult = WaitForSingleObject(h, -1);

        if (waitResult == WAIT_FAILED)
        {
            std::cout << "Failed to wait for remote thread. # " << GetLastError();
            return NULL;
        }


        DWORD error;

        if (!GetExitCodeThread(h, &error))
        {
            std::cout << "Failed to get thread exit code. # " << GetLastError();
            return NULL;
        }


        if (error == 3221225477)
        {
            std::cout << "An access violation occurred while executing.";
            return NULL;
        }


    } 
    else
    {
        std::cout << "Invalid handle! # " << GetLastError();
        return NULL;
    }
        


    CloseHandle(handle);
    return asse;

}

这是我的Dll,它包含将被注入的方法:

代码语言:javascript
运行
复制
using System;

namespace TestDll
{
    public class Class1
    {
        static void PrintText()
        {
            Console.WriteLine("HELLO FROM DLL");
        }
    }
}

这是我的测试目标应用程序的代码:

代码语言:javascript
运行
复制
using System;

namespace TestTarget
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "";
            while(true)
            {
                s = Console.ReadLine();
                if(s == "stop")
                {
                    break;
                }
            }
        }
    }
}

这是TestTarget在尝试注入时抛出的消息:

代码语言:javascript
运行
复制
The program '[9636] TestTarget.exe' has exited with code 3221225477 (0xc0000005) 'Access violation'.

我知道mono_compile_method可以工作,因为如果我尝试将返回值转换为函数指针并调用它:

代码语言:javascript
运行
复制
void (*code)() = (void(*)())mono_compile_method(method);
code();

它按预期工作,并打印

代码语言:javascript
运行
复制
HELLO FROM DLL

因此,它返回一个指向本机代码的指针(如果我是对的,它应该由CPU直接执行)。我想知道当我在CreateRemoteThread上使用它时,它为什么不能工作,因为我可以将它称为函数指针。我认为这是错误的/我写了指向内存的本机代码的指针,它指向我进程中的本机代码,但是天知道目标进程中有什么,因为进程有自己的地址空间。

如果我试图做的事情(将方法注入远程进程)是不可能的,那么请尝试并提供相应的技术。谢谢,如果你对我的问题(:D)有什么疑问,请问。

EN

回答 1

Stack Overflow用户

发布于 2022-07-14 02:02:22

您需要编写注入的数据和代码(而不是您指出的函数指针)到远程进程。三种注射方式的There is an example。值得注意的是CreateRemoteThread & WriteProcessMemory技术。

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

https://stackoverflow.com/questions/72970547

复制
相关文章

相似问题

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