CreateRemoteThread API 函数心得

来源:互联网 发布:java单例设计模式 编辑:程序博客网 时间:2024/06/15 20:36

原帖地址:http://blog.csdn.net/xiadasong007/archive/2009/10/14/4668863.aspx

 

 

 

 

昨天晚上找到了个有意思的API CreateRemoteThread(),它可以在别的进程中创建自己需要的线程,我想这个函数在做坏事上肯定很拿手哈~,当然,技术没有好坏,用得好是天使,用得坏是魔鬼,关键在于人。

许多API是值得花时间看的,虽然不好懂,但作用强大,因此这里总结一下这个函数的心得,以后若忘了也容易捡起来。

1:我们的目的是这样的:我们启动进程A,让A在进程B中增加一个线程S,然后进程A结束,然后S在B中正常工作,比如说打印一条"hello world“。

2:这个过程遇到了些问题,下面简要说明下:

(1):进程B中需要为新线程S添加2个区域,即CODE段和DATA段,让我们想想单纯的汇编中的CODE SEGMENT和DATA SEGMENT。CODE段大小直接为一页即可,不就4KB嘛,没必要计算CODE的真正空间大小。

(2):DATA段是必须的,除非你的线程函数不调用其他函数(这样没什么意思吧),DATA段通常传入一个自定义结构,这个结构非常重要,所有的操作都在结构里面了。

(3):只要搞定了这2个段,就可以CreateRemoteThread了,但还有一些细节问题需要注意,比如如何通过进程名(任务管理器)得到进程ID,进而得到句柄,比如如何加载DLL(我前面刚讲DLL哈~)。

3:最后还有一个问题,请不要使用DEBUG模式执行,请在Release下编译链接执行,否则你的B就有危险了!

参考代码如下:(转自http://blog.csdn.net/vcforever/archive/2005/03/15/319872.aspx,我这里省了许多东西,目的是为了更加清楚的看清流程,请原作者勿怪,对了,请把QQ打开哈)

// Test.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"
#pragma comment(lib, "advapi32.lib")
#include <windows.h>
#include <TlHelp32.h>
#include <iostream>
using namespace std;

//线程参数结构体定义
typedef struct _RemoteParam {
char szMsg[12]; //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->szMsg, 0);

return 0;
}

//根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的ID
DWORD processNameToId(LPCTSTR lpszProcessName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);

if (!Process32First(hSnapshot, &pe)) {
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;

//等待输入进程名称,注意大小写匹配

DWORD dwProcessId = processNameToId("QQ.exe");

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

void* pRemoteThread = VirtualAllocEx(hTargetProcess, 0,
dwThreadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

//将线程体拷贝到宿主进程中
if (!WriteProcessMemory(hTargetProcess,
pRemoteThread, &threadProc, dwThreadSize, 0)) {
return 0;
}
//定义线程参数结构体变量
RemoteParam remoteData;

//填充结构体变量中的成员
HINSTANCE hUser32 = LoadLibrary("User32.dll");
remoteData.dwMessageBox = (DWORD)GetProcAddress(hUser32, "MessageBoxA");
FreeLibrary(hUser32);
strcat(remoteData.szMsg, "Hello/0");

//为线程参数在宿主进程中开辟存储区域
RemoteParam* pRemoteParam = (RemoteParam*)VirtualAllocEx(
hTargetProcess , 0, sizeof(RemoteParam), MEM_COMMIT, PAGE_READWRITE);

//将线程参数拷贝到宿主进程地址空间中
if (!WriteProcessMemory(hTargetProcess ,
pRemoteParam, &remoteData, sizeof(remoteData), 0)) {
return 0;
}

//在宿主进程中创建线程
HANDLE hRemoteThread = CreateRemoteThread(
hTargetProcess, NULL, 0, (DWORD (__stdcall *)(void *))pRemoteThread,
pRemoteParam, 0, &dwWriteBytes);

CloseHandle(hRemoteThread);
return 0;
}

原创粉丝点击