createthread函数详解_createremotethread

createthread函数详解_createremotethreadCreateRemoteThread和WriteProcessMemory技术示例程序:WinSpy另一种注入代码到其他进程地址空间的方法是使用WriteProcessMemoryAPI。这次你不用编写一个独立的DLL而是直接复制你的代码到远程进程(WriteProcessMemory)并用CreateRemoteThread执行之。让我们看一下CreateRemoteThread

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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
;
}

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

——————————————————–
 

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/194389.html原文链接:https://javaforall.net

(0)
上一篇 2025年11月6日 下午8:43
下一篇 2025年11月6日 下午9:22


相关推荐

  • 向 J2EE 架构师 学习之路[通俗易懂]

    向 J2EE 架构师 学习之路[通俗易懂]首先表明下这个只是个人记录,看到觉得很烂莫怪。认真看点书学点知识,脚踏实地的走,记录学到的东西,收获的东西,慢慢的成长。今天心血来潮,想看下书,百度搜索了下到csdn下载了一本《TheJ2EEArchitect’sHandbook》,毕竟想成为J2EE架构师自己觉得自己路还很长,一直觉得自己很笨,做事方法肯定有问题,一会看js,一会看java,一会看j2ee,感觉确认很烦,自己未来…

    2022年6月24日
    30
  • 光场相机可以计算光线的方向,也可以计算目标的深度_相机感光器在哪里

    光场相机可以计算光线的方向,也可以计算目标的深度_相机感光器在哪里博主最近在搞光场相机方面的研究啦,好了废话不多说,开始!1.一些前言废话首先,来一下光场的基本概念,来自百度百科。光场(lightfield):就是指光在每一个方向通过每一个点的光量。从概念里

    2022年8月3日
    8
  • office 快捷键

    office 快捷键Word1 用于设置字符格式和段落格式的快捷键 nbsp Ctrl Shift P 改变字号 office 适用 nbsp Ctrl Shift 增大字号 PPT 适用 nbsp Ctrl Shift nbsp Ctrl 逐磅增大字号 PPT 适用 nbsp Ctrl 逐磅减小字号 PPT 适用 nbsp Ctrl D 字体快捷键 nbsp Shift F3 切换字母大小写 PPT 适用 nbsp Ctrl Shift A 将

    2026年3月19日
    1
  • Mybatis RowBounds 分页原理「建议收藏」

    Mybatis RowBounds 分页原理「建议收藏」在mybatis中,使用RowBounds进行分页,非常方便,不需要在sql语句中写limit,即可完成分页功能。但是由于它是在sql查询出所有结果的基础上截取数据的,所以在数据量大的sql中并不适用,它更适合在返回数据结果较少的查询中使用最核心的是在mapper接口层,传参时传入RowBounds(intoffset,intlimit)对象,即可完成分页注意:由于java允许的最大整数为2147483647,所以limit能使用的最大整数也是214748…

    2025年12月9日
    6
  • 在Vs Code中搭建JSP开发环境

    在Vs Code中搭建JSP开发环境如何在 VisualStudio 中搭建 JSP 网页的开发环境准备 VisualStudio 和 Java 开发环境 VsCode 的安装不再赘述首先需要在 vscode 中搭建好 Java 的开发环境 安装 java 环境的扩展插件下载 jdk 建议使用 jdk11 若有梯子可以上官网下载 没有的话建议去清华大学的镜像站下载下载好之后将 JDK 的环境变量配置好 配置 JDK 的环境变量网上已经有大量资料 不再赘述 特别提醒系统变量中必须要有一个叫 JAVA

    2026年3月26日
    2
  • 一起学JAVA API Object String StringBuffer/StringBuilder

    一起学JAVA API Object String StringBuffer/StringBuilder1前言亲爱的小伙伴萌,目前我们看到的是Java基础部分的一个新的部分API,这是个啥,又能做啥呢?其实可以概括成一句话:帮助我们站在巨人的肩膀上,实现更加高效的开发,那么我们来一探究竟吧~2什么是APIAPI(ApplicationProgrammingInterface,应用程序接口)是一些预先定义的函数。目的是提供应用程序与开发人员基于某软件可以访问的一些功能集,但又无需访问源码或理解内部工作机制的细节.API是一种通用功能集,有时公司会将API作为其公共开放系统,也就是公司制定自己的

    2022年5月25日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号