原理通过挂起线程(SuspendThread),设置线程(SetThreadContext)上下文中的eip(rip)方式注入。 //ThreadInject.h

#pragma once


// ThreadInject 对话框

class ThreadInject : public CDialogEx
{
	DECLARE_DYNAMIC(ThreadInject)

public:
	ThreadInject(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~ThreadInject();

// 对话框数据
	enum { IDD = IDD_DIALOG2 };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	// 进程ID
	DWORD m_dwPid;
	CString m_strDllPath;
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedButton4();
};

//ThreadInject.cpp

// ThreadInject.cpp : 实现文件
//

#include "stdafx.h"
#include "MyInjectTool.h"
#include "ThreadInject.h"
#include "afxdialogex.h"

//777A01D5    68 78563412     push    12345678
//777A01DA    9C              pushfd
//777A01DB    60              pushad

//777A01EB    61              popad
//777A01EC    9D              popfd
//777A01ED    C3              retn
//结构必须字节对齐1
#pragma pack(1)  
typedef struct _INJECT_CODE
{
	BYTE  byPUSH;
	DWORD dwPUSH_VALUE;
	BYTE  byPUSHFD;
	BYTE  byPUSHAD;
	BYTE  byMOV_EAX;          //mov eax, addr szDllpath
	DWORD dwMOV_EAX_VALUE;
	BYTE  byPUSH_EAX;         //push eax
	BYTE  byMOV_ECX;          //mov ecx, LoadLibrary
	DWORD dwMOV_ECX_VALUE;
	WORD  wCALL_ECX;          //call ecx
	BYTE  byPOPAD;
	BYTE  byPOPFD;
	BYTE  byRETN;
	CHAR  szDllPath[MAX_PATH];
}INJECT_CODE, *PINJECT_CODE;
#pragma pack()  


// ThreadInject 对话框

IMPLEMENT_DYNAMIC(ThreadInject, CDialogEx)

ThreadInject::ThreadInject(CWnd* pParent /*=NULL*/)
	: CDialogEx(ThreadInject::IDD, pParent)
	, m_dwPid(0)
	, m_strDllPath(_T(""))
{

}

ThreadInject::~ThreadInject()
{
}

void ThreadInject::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, m_dwPid);
	DDX_Text(pDX, IDC_EDIT4, m_strDllPath);
}


BEGIN_MESSAGE_MAP(ThreadInject, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON2, &ThreadInject::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &ThreadInject::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &ThreadInject::OnBnClickedButton4)
END_MESSAGE_MAP()


// ThreadInject 消息处理程序


void ThreadInject::OnBnClickedButton2()
{
	// TODO:  在此添加控件通知处理程序代码
	char szFilter[] = "动态链接库|*.dll";
	CFileDialog fileDlg(TRUE, "dll", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
	UpdateData(TRUE);
	if (fileDlg.DoModal() == IDOK)
	{
		m_strDllPath = fileDlg.GetPathName();
	}
	UpdateData(FALSE);

}

HANDLE g_hProcess = 0;
LPVOID g_lpBuffer = NULL;
void ThreadInject::OnBnClickedButton3()
{
	// TODO:  在此添加控件通知处理程序代码
	//打开目标进程
	BOOL   bRet = 0;
	
	INJECT_CODE ic = { 0 };
	THREADENTRY32 te32 = { 0 };
	HANDLE hThreadSnap = NULL;
	DWORD dwThreadId = 0;
	HANDLE hThread = NULL;
	CONTEXT oldContext = { 0 };
	CONTEXT newContext = { 0 };
	DWORD dwOldEip = 0;
	//打开进程
	g_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwPid);
	
	if (!g_hProcess)
	{
		MessageBox("OpenProcess 失败");
		return;
	}


	g_lpBuffer = VirtualAllocEx(g_hProcess, NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (!g_lpBuffer)
	{
		MessageBox("VirtualAllocEx 失败");
		return;
	}

	//给ShellCode结构体赋值
	ic.byPUSH			= 0x68;
	ic.dwPUSH_VALUE		= 0x12345678;   //用于保存原来的返回地址
	ic.byPUSHFD			= 0x9C;
	ic.byPUSHAD			= 0x60;
	ic.byMOV_EAX		= 0xB8;
	ic.dwMOV_EAX_VALUE = (DWORD)g_lpBuffer + offsetof(INJECT_CODE, szDllPath);
	ic.byPUSH_EAX		= 0x50;
	ic.byMOV_ECX		= 0xB9;
	ic.dwMOV_ECX_VALUE  = (DWORD)&LoadLibrary;
	ic.wCALL_ECX		= 0xD1FF;
	ic.byPOPAD			= 0x61;
	ic.byPOPFD			= 0x9D;
	ic.byRETN			= 0xC3;
	memcpy(ic.szDllPath, m_strDllPath.GetBuffer(0), m_strDllPath.GetLength());

	//写入ShellCode
	bRet = WriteProcessMemory(g_hProcess, g_lpBuffer, &ic, sizeof(ic), NULL);
	if (!bRet)
	{
		MessageBox("写入内存失败");
		return;
	}

	//创建线程快照查找目标程序主线程
	te32.dwSize = sizeof(te32);
	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hThreadSnap == INVALID_HANDLE_VALUE)
	{
		MessageBox("CreateToolhelp32Snapshot 失败");
		return;
	}

	//遍历查询目标程序主线程ID
	if (Thread32First(hThreadSnap, &te32))
	{
		do
		{
			if (m_dwPid == te32.th32OwnerProcessID)
			{
				dwThreadId = te32.th32ThreadID;
				break;
			}
		} while (Thread32Next(hThreadSnap, &te32));
	}
	
	//打开目标主线程
	hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);

	if (!OpenThread)
	{
		MessageBox("OpenThread 失败");
		return;
	}

	//挂起目标主线程
	bRet = SuspendThread(hThread);

	if (bRet == -1)
	{
		MessageBox("SuspendThread 失败");
		return;
	}

	oldContext.ContextFlags = CONTEXT_FULL;
	bRet = GetThreadContext(hThread, &oldContext);
	if (!bRet)
	{
		MessageBox("GetThreadContext 失败");
		return;
	}
	newContext = oldContext;


#ifdef _WIN64
	newContext.Rip = (DWORD)g_lpBuffer;
	dwOldEip = oldContext.Rip;
#else 
	newContext.Eip = (DWORD)g_lpBuffer;
	dwOldEip = oldContext.Eip;
#endif

	//;将指针指向ShellCode第一句push 12345678h中的地址,写入返回地址
	bRet = WriteProcessMemory(g_hProcess, ((char*)g_lpBuffer) + 1, &dwOldEip, sizeof(DWORD), NULL);
	if (!bRet)
	{
		MessageBox("写入内存失败");
		return;
	}

	bRet = SetThreadContext(hThread, &newContext);

	if (!bRet)
	{
		MessageBox("SetThreadContext 失败");
		return;
	}

	//然后把主线程跑起来
	bRet = ResumeThread(hThread);
	
	if (bRet == -1)
	{
		MessageBox("ResumeThread 失败");
		return;
	}


}


void ThreadInject::OnBnClickedButton4()
{
	// TODO:  在此添加控件通知处理程序代码
	if (!VirtualFreeEx(g_hProcess, g_lpBuffer, 0, MEM_RELEASE))
	{
		MessageBox("VirtualFreeEx 失败");
		return;
	}

	MessageBox("释放对方空间成功");
}