win32相关(远程线程和远程线程注入)

远程线程和远程线程注入


CreateRemoteThread函数

作用:创建在另一个进程的虚拟地址空间中运行的线程

HANDLE CreateRemoteThread([in]  HANDLE                 hProcess,				// 需要在哪个进程中创建线程[in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,		// 安全描述符[in]  SIZE_T                 dwStackSize,				// 分配的堆栈大小[in]  LPTHREAD_START_ROUTINE lpStartAddress,			// 要执行的函数[in]  LPVOID                 lpParameter,				// 参数[in]  DWORD                  dwCreationFlags,			// 控制线程创建的标志[out] LPDWORD                lpThreadId				// 返回线程id
);

和我们 CreateThread 函数相比也就多了一个hProcess参数


远程线程

#include<iostream>
#include<windows.h>// 参数:进程ID,进程内函数地址
BOOL myCreateRemoteThread(DWORD dwProcessId,DWORD dwProcAddr) {// 获取进程句柄DWORD dwThreadId = 0;HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);if (hProcess == NULL) {std::cout << "打开进程失败!,错误码:" << GetLastError() << std::endl;return FALSE;}// 创建远程线程HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)dwProcAddr, NULL, 0, NULL);if (hThread == NULL) {std::cout << "创建远程线程失败!,错误码:" << GetLastError() << std::endl;return FALSE;}getchar();// 释放资源CloseHandle(hProcess);CloseHandle(hThread);return TRUE;
}int main()
{	 获取窗口句柄//HWND hWind = FindWindow(NULL, L"进程A.exe");//DWORD pid; 通过窗口句柄获取进程ID和线程id//GetWindowThreadProcessId(hWind,&pid);// 我们先使用硬编码的方式来测试 myCreateRemoteThread(10872, 0x00007FF76ECD2220);return 0;
}

现在我们可以在其它进程中创建一个新的线程,然后执行它里面的方法


远程线程注入

那如果我们要在其他进程中执行自己的代码要怎么办呢?

这就是用到注入的技术了,所谓注入就是在第三方进程不知道或者不允许的情况下将模块或者代码写入对方进程空间,并设法执行的技术

常见的注入方式:

  • 远程线程注入
  • APC注入
  • 消息钩子注入
  • 注册表注入(已淘汰 需要早期系统版本支撑)
  • 导入表注入
  • 输入法注入

在CreateRemoteThread方法中,有一个参数lpStartAddress,这个参数是一个返回类型为4/8个字节,接收的参数类型也是4/8个字节的方法(字节数与当前是多少位的系统相关)

DWORD WINAPI ThreadProc(LPVOID lpParameter
);

还有一个函数和ThreadProc很像,也是只有一个参数(4个字节),返回类型也是4个字节,那就是LoadLibrary这个函数

HMODULE LoadLibrary(LPCSTR lpLibFileName
);

这样以来我们就可以把LoadLibrary函数替换成ThreadProc函数去执行,我们回想一下,执LoadLibrary需要有一个参数,这个参数就是我们dll的路径,但是这个dll路径是不能放在我们当前进程的,进程之前的数据都隔离的,所以具体的实现步骤为以下几点

  1. 在要注入的进程中分配空间,存储dll的路径
  2. 获取LoadLibrary的函数地址
  3. 创建远程线程,执行LoadLibrary函数

接下来我们来看一下具体的实现流程

DLL注入模块的编写

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
extern "C" __declspec(dllimport) void __stdcall MyPrintWindow(); // pch.hDWORD WINAPI ThreadProc(LPVOID lpParameter)  { for (;;){Sleep(1000);std::cout << "注入的代码在执行。。。\n";}return 0;
}BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;}return TRUE;
}

实现注入功能的代码

#include<iostream>
#include<windows.h>
#include <tlhelp32.h>// 两个参数,processId要注入的进程ID,dllAddress dll的地址
BOOL LoadDLL(DWORD dwProcessId,const WCHAR* pDllAddressStr) {BOOL bRet = FALSE;HANDLE hProcess = NULL;HANDLE hThread;DWORD dwLength;DWORD64 dwLoadAddr = NULL;LPVOID lpAllocAddr;DWORD dwThreadId;HMODULE hModule;// 1.获取进程句柄hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);if (hProcess == NULL) {std::cout << "打开进程失败!,错误码:" << GetLastError() << std::endl;return FALSE;}// 2.计算Dll路径名称长度dwLength = (lstrlen(pDllAddressStr) + 1) * sizeof(WCHAR);// 3.在目标进程中申请内存 参数1,目标进程句柄,参数2,内存起始地址,参数3,内存大小,参数4,内存属性已提交,参数5,具有读写权限lpAllocAddr = VirtualAllocEx(hProcess, NULL, dwLength, MEM_COMMIT, PAGE_READWRITE);if (lpAllocAddr == NULL) {std::cout << "分配置内存失败!,错误码:" << GetLastError() << std::endl;CloseHandle(hProcess);return FALSE;}// 4.把Dll路径名称复制到刚刚分配的目标进程内存当中bRet = WriteProcessMemory(hProcess, lpAllocAddr, pDllAddressStr, dwLength, NULL);if (!lpAllocAddr) {std::cout << "写目标进程内存失败!,错误码:" << GetLastError() << std::endl;CloseHandle(hProcess);return FALSE;}// 5.获取模块地址hModule = GetModuleHandle(L"Kernel32.dll");if (!hModule) {std::cout << "获取模块失败!,错误码:" << GetLastError() << std::endl;CloseHandle(hProcess);return FALSE;}// 6.获取LoadLibraryW函数地址dwLoadAddr = (DWORD64)GetProcAddress(hModule, "LoadLibraryW");if (!dwLoadAddr) {std::cout << "函数地址失败!,错误码:" << GetLastError() << std::endl;CloseHandle(hProcess);CloseHandle(hModule);return FALSE;}// 7.创建远程线程,加载dllhThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)dwLoadAddr, lpAllocAddr, 0, NULL);if (hThread == NULL) {std::cout << "加载dll失败!,错误码:" << GetLastError() << std::endl;CloseHandle(hProcess);CloseHandle(hModule);return FALSE;}CloseHandle(hThread);return TRUE;}// 遍历进程id
DWORD FindConsoleExePid(const WCHAR* exeName) {HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hSnap != INVALID_HANDLE_VALUE){setlocale(LC_ALL, "chs");PROCESSENTRY32 pe32 = { 0 };pe32.dwSize = sizeof(pe32);BOOL bRet = Process32First(hSnap, &pe32);while (bRet){//wprintf(L"%s %d\r\n", pe32.szExeFile, pe32.th32ProcessID);if (lstrcmp(pe32.szExeFile, exeName) == 0){// 返回pidreturn pe32.th32ParentProcessID;}bRet = Process32Next(hSnap, &pe32);}CloseHandle(hSnap);}return 0;
}int main()
{DWORD dwProcessId = FindConsoleExePid(L"远程线程");//注入dllif (LoadDLL(dwProcessId, L"C:\\Users\\BananaLi\\Desktop\\注入DLL.dll")) {std::cout << "注入成功\n";}else{std::cout << "注入失败\n";}return 0;}

我们来一步步的分析下代码

// 1.获取进程句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

首先要知道要往哪个进程中注入,就要获取它的句柄

// 2.计算Dll路径名称长度
dwLength = (lstrlen(pDllAddressStr) + 1) * sizeof(WCHAR);

我们要把LoadLibraryW的参数也就是dll的路径地址传递进去,要计算字符串的长度,后面好分配空间

// 3.在目标进程中申请内存 参数1,目标进程句柄,参数2,内存起始地址,参数3,内存大小,参数4,内存属性已提交,参数5,具有读写权限
lpAllocAddr = VirtualAllocEx(hProcess, NULL, dwLength, MEM_COMMIT, PAGE_READWRITE);

我们要在目标进程中开辟一块空间用来存入我们的dll地址:0x0x0000014922cd0000
在这里插入图片描述
在这里插入图片描述

// 4.把Dll路径名称复制到刚刚分配的目标进程内存当中
bRet = WriteProcessMemory(hProcess, lpAllocAddr, pDllAddressStr, dwLength, NULL);

运行后我们发现我们dll的路径已经写入到了目标进程的空间
在这里插入图片描述
// 5.获取模块地址
hModule = GetModuleHandle(L"Kernel32.dll");
// 6.获取LoadLibraryW函数地址
dwLoadAddr = (DWORD64)GetProcAddress(hModule, “LoadLibraryW”);

我们会发现不管在任何程序当中都会有ntdll.dll,kernel32.dll这些模块,并且他们的模块地址和函数地址在任何进程中都是固定的,然而我们的LoadLibraryW就在kernel32.dll这个模块当中

在这里插入图片描述
在这里插入图片描述
// 7.创建远程线程,加载dll

最后就是CreateRemoteThread函数加载我们的LoadLibraryW函数,然后在加载LoadLibraryW函数时,创建一个新的线程执行我们需要执行的方法就可以了

在这里插入图片描述
查看模块,我们dll也被识别出来了
在这里插入图片描述
最后还有一个函数是用来退出的

  • FreeLibraryAndExitThread // 卸载自己并退出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/85886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flyway

Flyway 是一个强大的数据库版本控制和迁移工具&#xff0c;主要用于管理数据库结构的变更和演进。 核心作用 1. 数据库版本控制 追踪数据库变更&#xff1a;记录每次数据库结构的修改版本管理&#xff1a;为每个变更分配版本号变更历史&#xff1a;完整记录数据库演进过程 …

【深尚想】OPA855QDSGRQ1运算放大器IC德州仪器TI汽车级高速8GHz增益带宽的全面解析

1. 元器件定义与核心特性 OPA855QDSGRQ1 是德州仪器&#xff08;TI&#xff09;推出的一款 汽车级高速运算放大器&#xff0c;专为宽带跨阻放大&#xff08;TIA&#xff09;和电压放大应用优化。核心特性包括&#xff1a; 超高速性能&#xff1a;增益带宽积&#xff08;GBWP&a…

机器学习实验八--基于pca的人脸识别

基于pca的人脸识别 引言&#xff1a;pca1.pca是什么2.PCA算法的基本步骤 实例&#xff1a;人脸识别1.实验目的2.实现步骤3.代码实现4.实验结果5.实验总结 引言&#xff1a;pca 1.pca是什么 pca是一种统计方法&#xff0c;它可以通过正交变换将一组可能相关的变量转换成一组线…

【LLIE专题】NTIRE 2025 低照度图像增强第二名方案

Towards Scale-Aware Low-Light Enhancement via Structure-Guided Transformer Design&#xff08;2025&#xff0c;NTIRE&#xff09; 专题介绍一、研究背景二、SG-LLIE方法1.和Retinexformer方案对比2.总体方案及创新点3.详细方案3.1 结构先验提取3.2 网络结构3.3 损失函数 …

泊松融合的介绍和OpenCV教程

泊松融合 Poisson Blending 简介 核心思想 泊松融合的目标是在保留剪切图像的梯度(纹理)信息的同时,使融合结果在边界区域平滑过渡到目标图像中。换句话说,它在融合区域中重建一个图像,使其梯度尽可能接近源图像的梯度,并且边界贴合目标图像。 数学描述 泊松融合将问题…

Unity协程Coroutine与UniTask对比

原理对比 CoroutineUniTask本质IEnumerator 的协作调度器async/await 状态机&#xff08;IAsyncStateMachine&#xff09;调度方式Unity 内部调用 MoveNext()自建 PlayerLoopRunner 控制状态推进内存管理引用类型&#xff0c;频繁分配 GC结构体 UniTask&#xff0c;低 GC 压力…

MAC软件打开提示已损坏:“已损坏,打不开。您应将它移到废纸篓“

打开「终端.app」&#xff0c;输入以下命令并回车&#xff0c;输入开机密码回车 sudo spctl --master-disable 按照上述步骤操作完成后&#xff0c;打开「系统偏好设置」-「安全与隐私」-「通用」&#xff0c;确保已经修改为「任何来源」。 打开「终端.app」&#xff0c;输入…

JAVA之 Lambda

Java Lambda Lambda 表达式是 Java 8 的核心特性&#xff0c;通过 函数式编程 大幅简化代码。其核心思想是将行为作为参数传递&#xff0c;替代匿名内部类&#xff0c;提升代码的简洁性和可读性。以下是系统解析和完整代码示例&#xff1a; 一、Lambda 表达式基础 语法结构 (…

Starrocks中RoaringBitmap杂谈

背景 最近在阅读Starrocks源码的时候&#xff0c;遇到ColumnRefSet的RoaringBitmap使用&#xff0c;所以借此来讨论一下RoaringBitmap这个数据结构,这种思想是很值得借鉴的。 对于的实现可以参考一下 <dependency><groupId>org.roaringbitmap</groupId><…

数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)

目录 &#x1f50d; 若用递归计算每一项&#xff0c;会发生什么&#xff1f; Horners Rule&#xff08;霍纳法则&#xff09; 第一步&#xff1a;我们从最原始的泰勒公式出发 第二步&#xff1a;从形式上重新观察展开式 &#x1f31f; 第三步&#xff1a;引出霍纳法则&…

从Java的Jvm的角度解释一下为什么String不可变?

从Java的Jvm的角度解释一下为什么String不可变&#xff1f; 从 JVM 的角度看&#xff0c;Java 中 String 的不可变性是由多层次的机制共同保障的&#xff0c;这些设计涉及内存管理、性能优化和安全保障&#xff1a; 1. JVM 内存模型与字符串常量池 字符串常量池&#xff08;St…

初识硬编码(x86指令描述)

硬编码 任何一个程序其实都可以看做两部分组成的&#xff0c;指令和数据 cpu并没有明确的规定哪些要当做数据&#xff0c;哪些要当做指令来执行&#xff0c;把数据给EIP只要是遵循了指定的格式&#xff08;x86 x64 ARM&#xff09;&#xff0c;cpu都会当做指令来执行 x86/x64…

3.RV1126-OPENCV 图像叠加

一.功能介绍 图像叠加&#xff1a;就是在一张图片上放上自己想要的图片&#xff0c;如LOGO&#xff0c;时间等。有点像之前提到的OSD原理一样。例如&#xff1a;下图一张图片&#xff0c;在左上角增加其他图片。 二.OPENCV中图像叠加常用的API 1. copyTo方法进行图像叠加 原理…

MySQL垂直分库(基于MyCat)

参考资料&#xff1a; 参考视频 参考博客 Mycat基本部署 视频参考资料&#xff1a;链接: https://pan.baidu.com/s/1xT_WokN_xlRv0h06b6F3yg 提取码: aag3 概要&#xff1a; 本文的垂直分库&#xff0c;全部是基于前文部署的基本架构进行的 垂直分库&#xff1a; 垂直分库…

Spitfire:Codigger 生态中的高性能、安全、分布式浏览器

Spitfire 是 Codigger 生态系统中的一款现代化浏览器&#xff0c;专为追求高效、隐私和分布式技术的用户设计。它结合了 Codigger 的分布式架构优势&#xff0c;在速度、安全性和开发者支持方面提供了独特的解决方案&#xff0c;同时确保用户对数据的完全控制。 1. 高性能浏览…

1-【源码剖析】kafka核心概念

从今天开始开始在csdn上记录学习的笔记&#xff0c;主要包括以下几个方面&#xff1a; kafkaflinkdoris 本系列笔记主要记录Kafka学习相关的内容。在进行kafka源码学习之前&#xff0c;先介绍一下Kafka的核心概念。 消息 消息是kafka中最基本的数据单元&#xff0c;由key和…

互联网大厂Java求职面试:云原生架构下的微服务网关与可观测性设计

互联网大厂Java求职面试&#xff1a;云原生架构下的微服务网关与可观测性设计 郑薪苦怀着忐忑的心情走进了会议室&#xff0c;对面坐着的是某大厂的技术总监张总&#xff0c;一位在云原生领域有着深厚积累的专家。 第一轮面试&#xff1a;微服务网关的设计挑战 张总&#xf…

【HarmonyOS 5】针对 Harmony-Cordova 性能优化,涵盖原生插件开发、线程管理和资源加载等关键场景

1. ‌原生图片处理插件&#xff08;Java&#xff09; package com.example.plugin; import ohos.media.image.ImageSource; import ohos.media.image.PixelMap; import ohos.app.Context; public class ImageProcessor { private final Context context; public ImagePro…

Java-IO流之缓冲流详解

Java-IO流之缓冲流详解 一、缓冲流概述1.1 什么是缓冲流1.2 缓冲流的工作原理1.3 缓冲流的优势 二、字节缓冲流详解2.1 BufferedInputStream2.1.1 构造函数2.1.2 核心方法2.1.3 使用示例 2.2 BufferedOutputStream2.2.1 构造函数2.2.2 核心方法2.2.3 使用示例 三、字符缓冲流详…

健康检查:在 .NET 微服务模板中优雅配置 Health Checks

&#x1f680; 健康检查&#xff1a;在 .NET 微服务模板中优雅配置 Health Checks &#x1f4da; 目录 &#x1f680; 健康检查&#xff1a;在 .NET 微服务模板中优雅配置 Health Checks一、背景与意义 &#x1f50d;二、核心配置 &#x1f527;2.1 引入必要的 NuGet 依赖 &…