揰掵佲 发表于 2021-3-17 18:01

利用shellCode跨进程调用函数x86

之前发过一个帖子,是用易语言实现的
调用QQ/TIM算法实现获取当前登陆账号和ClientKey
https://www.52pojie.cn/thread-1037514-1-1.html

最近这段时间呢,一直在搞跨进程调用,经过不断的测试,找到一个稳定跨进程调用的方法,简单明了.易语言比较熟练,代码早已经封装完成,这次用的是C++还是以https://www.52pojie.cn/thread-1037514-1-1.html为例子跨进程取出指定QQ进程的QQ号
先看效果

然后说一下思路
在进程中利用以下代码调用函数,可以达到稳定0000000055                push ebp
0000000189E5            mov ebp, esp
00000003C9                leave
0000000458                pop eax
00000005870424            xchg eax,
00000008FFE0            jmp eax
0000000A89EC            mov esp, ebp
0000000C5D                pop ebp
0000000DC3                ret

构建的远程调用函数有最大支持15个参数的传递,只支持int类型
/*
* 定义调用函数的代码
* push ebp
* mov ebp,esp
* sub esp,0x3c
* push arg15
* push arg14
* push arg13
* push arg12
* push arg11
* push arg10
* push arg9
* push arg8
* push arg7
* push arg6
* push arg5
* push arg4
* push arg3
* push arg2
* push arg1
* call pCallFun    //这里需要注意的是,我们call的是上面的汇编代码,并非指定的函数
* mov dword ,eax
* add esp,0x3c
* mov esp,ebp
* pop ebp
* ret
*/

代码比较粗糙,贴上来
void getPushBin(int arg, LPVOID& pShellCode, HANDLE hProcess)
{
    if (arg >= -128 && arg <= 127)
    {
      unsigned char code = { 106 };
      WriteProcessMemory(hProcess, pShellCode, &code, 1, NULL);
      pShellCode = LPVOID((int)pShellCode + 1);
      WriteProcessMemory(hProcess, pShellCode, (LPVOID)arg, 1, NULL);
      pShellCode = LPVOID((int)pShellCode + 1);
    }
    else {
      unsigned char code = { 104 };
      WriteProcessMemory(hProcess, pShellCode, &code, 1, NULL);
      pShellCode = LPVOID((int)pShellCode + 1);
      WriteProcessMemory(hProcess, pShellCode, (LPVOID)&arg, 4, NULL);
      pShellCode = LPVOID((int)pShellCode + 4);
    }

}

void getCallBin(int src, int Dest, LPVOID& pShellCode, HANDLE hProcess)
{
    unsigned char code = { 232 };
    WriteProcessMemory(hProcess, pShellCode, &code, 1, NULL);
    pShellCode = LPVOID((int)pShellCode + 1);
    int arg = Dest - src - 5;
    WriteProcessMemory(hProcess, pShellCode, (LPVOID)&arg, 4, NULL);
    pShellCode = LPVOID((int)pShellCode + 4);
}

void getresEaxBin(int src, LPVOID& pShellCode, HANDLE hProcess)
{
    unsigned char code = { 163 };
    WriteProcessMemory(hProcess, pShellCode, &code, 1, NULL);
    pShellCode = LPVOID((int)pShellCode + 1);
    WriteProcessMemory(hProcess, pShellCode, (LPVOID)&src, 4, NULL);
    pShellCode = LPVOID((int)pShellCode + 4);
}
int runRemoteFunc(HANDLE hProcess, int pFunc, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0, int arg6 = 0, int arg7 = 0, int arg8 = 0, int arg9 = 0, int arg10 = 0, int arg11 = 0, int arg12 = 0, int arg13 = 0, int arg14 = 0, int arg15 = 0) {




    /*
    * 定义callFunCode 这个是调用call的代码
      0000000055                push ebp
      0000000189E5            mov ebp, esp
      00000003C9                leave
      0000000458                pop eax
      00000005870424            xchg eax,
      00000008FFE0            jmp eax
      0000000A89EC            mov esp, ebp
      0000000C5D                pop ebp
      0000000DC3                ret
   */
    unsigned char callFunCode[] = { 85, 137, 229, 201, 88, 135, 4, 36, 255, 224, 137, 236, 93, 195 };
    SIZE_T codelen = sizeof(callFunCode);
    //分配适当内存
    LPVOID pCallFun = VirtualAllocEx(hProcess, NULL, codelen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //准备写入代码
    bool res = WriteProcessMemory(hProcess, pCallFun, callFunCode, codelen, NULL);
    if (!res)
    {
      //写入失败,释放内存
      MessageBox(NULL, L"写入shellCode失败", L"提示", 0);
      VirtualFreeEx(hProcess, pCallFun, 0, MEM_RELEASE);
      return -1;
    }
    //分配调用函数的地址
    LPVOID pShellCodeStart = VirtualAllocEx(hProcess, NULL, 0x200, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //保存原有地址
    LPVOID pShellCode = pShellCodeStart;
    //分配返回值地址


    LPVOID resEax = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    /*
    * 定义调用函数的代码
    * push ebp
    * mov ebp,esp
    * sub esp,0x3c
    * push arg15
    * push arg14
    * push arg13
    * push arg12
    * push arg11
    * push arg10
    * push arg9
    * push arg8
    * push arg7
    * push arg6
    * push arg5
    * push arg4
    * push arg3
    * push arg2
    * push arg1
    * call pCallFun
    * mov dword ,eax
    * add esp,0x3c
    * mov esp,ebp
    * pop ebp
    * ret
    */

    unsigned char pfunHead = { 85,137,229,131,236,60 };
    codelen = sizeof(pfunHead);
    WriteProcessMemory(hProcess, pShellCode, pfunHead, codelen, NULL);
    pShellCode = LPVOID((int)pShellCode + codelen);
    getPushBin(arg15, pShellCode, hProcess);
    getPushBin(arg14, pShellCode, hProcess);
    getPushBin(arg13, pShellCode, hProcess);
    getPushBin(arg12, pShellCode, hProcess);
    getPushBin(arg11, pShellCode, hProcess);
    getPushBin(arg10, pShellCode, hProcess);
    getPushBin(arg9, pShellCode, hProcess);
    getPushBin(arg8, pShellCode, hProcess);
    getPushBin(arg7, pShellCode, hProcess);
    getPushBin(arg6, pShellCode, hProcess);
    getPushBin(arg5, pShellCode, hProcess);
    getPushBin(arg4, pShellCode, hProcess);
    getPushBin(arg3, pShellCode, hProcess);
    getPushBin(arg2, pShellCode, hProcess);
    getPushBin(arg1, pShellCode, hProcess);
    getCallBin((int)pShellCode, pFunc, pShellCode, hProcess);
    getresEaxBin((int)resEax, pShellCode, hProcess);
    unsigned char pfunEnd[] = { 131,196,60,137,236,93,195 };
    codelen = sizeof(pfunEnd);
    WriteProcessMemory(hProcess, pShellCode, pfunEnd, codelen, NULL);
    pShellCode = LPVOID((int)pShellCode + codelen);
    DWORD Tid;
    HANDLE tHandle = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pShellCodeStart, NULL, NULL, &Tid);
    if (!tHandle)
    {
      VirtualFreeEx(hProcess, pCallFun, 0, MEM_RELEASE);
      VirtualFreeEx(hProcess, resEax, 0, MEM_RELEASE);
      VirtualFreeEx(hProcess, pShellCodeStart, 0, MEM_RELEASE);
      MessageBox(NULL, L"执行线程失败失败", L"提示", 0);
      return -1;
    }
    WaitForSingleObject(tHandle, -1);
    int resa = 0;
    ReadProcessMemory(hProcess, resEax, &resa, 4, 0);
    VirtualFreeEx(hProcess, pCallFun, 0, MEM_RELEASE);
    VirtualFreeEx(hProcess, resEax, 0, MEM_RELEASE);
    VirtualFreeEx(hProcess, pShellCodeStart, 0, MEM_RELEASE);
    return resa;
}



int main()
{
    int nRetCode = 0;
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, 20368);// 人懒固定了QQ的PID
    HMODULE hModule = LoadLibraryW(L"kernel32.dll");
    int pGetModuleHandleA = (int)GetProcAddress(hModule, "GetModuleHandleA");
    int pGetProcAddress = (int)GetProcAddress(hModule, "GetProcAddress");
    unsigned char dllName[] = "KernelUtil.dll";
    unsigned char funName[] = "?GetSelfUin@Contact@Util@@YAKXZ";
    LPVOID pDllName = VirtualAllocEx(hProcess, NULL, sizeof(dllName), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hProcess, pDllName, &dllName, sizeof(dllName), 0);
    LPVOID pFunName = VirtualAllocEx(hProcess, NULL, sizeof(funName), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hProcess, pFunName, &funName, sizeof(funName), 0);
    int kernelMoudle = runRemoteFunc(hProcess, pGetModuleHandleA, (int)pDllName);
    int getUin = runRemoteFunc(hProcess, pGetProcAddress, kernelMoudle, (int)pFunName);
    int res = runRemoteFunc(hProcess, getUin);
    CloseHandle(hProcess);
    cout << "函数执行完毕:结果是\n\r";
    cout << res;
    cout << "\n\r\n\r";
    return nRetCode;
}

其中 以下3个函数是构建汇编代码的,因为,当无参调用时,默认为0 从unsigned char* 之后会缺少,导致汇编代码错乱,所以分别在函数内部直接写入到内存

getPushBin //push xxx
getCallBin //call xxx
getresEaxBin //mov dword ,eax
求指教如何解决,代码比较糙,轻喷

**** Hidden Message *****

wylksy 发表于 2021-3-17 18:08

感谢分享

mangmangxiyu 发表于 2021-3-17 18:11

厉害,感谢分享

turuoyang 发表于 2021-3-17 18:20

学习学习

智趣库 发表于 2021-3-17 18:27

学到了,感觉分享

lin326326 发表于 2021-3-17 18:43

厉害,感谢分享

朱朱你堕落了 发表于 2021-3-17 20:05

孤陋寡闻了,第一次吹说跨进程调用的,膜拜大佬。

揰掵佲 发表于 2021-3-17 20:09

朱朱你堕落了 发表于 2021-3-17 20:05
孤陋寡闻了,第一次吹说跨进程调用的,膜拜大佬。

表述不好,也叫远程

bester 发表于 2021-3-17 22:28

看起来得实际跑一下代码才能看得懂

夜泉 发表于 2021-3-18 04:52

感谢发布原创作品,吾爱破解论坛因你更精彩{:301_1001:}
页: [1] 2
查看完整版本: 利用shellCode跨进程调用函数x86