• [远程Call]32位远程多参数带返回调用


    [远程Call]32位远程多参数带返回调用

    引子

    在Windows上可以使用CreateRemoteThread实现远程Call,但是有不带返回值且只能传递一个参数的限制。

    解决思路

    将多个参数利用VirtualAllocEx和WriteProcessMemory写入目标程序,再通过此方法注入一段shellcode,通过shellcode完成多参数的调用。

    核心shellcode
    push var_1
    ...
    push var_n
    mov eax,function_addr
    /*
    如果为 cdcel则需要平栈
    add esp,count_param
    */
    call eax
    实现c++代码
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    LPVOID RemoteNew(HANDLE hProcess, PUCHAR data,size_t size)
    {
        auto hMem=VirtualAllocEx(hProcess, NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (hMem == NULL)
        {
            return FALSE;
        }
        if (WriteProcessMemory(hProcess, hMem, data, size,NULL) == FALSE)
        {
            VirtualFreeEx(hProcess, hMem, 0, MEM_RELEASE);
            return FALSE;
        }
        return hMem;
    }
    
    
    BOOL RemoteCall(
        HANDLE hProcess,
        LPVOID remoteFuncAddr,
        vector param,
        bool cdcelCall,
        bool waitRemoteThread 
    )
    {
        if (remoteFuncAddr == NULL)
            return FALSE;
    
        vector shellcode;
        //push 结构
    
        for (int i = param.size() - 1; i >= 0; i--)//调用栈是个栈
        {
            if (((UINT)param[i]) <= 255) //小参数可以只传低位
                shellcode.push_back(106), shellcode.push_back((UCHAR)param[i]); //push byte
            else
                shellcode.push_back(104), shellcode.insert(shellcode.end(), (PUCHAR)¶m[i], (PUCHAR)(¶m[i] + 1)); //push dword
        }
        //把addr塞入寄存器
        shellcode.push_back(184); //mov
        shellcode.insert(shellcode.end(), (PUCHAR)&remoteFuncAddr, (PUCHAR)(&remoteFuncAddr + 1)); //eax,addr
        shellcode.push_back(255),shellcode.push_back(208);//call eax
    
      
        if (cdcelCall)
        {
            size_t paramSize = param.size() * sizeof(LPVOID);
            //cdcel是函数调用后平栈,stdcall是函数自己平
            shellcode.push_back(129), shellcode.push_back(196);//add esp
            shellcode.insert(shellcode.end(), (PUCHAR)¶mSize, (PUCHAR)(¶mSize + 1));
        }
        shellcode.push_back(195);//ret
        auto shellcodeAddr=RemoteNew(hProcess, shellcode.data(), shellcode.size() * sizeof(UCHAR));
        if (shellcodeAddr == NULL)
            return FALSE;
       
        auto hThread=CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)shellcodeAddr, NULL, NULL, NULL);
        if (hThread == NULL)
        {
            VirtualFreeEx(hProcess, shellcodeAddr, 0, MEM_RELEASE);
            return FALSE;
        }
    
        thread waiter([hThread, hProcess, shellcodeAddr] {
            WaitForSingleObject(hThread, INFINITE);
            VirtualFreeEx(hProcess, shellcodeAddr, 0, MEM_RELEASE);
            DWORD retCode;
            GetExitCodeThread(hThread, &retCode);
            cout <<"Ret: " << retCode << endl;
        });
        if (waitRemoteThread)
            waiter.join();
        else
            waiter.detach();
    
        return TRUE;
    }
    
    int add(int a, int b)
    {
        return a + b;
    }
    
    int main()
    {
        char a[] = "hello world";
        char b[] = "C++ YES";
    
        //-1是自己
        RemoteCall((HANDLE)-1, add, { (LPVOID)1,(LPVOID)3 }, true, true);
    
        auto p1 = RemoteNew((HANDLE)-1, (PUCHAR)a, sizeof(a));
        auto p2 = RemoteNew((HANDLE)-1, (PUCHAR)b, sizeof(b));
        RemoteCall((HANDLE)-1, MessageBoxA, { 0, p1,p2,(LPVOID)64 }, true, true);
    
    
        std::cout << "Hello World!\n";
        Sleep(-1);
    }
    实现缺陷
    1. 目前只能实现32位的远程调用,64位新增了内存的可执行权限,这样注入的shellcode没法执行。

    2. 返回值只能接受32位整数,其实实现64位整数和浮点的方法也不复杂,都可以用汇编把对应寄存器的值写到内存里,但是情况比较多,懒得写了。


    __EOF__

  • 本文作者: Ice
  • 本文链接: https://www.cnblogs.com/Icys/p/RemoteCall.html
  • 关于博主: I am a student.
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    在线聊天系统,即时通讯系统
    Linux:环境变量
    ConsensusClusterPlus包进行聚类分析
    HTTP版本、状态码
    MySQL学习笔记(七)——数据处理之增删改
    【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.8 绘图事件
    开源的大模型
    uniCloud 如何创建数据表
    关于docker启动时报错binlog权限问题
    前后端分离的后台管理系统源码,快速开发OA、CMS网站后台管理、毕业设计项目
  • 原文地址:https://www.cnblogs.com/Icys/p/RemoteCall.html