首页
论坛
课程
招聘
[开源分享] [原创]利用shellCode跨进程调用函数x86
2021-3-17 17:56 2734

[开源分享] [原创]利用shellCode跨进程调用函数x86

2021-3-17 17:56
2734

之前发过一个帖子,是用易语言实现的.

[原创]调用QQ/TIM算法实现获取当前登陆账号和ClientKey


https://bbs.pediy.com/thread-255014.htm


最近这段时间呢,一直在搞跨进程调用,经过不断的测试,找到一个稳定跨进程调用的方法,简单明了.

易语言比较熟练,代码早已经封装完成,这次用的是C++

还是以https://bbs.pediy.com/thread-255014.htm帖子为例子

跨进程取出指定QQ进程的QQ号


先贴效果


然后说一下思路


在进程中利用以下代码调用函数,可以达到稳定

	  00000000  55                push ebp
	  00000001  89E5              mov ebp, esp
	  00000003  C9                leave
	  00000004  58                pop eax
	  00000005  870424            xchg eax, [esp]
	  00000008  FFE0              jmp eax
	  0000000A  89EC              mov esp, ebp
	  0000000C  5D                pop ebp
	  0000000D  C3                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 [resEax],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的代码
	  00000000  55                push ebp
	  00000001  89E5              mov ebp, esp
	  00000003  C9                leave
	  00000004  58                pop eax
	  00000005  870424            xchg eax, [esp]
	  00000008  FFE0              jmp eax
	  0000000A  89EC              mov esp, ebp
	  0000000C  5D                pop ebp
	  0000000D  C3                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 [resEax],eax
	* add esp,0x3c
	* mov esp,ebp
	* pop ebp
	* ret
	*/

	unsigned char pfunHead[6] = { 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 [xxx],eax

求指教如何解决,代码比较糙,轻喷


[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年秋季班火热招生!!

上传的附件:
收藏
点赞2
打赏
分享
最新回复 (3)
雪    币: 161
活跃值: 活跃值 (96)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
装饭的桶_342083 活跃值 2021-6-11 05:25
2
0
新手请教问题,再用上面的方法取key的时候,不知道shellcode哪一行错误导致 QQ直接崩溃。请大佬赐教啊。我的QQ是 2628014483  希望大牛百忙之中赐教啊啊啊啊
雪    币: 2126
活跃值: 活跃值 (636)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
htpidk 活跃值 2021-6-11 08:10
3
0
/*
    * 定义调用函数的代码
    * 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 [resEax],eax
    * add esp,0x3c
    * mov esp,ebp
    * pop ebp
    * ret
    */

/*
    * 定义callFunCode 这个是调用call的代码
      00000000  55                push ebp
      00000001  89E5              mov ebp, esp
      00000003  C9                leave
      00000004  58                pop eax
      00000005  870424            xchg eax, [esp]
      00000008  FFE0              jmp eax
      0000000A  89EC              mov esp, ebp
      0000000C  5D                pop ebp
      0000000D  C3                ret
   */
你这两段汇编能正常工作吗,在你这里jmp eax=jmp arg1,我看你的runRemoteFunc(hProcess, pGetModuleHandleA, (int)pDllName)这些里面arg1并不是一个函数地址啊
游客
登录 | 注册 方可回帖
返回