远程线程注入DLL

摘要:
0x00原理介绍:上一篇文章介绍了如何在Windows下的其他进程中创建远程线程:https://www.cnblogs.com/DarkBright/p/10820582.html调用CreateRemoteThread创建远程线程所需的过程函数的标准形式为:DWORDWINAPIThreadProc(_In_LPVOIDlpParameter);Win32编程加载DLL的API是:HMOD
0x00 原理介绍:

上一篇文章介绍了在Windows下如何在其他进程创建一个远程线程:https://www.cnblogs.com/DarkBright/p/10820582.html

调用 CreateRemoteThread 创建远程线程所需要的过程函数的标准形式为:

DWORD WINAPI ThreadProc(
  _In_ LPVOID lpParameter
);

Win32编程加载DLL的API为:

HMODULE WINAPI LoadLibrary(
  _In_ LPCTSTR lpFileName
);

观察发现 ThreadProc 与 LoadLibrary 函数类型是一致的,所以可以通过 CreateRemoteThread 在其他的进程中创建一个线程调用 LoadLibrary 加载我们准备的DLL

系统启动后,kernel32.dll 的加载基址在各个进程中是相同的,因此导出函数(LoadLibrary)的地址也相同,即自己程序空间的LoadLibrary函数地址和其他进程空间的LoadLibrary函数地址相同

1

0x01 目标程序:

目标程序与上一篇文章(https://www.cnblogs.com/DarkBright/p/10820582.html)中的一致:

#include <windows.h>
#include <stdio.h>

void Fun(void)
{
     for(size_t i = 0; i < 10; i++)
         printf("%s addr:0x%p ", __FUNCTION__, Fun);
}

int main(int argc, char* argv[])
{
     Fun();
     //MessageBox(NULL, TEXT("执行完成!"), TEXT("提示"), MB_OK);

    getchar();
     return 0;
}

编译生成 Project1.exe

0x02 要注入的DLL:

在DLL成功注入到目标进程之后弹出一个信息框,代码如下:

BOOL APIENTRY DllMain( HMODULE hModule,
                        DWORD  ul_reason_for_call,
                        LPVOID lpReserved
                      )
{
     switch (ul_reason_for_call)
     {
     case DLL_PROCESS_ATTACH:
         MessageBox(NULL, TEXT("DLL注入成功!"), TEXT("提示"), MB_OK);
     case DLL_THREAD_ATTACH:
     case DLL_THREAD_DETACH:
     case DLL_PROCESS_DETACH:
         break;
     }
     return TRUE;
}

将生成的TestDLL.dll拷贝至桌面

0x03 注入程序:

注入程序编写流程大致如下:

1、 获取目标进程的句柄

2、 向目标进程中申请一片内存,要能够容纳 DLL路径信息字符串 的长度

3、 将 DLL路径信息字符串 写入到步骤2申请的内存中

4、 获取注入程序中 LoadLibraryA 的函数地址(前面已经说明该地址在目标程序中同样适用)

5、 调用 CreateRemoteThread 在目标进程中创建一个线程,该线程调用 LoadLibraryA 加载我们准备的DLL

具体实现代码如下:

#include <windows.h>
#include <string.h>
#include "Process.h"

#define        NAME    L"Project1.exe"
#define        DLL_NAME    "C:\Users\DarkBright\Desktop\TestDLL.dll"
//#define  DLL_NAME    "TestDLL.dll"

int main(int argc, char* argv[])
{
     Process* pProcess = new Process(NAME, FALSE);
     if (pProcess->hProcess == NULL) {
         OutputDebugString(TEXT("未找到目标进程! "));
         DWORD ret = GetLastError();
         exit(-1);
     }
     //OutputDebugString(TEXT("已找到目标进程! "));
     PVOID pDllName = VirtualAllocEx(pProcess->hProcess, NULL, strlen(DLL_NAME)+1,
                                     MEM_COMMIT, PAGE_READWRITE);
     if(pDllName == NULL){
         delete pProcess;
         OutputDebugString(TEXT("分配空间失败! "));
         exit(-1);
     }
     pProcess->WriteByteArray(pDllName, (BYTE *)DLL_NAME, strlen(DLL_NAME) + 1);
     HMODULE hModule = GetModuleHandle(TEXT("Kernel32.dll"));
     if(hModule == NULL){
         VirtualFreeEx(pProcess->hProcess, pDllName, 0, MEM_RELEASE);
         delete pProcess;
         OutputDebugString(TEXT("GetModuleHandle失败! "));
         exit(-1);
     }
     FARPROC pfnLoadLibraryA = GetProcAddress(hModule, "LoadLibraryA");
     HANDLE hThread = CreateRemoteThread(pProcess->hProcess, NULL, 0,
                                         (LPTHREAD_START_ROUTINE)pfnLoadLibraryA,
                                         pDllName, 0, NULL);
     if(hThread == NULL){
         VirtualFreeEx(pProcess->hProcess, pDllName, 0, MEM_RELEASE);
         delete pProcess;
         OutputDebugString(TEXT("CreateRemoteThread失败! "));
         exit(-1);
     }
     CloseHandle(hThread);

    delete pProcess;
     return 0;
}

#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )

其中 Process 类的相关内容参考:https://www.cnblogs.com/DarkBright/p/10809092.html

最后一行:#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" ) 表示隐藏控制台

运行 Project1.exe 并且适用调试器附加(注意是附加,不要直接用调试器打开程序):

2

将 TestDLL.dll 拷贝至桌面后运行注入程序:

3

弹框提示注入成功,并且在调试器的模块列表中也可以发现新注入的DLL

免责声明:文章转载自《远程线程注入DLL》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇P1082丛林探险pycharm连接git的方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

多线程中的lua同步问题

最近写paintsnow::start时出现了一个非常麻烦的BUG,程序的Release版本大约每运行十几次就会有一次启动时崩溃(Debug版本还没崩溃过),崩溃点也不固定。经过简单分析之后,确定是线程同步的问题。于是便修改了线程通信的代码,并使用pthread_mutex_lock/unlock来防止冲突。重新编译后,崩溃频率有所减少。但是每运行约四十次...

ManualResetEvent 与 AutoResetEvent 的理解和使用

在多线程开发中,时常用到ManualResetEvent 与AutoResetEvent 。 它们如同道路交通中的信号灯。两者之间有什么区别呢? 共同点: 均继承EventWaitHandle 接口,因此,均具有以下功能: Reset() //红灯 Set() //绿灯 WaitOne() // 等待信号 ManualResetEvent mre = ne...

什么是 Daemon 线程?它有什么意义?

所谓后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线 程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程 结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说, 只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用 setDaemon()方法,才能把它设置为后台线程。注意:后台进程在不...

window消息机制

剖析Windows消息处理机制 前一段,帮人写了个小控件,又温习了一遍Windows消息处理机制,现在把一些知识点总结出来,供大家参考.1.窗口 Windows程序是由一系列的窗口构成的,每个窗口都有自己的窗口过程,窗口过程就是一个拥有有固定 Signature 的 C函数,具体格式如下: LRESULT CALLBACK WindowProc(HWND...

Java线程间通信-回调的实现方式

Java线程间通信-回调的实现方式   Java线程间通信是非常复杂的问题的。线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互。   比如举一个简单例子,有一个多线程的类,用来计算文件的MD5码,当多个这样的线程执行的时候,将每个文件的计算的结果反馈给主线程,并从控制台输出。   线程之间的通讯主要靠回调来实现,回调的概念说...

java问题排查工具之一板斧jstack——使用 jstack 定位 java进程CPU过高的问题

 jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下: jstack [option] pid jstack [option] executable core jstack [option] [server-id@]remote-hostname-or-ip 参数说明: -l long listings,会打印出额外的锁...