您的位置:首页 > 编程语言

win32向目标进程注入代码

2014-04-01 14:34 459 查看
下面代码演示了向“记事本”程序(NOTEPAD.EXE)的进程地址空间中注入我们自己写的函数代码,大致原理如下:

1. 提升注入(注意和“被注入”的区别)程序的进程访问权限

2. 随便打开一个记事本文件,注意是用NOTEPAD.EXE打开的

3. 查找NOTEPAD.EXE对应的进程ID,即Process ID

4. 以所有权限(包括read/write)打开NOTEPAD.EXE的进程ID

5. 在NOTEPAD.EXE的进程ID地址空间中,申请一块内存

6. 向刚刚申请的内存中,写入我们想要写的任何代码(注意:注入的代码中全部都用指针的形式调用相关数据和函数)

7. 我们写的代码不会自动执行,需要在被注入的进程中创建一个新的线程,调用注入的代码

-------------------------------------------------------------------------------------------------------------------------------

相关代码如下:

//整理:过客
//邮箱:386520874@qq.com
//日期:2014.04.01

#pragma once
#include <windows.h>
#include <TlHelp32.h>
#include "stdio.h"

//--------------------------------------------------------
typedef struct tagWNDINFO
{
DWORD dwProcId;
HWND hWnd;
} WNDINFO, *LPWNDINFO;

BOOL CALLBACK MyEnumProc(HWND hWnd,LPARAM lParam)
{
DWORD dwProcId;
GetWindowThreadProcessId(hWnd, &dwProcId); //获得hWnd对应的线程ID

LPWNDINFO pInfo = (LPWNDINFO)lParam;
if(dwProcId == pInfo->dwProcId) //判断是否是我们需要寻找的ID
{
pInfo->hWnd = hWnd;
return FALSE;
}

return TRUE;
}

HWND GetProcessMainWnd(DWORD dwProcId)
{
WNDINFO wi;

wi.dwProcId = dwProcId; //被查询窗口的进程ID
wi.hWnd = NULL;

EnumWindows(MyEnumProc,(LPARAM)&wi); //枚举窗口

return wi.hWnd; //返回dwProcId对应的窗口句柄
}

//--------------------------------------------------------
//线程参数结构体定义
typedef struct tagRemoteParam
{
char szTitle[60]; // MessageBox函数中窗口标题
char szMsg[60]; // MessageBox函数中显示的字符提示
DWORD dwMessageBox; // MessageBox函数的入口地址
} RemoteParam, *PRemoteParam;

//定义MessageBox类型的函数指针
typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);

//线程函数定义
DWORD __stdcall threadProc(LPVOID lParam)
{
RemoteParam* pRP = (RemoteParam*)lParam;
PFN_MESSAGEBOX pfnMessageBox;
pfnMessageBox = (PFN_MESSAGEBOX)pRP->dwMessageBox;
pfnMessageBox(NULL, pRP->szMsg, pRP->szTitle, 0);
return 0;
}

//提升进程访问权限
BOOL enableDebugPriv()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;

if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
return FALSE;
}
if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
{
CloseHandle(hToken);
return FALSE;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // 特权启用
if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) // 启用指定访问令牌的特权
{
CloseHandle(hToken);
return FALSE;
}
return TRUE;
}

//根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的ID
DWORD processNameToId(LPCTSTR lpszProcessName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
if(!Process32First(hSnapshot, &pe))
{
MessageBox(NULL, "The frist entry of the process list has not been copyied to the buffer", "Notice", MB_ICONINFORMATION | MB_OK);
return 0;
}
while(Process32Next(hSnapshot, &pe)) // 循环查找下一个进程
{
if(!strcmp(lpszProcessName, pe.szExeFile)) // 找到了
{
return pe.th32ProcessID;
}
}

return 0;
}

//-----------------------------------------------------------
int main(int argc, char* argv[])
{
//定义线程体的大小,实际分配的内存大小是页内存大小的整数倍
const DWORD dwThreadSize = 4096;
DWORD dwWriteBytes;

//提升进程访问权限
enableDebugPriv();

//等待输入进程名称,注意大小写匹配
char szExeName[MAX_PATH] = { 0 };
//	cout << "Please input the name of target process !" << endl;
//	cin >> szExeName; //接收命令行输入的字符串
//	cout << szExeName << endl;
//	strcpy(szExeName,"notepad.exe");
//	scanf("%s",szExeName);
sprintf(szExeName,"NOTEPAD.EXE");

DWORD dwProcessId = processNameToId(szExeName); //Name转换成ID
if(dwProcessId == 0)
{
MessageBox(NULL, "The target process have not been found !", "Notice", MB_ICONINFORMATION | MB_OK);
return -1;
}

HWND hWnd=GetProcessMainWnd(dwProcessId);
char szTile[MAX_PATH];
::GetWindowText(hWnd, szTile, MAX_PATH); //获得已经打开的记事本窗口的标题

//根据进程ID得到进程句柄
HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

if(!hTargetProcess)
{
MessageBox(NULL, "Open target process failed !", "Notice", MB_ICONINFORMATION | MB_OK);
return 0;
}

//在宿主进程中为线程体开辟一块存储区域
//在这里需要注意 MEM_COMMIT | MEM_RESERVE 内存分配类型以及PAGE_EXECUTE_READWRITE内存保护类型
//其具体含义请参考MSDN中关于VirtualAllocEx函数的说明。
void* pRemoteThread = VirtualAllocEx(hTargetProcess, 0, dwThreadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(!pRemoteThread)
{
MessageBox(NULL, "Alloc memory in target process failed !", "notice", MB_ICONINFORMATION | MB_OK);
return 0;
}

//将线程体拷贝到宿主进程中
if(!WriteProcessMemory(hTargetProcess, pRemoteThread, &threadProc, dwThreadSize, 0))
{
MessageBox(NULL, "Write data to target process failed !", "Notice", MB_ICONINFORMATION | MB_OK);
return 0;
}

//定义线程参数结构体变量
RemoteParam remoteData;
ZeroMemory(&remoteData, sizeof(RemoteParam)); //初始化

//填充结构体变量中的成员
HINSTANCE hUser32 = LoadLibrary("User32.dll");
remoteData.dwMessageBox = (DWORD)GetProcAddress(hUser32, "MessageBoxA"); //取得MessageBox API的地址
//	strcat(remoteData.szTitle, "新建文本文档");
int len=strlen(szTile);
szTile[len]='\0';
strcat(remoteData.szTitle, szTile); //MessageBox的标题
strcat(remoteData.szMsg, "Hello 你好吗?\\(^o^)/~"); //MessageBox的内容

//为线程参数在宿主进程中开辟存储区域
RemoteParam* pRemoteParam = (RemoteParam*)VirtualAllocEx(hTargetProcess , 0, sizeof(RemoteParam), MEM_COMMIT, PAGE_READWRITE);
if(!pRemoteParam)
{
MessageBox(NULL, "Alloc memory failed !", "Notice", MB_ICONINFORMATION | MB_OK);
return 0;
}

//将线程参数拷贝到宿主进程地址空间中
if(!WriteProcessMemory(hTargetProcess , pRemoteParam, &remoteData, sizeof(remoteData), 0))
{
MessageBox(NULL, "Write data to target process failed !", "Notice", MB_ICONINFORMATION | MB_OK);
return 0;
}

//在宿主进程中创建线程
HANDLE hRemoteThread = CreateRemoteThread(hTargetProcess, NULL, 0, (DWORD (__stdcall *)(void *))pRemoteThread, pRemoteParam, 0, &dwWriteBytes);
if(!hRemoteThread)
{
MessageBox(NULL, "Create remote thread failed !", "Notice",  MB_ICONINFORMATION | MB_OK);
return 0;
}

CloseHandle(hRemoteThread);
FreeLibrary(hUser32);
return 0;
}


---------------------------------------------------------------------

测试运行结果如下:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: