[远程Call]32位远程多参数带返回调用
来源:博客园时间:2023-08-25 22:13:40


(资料图)

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

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

解决思路

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

核心shellcode
push var_1...push var_nmov 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);}
实现缺陷

目前只能实现32位的远程调用,64位新增了内存的可执行权限,这样注入的shellcode没法执行。

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

关键词: