CreateRemoteThread和WriteProcessMemory技术

示例程序:WinSpy

另一种注入代码到其他进程地址空间的方法是使用WriteProcessMemory API。这次你不用编写一个独立的DLL而是直接复制你的代码到远程进程(WriteProcessMemory)并用CreateRemoteThread执行之。

让我们看一下CreateRemoteThread的声明:

HANDLE CreateRemoteThread( 
   HANDLE hProcess,         // handle to process to create thread in 
   LPSECURITY_ATTRIBUTES lpThreadAttributes,   // pointer to security
                                              // attributes 
   DWORD dwStackSize,       // initial thread stack size, in bytes 
   LPTHREAD_START_ROUTINE lpStartAddress,      // pointer to thread 
                                              // function 
   LPVOID lpParameter,      // argument for new thread 
   DWORD dwCreationFlags,   // creation flags 
   LPDWORD lpThreadId       // pointer to returned thread identifier 
);

和CreateThread相比,有一下不同:
●增加了hProcess参数。这是要在其中创建线程的进程的句柄。 
●CreateRemoteThread的lpStartAddress参数必须指向远程进程的地址空间中的函数。这个函数必须存在于远程进程中,所以我们不能简单地传递一个本地ThreadFucn的地址,我们必须把代码复制到远程进程。 
●同样,lpParameter参数指向的数据也必须存在于远程进程中,我们也必须复制它。

现在,我们总结一下使用该技术的步骤:
1.   得到远程进程的HANDLE(OpenProcess)。 
2.   在远程进程中为要注入的数据分配内存(VirtualAllocEx)、 
3.   把初始化后的INJDATA结构复制到分配的内存中(WriteProcessMemory)。 
4.   在远程进程中为要注入的数据分配内存(VirtualAllocEx)。 
5.   把ThreadFunc复制到分配的内存中(WriteProcessMemory)。 
6.   用CreateRemoteThread启动远程的ThreadFunc。 
7.   等待远程线程的结束(WaitForSingleObject)。 
8.   从远程进程取回指执行结果(ReadProcessMemory 或 GetExitCodeThread)。 
9.   释放第2、4步分配的内存(VirtualFreeEx)。 
10.   关闭第6、1步打开打开的句柄。

另外,编写ThreadFunc时必须遵守以下规则: 
1.   ThreadFunc不能调用除kernel32.dll和user32.dll之外动态库中的API函数。只有kernel32.dll和user32.dll(如果被加载)可以保证在本地和目的进程中的加载地址是一样的。(注意:user32并不一定被所有的Win32进程加载!)参考附录A。如果你需要调用其他库中的函数,在注入的代码中使用LoadLibrary和GetProcessAddress强制加载。如果由于某种原因,你需要的动态库已经被映射进了目的进程,你也可以使用GetMoudleHandle代替LoadLibrary。同样,如果你想在ThreadFunc中调用你自己的函数,那么就分别复制这些函数到远程进程并通过INJDATA把地址提供给ThreadFunc。

2.   不要使用static字符串。把所有的字符串提供INJDATA传递。为什么?编译器会把所有的静态字符串放在可执行文件的“.data”段,而仅仅在代码中保留它们的引用(即指针)。这样,远程进程中的ThreadFunc就会执行不存在的内存数据(至少没有在它自己的内存空间中)。

3.   去掉编译器的/GZ编译选项。这个选项是默认的(看附录B)。 
4.   要么把ThreadFunc和AfterThreadFunc声明为static,要么关闭编译器的“增量连接(incremental linking)”(看附录C)。 
5.   ThreadFunc中的局部变量总大小必须小于4k字节(看附录D)。注意,当degug编译时,这4k中大约有10个字节会被事先占用。 
6.   如果有多于3tch分支的case语句,必须像下面这样分割开,或用if-else if代替.

case constant1: statement1; goto END; 
     case constant2: statement2; goto END; 
     case constant3: statement2; goto END; 
}

case constant4: statement4; goto END; 
     case constant5: statement5; goto END; 
     case constant6: statement6; goto END;

END:

=====简单的CreateRemoteThread例程-初学者必看

// _remotethreaddemo.cpp : Defines the entry point for the console application.
// Author:秋镇菜

#include "stdafx.h"
#include "windows.h"

// ========== 定义一个代码结构,本例为一个对话框============
struct MyData
{
 char sz[64]; // 对话框显示内容
 DWORD dwMessageBox; // 对话框的地址
};

// ========== 远程线程的函数 ==============================
DWORD __stdcall RMTFunc(MyData *pData)
{
 typedef int(__stdcall*MMessageBox)(HWND,LPCTSTR,LPCTSTR,UINT);
 MMessageBox MsgBox = (MMessageBox)pData->dwMessageBox;
 MsgBox(NULL, pData->sz, NULL, MB_OK);
 return 0;
}
int main(int argc, char* argv[])
{
// ===== 获得需要创建REMOTETHREAD的进程句柄 ===============================
 HWND hWnd = FindWindow("notepad", NULL); // 以NOTEPAD为例
 DWORD dwProcessId;
 ::GetWindowThreadProcessId(hWnd, &dwProcessId);
 HANDLE hProcess = OpenProcess(
        PROCESS_ALL_ACCESS,
        FALSE,
        dwProcessId);

// ========= 代码结构 ================================================
 MyData data;
 ZeroMemory(&data, sizeof (MyData));
 strcat(data.sz, "对话框的内容.");
 HINSTANCE hUser = LoadLibrary("user32.dll");
 if (! hUser)
 {
  printf("Can not load library. ");
  return 0;
 }
 data.dwMessageBox = (DWORD)GetProcAddress(hUser, "MessageBoxA");
 FreeLibrary(hUser);
 if (! data.dwMessageBox)
  return 0;

// ======= 分配空间 ===================================================
 void *pRemoteThread
  = VirtualAllocEx(hProcess, 0,
      1024*4, MEM_COMMIT|MEM_RESERVE,
      PAGE_EXECUTE_READWRITE);
 if (! pRemoteThread)
  return 0;
 if (! WriteProcessMemory(hProcess, pRemoteThread, &RMTFunc, 1024*4, 0))
  return 0;

MyData *pData
  = (MyData*)VirtualAllocEx(hProcess, 0,
      sizeof (MyData), MEM_COMMIT,
      PAGE_READWRITE);
 if (!pData)
  return 0;

if (! WriteProcessMemory(hProcess, pData, &data, sizeof (MyData), 0))
  return 0;

// =========== 创建远程线程 ===========================================
 HANDLE hThread
  = CreateRemoteThread(hProcess, 0,
       0, (LPTHREAD_START_ROUTINE)pRemoteThread,
       pData, 0, 0);
 if (! hThread)
 {
  printf("远程线程创建失败");
  return 0;
 }
 CloseHandle(hThread);
 VirtualFreeEx(hProcess, pRemoteThread, 1024*3, MEM_RELEASE);
 VirtualFreeEx(hProcess, pData, sizeof (MyData), MEM_RELEASE);
 CloseHandle(hProcess);
 printf("Hello World! ");
 return 0;
}

程序在windows xp下运行, 弹出messagebox之后, 只要点击确定宿主进程就会崩溃。 
而且不止是messagebox,调用其它的api函数也是一样,请问这是什么原因?有什么办法可以解决吗? 
--------------------------------------------------------

编译成RELEASE版本就不会出错了,主要是DEBUG版本加了一个__chkesp的函数导致调用了非法地址

CreateRemoteThread和WriteProcessMemory技术相关推荐

  1. 向其他进程注入代码的三种方法

    如何向其他线程的地址空间中注入代码并在这个线程的上下文中执行之? 目录: ●导言 ●Windows 钩子(Hooks) ●CreateRemoteThread 和LoadLibrary 技术 ○进程间 ...

  2. 远程注入利用远程线程直接注入

    利用远程线程无DLL直接注入 (okwary) 小叹的学习园地 注入代码到其他进程地址空间的方法是使用WriteProcessMemory API.这次你不用编写一个独立的DLL而是直接复制你的代码到 ...

  3. 金山词霸”屏幕取词技术揭密

    金山词霸"屏幕取词技术揭密                               "金山词霸"屏幕取词技术揭密(讨论稿)                       ...

  4. CreateRemoteThreadWriteProcessMemory技术 简要的

    CreateRemoteThread WriteProcessMemory 第三种方法的基本思想是拷贝一些代码到另一进程的地址空间中然后执行.这种方法代替了编写独立的DLL,而是直接将代码使用Writ ...

  5. 关于金山词霸的屏幕取词1

    "金山词霸"屏幕取词技术揭密(讨论稿) (17千字) 发信人:5,555 时 间:2001-11-1 9:30:12 详细信息: "金山词霸"屏幕取词技术揭密( ...

  6. 将代码注入到进程的三种方式

    [源码下载] 介绍 在Code Project网站有许多关于password spy的文章,但是这些都是基于Windows Hooks的,还有没有其他方式能实现这种效果呢?是的,有,不过,先让我们简要 ...

  7. 收集的计算机编程电子书目录,仅供日后查阅方便

    本人有收集电子书的癖好.每日在网上收集经典的电子书籍,尤其喜欢原版的,看起来舒服.不过总是心血来潮,当时下载后瞅几眼,之后就束之高阁,再也不问津了.很为此苦恼,过后找某本书时也总是不知道在哪,为了查找 ...

  8. Java实现lucene搜索功能

    直接上代码: package com.sand.mpa.sousuo;//--------------------- Change Logs---------------------- //<p ...

  9. VirtualAllocEx;WriteProcessMemory;CreateRemoteThread

    /* struct StrParam{HWND hPwdEdit;unsigned int nLenth;char* buff; };//计算器为目标进程. static DWORD WINAPI M ...

最新文章

  1. lt view gt android,RecyclerView的linearLayoutManager.findViewByPosition()问题
  2. flume的概述和运行机制
  3. 台州银行登录显示服务器异常,台州银行网上银行异常问题处理
  4. 某工程车零部件制造厂商
  5. 华为云原生数据仓库GaussDB(DWS)深度技术解读:融、快、大、稳、易
  6. poj 3087 Shuffle'm Up 模拟(map记录)
  7. 风投的钱都从哪里来?
  8. JDBC和JPA调用储存过程 接收存储过程有返回值
  9. grumble.js
  10. 在TFS2013上删除项目
  11. MySQL 浅谈NOT NULL和DEFAULT的关系
  12. 用Caffe搭建自己的网络,并用图片进行测试
  13. BP神经网络整定PID
  14. 追寻宇宙的形状--庞加莱猜想
  15. hive使用,及语法
  16. 《大学“电路分析基础”课程实验合集.实验四》丨线性电路特性的研究
  17. 抖音CLICKID+淘宝Relaitionid回传淘积木APP内下单--转化归因联调ROI程序算法及代码技术实现
  18. 服务器系统开机黑屏只有个鼠标,Win7系统开机却显示黑屏并只有鼠标光标该怎么办...
  19. 蓝色主机 bluehost主机 启用CloudFlare的cdn加速服务
  20. 2022-CS224n-Assignment1-exploring_word_vectors

热门文章

  1. Python 量化交易 数据分析学习之旅
  2. java 协变性_Java 泛型 协变性、逆变性
  3. 甘超波:目标管理该学习什么
  4. [连接 HarmpnyOS ]-使用 ADB+USB 进入华为鸿蒙系统
  5. 如何证明自己的软件著作权
  6. Windows云服务器如何进行PHP环境搭建?
  7. 炉石辛达苟斯贫民打法
  8. 新款 iMac 短期内不会支持 Face ID
  9. 让windows XP快10倍 德国人的优化补丁
  10. java教务系统登录界面代码_985、211高校教务管理系统源代码(java)