CreateRemoteThread API 函数心得

来源:互联网 发布:工程中标数据网 编辑:程序博客网 时间:2024/05/18 03:23

昨天晚上找到了个有意思的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;
}

原创粉丝点击