DLL注入技术简介
DLL注入技术
属于是非常笼统了,基本没有啥自己写的东西qaq
一.dll注入的概念
当一个进程运行时,它会加载并使用一些动态链接库(DLL)来提供额外的功能和资源。这些DLL可以被多个进程共享,使得代码重用和资源共享变得更加高效。DLL注入技术利用了这种共享机制。它允许向正在运行的进程中注入一个动态链接库(DLL),被注入的DLL可以利用它所在的进程的权限执行一些特殊的任务,比如修改进程内存中的数据、劫持进程的执行流程、监控进程的行为等等。
dll注入的本质就是把一个不属于某个进程的dll文件加载到该进程当中。
DLL注入与一般DLL加载的主要区别是加载的目标进程是其自身或者其他进程。
插入基础知识:
Kernel32.dll(包含管理内存,进程和线程相关的函数),“User32.dll”(大部分是用户接口函数),和“GDI32.dll”(绘制图像和显示文本相关的函数)
二.dll技术的应用(主要方面)
三.dll相关的API
OpenProcess | 打开远程进程 |
---|---|
VirtualAllocEx | 在远程进程中申请内存空间 |
WriteProcessMemory | 写入数据到远程进程 |
CreateRemoteThread | 创建远程线程 |
Loadlibrary | 加载模块 |
WaitForSingleObject | 等待信号 |
VirturalFreeEx | 释放远程进程内存空间 |
CloseHandle | 关闭句柄 |
四.编写代码前的准备工作:
1.OpenProcess函数
OpenProcess是windows操作系统提供的一个函数,它用于打开一个现有的进程,并返回一个与该进程关联的进程句柄。该函数的原型如下:
1 | HANDLE OpenProcess( |
参数说明:
dwDesiredAccess:指定进程的访问权限。这可以是一些常量值的组合,如PROCESS_ALL_ACCESS、PROCESS_CREATE_PROCESS、PROCESS_QUERY_INFORMATION等。
bInheritHandle:指定新句柄是否可以被继承。如果为TRUE,则新句柄可以被继承;如果为FALSE,则新句柄不可以被继承。
dwProcessId:指定要打开的进程的进程ID号。
OpenProcess函数可以用于获取一个现有进程的句柄,以便在该进程中执行一些操作,如读取或写入进程内存、修改进程的安全属性、发送消息等。需要注意的是,不同的进程拥有不同的访问权限,因此在使用OpenProcess函数时需要正确设置进程的访问权限,以避免权限问题导致的操作失败。
OpenProcess函数常用于编写一些系统工具或调试程序,以及一些需要与其他进程交互的应用程序。在编写一些恶意软件或攻击程序时,OpenProcess函数也可以被用于获取另一个进程的句柄,并对其进行一些未授权的操作。因此,在使用OpenProcess函数时需要谨慎,以避免对系统造成不良影响。
2.VirtualAllocEx函数
VirtualAllocEx是Windows操作系统提供的一个函数,用于在指定进程的虚拟地址空间中分配内存。函数原型如下:
1 | LPVOID VirtualAllocEx( |
函数参数说明:
hProcess:指定要在哪个进程中分配内存,该参数需要指定要分配内存的进程句柄。
lpAddress:指定欲分配的虚拟内存起始地址,如果为NULL,表示由系统自动选择一个合适的地址。
dwSize:指定要分配的内存大小,以字节为单位。
flAllocationType:指定内存分配的类型,可以使用一些常量值如MEM_COMMIT、MEM_RESERVE等。
flProtect:指定内存的保护属性,可以使用一些常量值如PAGE_READWRITE、PAGE_EXECUTE_READ等。
VirtualAllocEx函数的返回值是一个LPVOID类型的指针,指向在指定进程的虚拟地址空间中分配的内存的起始地址。如果函数调用失败,则返回NULL
使用VirtualAllocEx函数可以实现在指定进程的虚拟地址空间中分配内存,从而使得其他进程可以访问和使用该内存。需要注意的是,使用VirtualAllocEx函数分配的内存需要在使用完毕后通过VirtualFreeEx函数释放,以避免内存泄漏和资源浪费。
3.WriteProcessMemory函数:
WriteProcessMemory函数是Windows API中的一个函数,它可以将数据写入到指定进程的内存中。该函数可以用于在一个进程中注入代码或数据,实现进程间通信等功能。声明如下:
1 | BOOL WriteProcessMemory( |
参数说明:
hProcess:目标进程的句柄。
lpBaseAddress:要写入数据的目标进程内存的起始地址。
lpBuffer:要写入的数据缓冲区的指针。
nSize:要写入的数据的大小,以字节为单位。
lpNumberOfBytesWritten:一个指向变量的指针,用于接收实际写入的字节数。
WriteProcessMemory函数返回的是一个布尔类型的值,表示有没有写内存成功。
4.CreateRemoteThread函数
CreateRemoteThread是Windows操作系统提供的一个函数,它可以在指定的进程空间中创建一个远程线程,以便在该进程中执行指定的函数。函数原型如下:
1 | HANDLE CreateRemoteThread( |
函数参数说明:
hProcess:指定要在哪个进程中创建线程,该参数需要指定要创建线程的进程句柄。
lpThreadAttributes:指定线程的安全属性,如果不需要设置,则传入NULL即可。
dwStackSize:指定线程的堆栈大小,如果不需要设置,则传入0即可。
lpStartAddress:指定要在远程线程中执行的函数地址。
lpParameter:指定要传递给远程线程的参数。
dwCreationFlags:指定线程的创建标志,可以使用一些常量值如0、CREATE_SUSPENDED等。
lpThreadId:指向一个变量,用于返回线程ID号。
使用CreateRemoteThread函数可以实现在一个进程空间中注入一个线程,并且可以传递一些参数给该线程。该函数常用于编写一些系统工具或调试程序,以及一些需要与其他进程交互的应用程序。
以下是一个使用CreateRemoteThread函数实现DLL注入的示例代码:
1 |
|
5.LoadLibrary函数
LoadLibrary函数是Windows操作系统提供的一个函数,它可以加载一个动态链接库(DLL)文件到进程空间中,并返回该DLL的句柄。
需要注意的是它仅仅是把dll文件加载到进程的空间,但是想要调用这个dll还需要别的操作,比如在这个dll的DllMain里面添加附加到线程的时候执行等等。
DllMain
是 Windows DLL 中的一个特殊函数,用于处理 DLL 的加载、卸载以及其他状态的通知。
该函数的签名为:
1 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved); |
参数说明:
hModule: DLL 的模块句柄。该参数可以用来获取 DLL 中的其他资源,例如资源文件、函数地址等。
ul_reason_for_call: 表示 DLL 被加载、卸载或者其他状态的通知。可能的值包括:
DLL_PROCESS_ATTACH: DLL 被进程加载时调用。
DLL_PROCESS_DETACH: DLL 被进程卸载时调用。
DLL_THREAD_ATTACH: 进程创建新线程时调用。
DLL_THREAD_DETACH: 进程中线程退出时调用。
lpReserved: 保留参数。在实际开发中,一般不使用该参数。
在实际使用中,DllMain 函数常用于执行一些初始化或清理操作,例如:
在 DLL 加载时,进行资源的初始化,例如初始化共享内存、建立临界区等。
在 DLL 卸载时,进行资源的释放,例如清除共享内存、释放临界区等。
需要注意的是,在 DllMain 函数中,有一些操作是不安全的,例如:
调用其他 DLL 函数。这可能会导致死锁或死循环,因为其他 DLL 函数也可能调用 DllMain 函数。
创建新线程。在 DllMain 函数中创建新线程可能会导致死锁,因为该函数会在 DLL 加载之前被调用,此时可能没有完成初始化操作。
调用某些系统函数。某些系统函数可能会使用其他 DLL,这可能会导致死锁或死循环。
因此,在编写 DllMain 函数时需要小心谨慎,避免出现安全问题。
五.DLL注入四个步骤
(四个步骤)
1)附加到目标/远程进程
2)在目标/远程进程内分配内存
3)将DLL文件路径,或者DLL文件,复制到目标/远程进程的内存空间
4)控制进程运行DLL文件
1.技术介绍:
我们有多种方式可以控制进程运行我们的DLL文件。最普通的应该是“CreateRemoteThread()”和“NtCreateThreadEx()”函数;然而,不可能仅仅向这些函数传递一个DLL文件作为参数,我们必须提供一个包含执行起点的内存地址。为此,我们需要分配内存,使用“LoadLibrary()”加载我们的DLL文件,复制内存,等等。
以下还有7种注入方法:
- CreateRemoteThread()
- NtCreateThreadEx()
- QueueUserAPC
- SetWindowsHookEx()
- RtlCreateUserThread()
- 利用SetThreadContext()找到的代码区域
- 反射DLL
2.LoadLibrary()[附加函数原型和参数补充]
“LoadLibrary()”函数“被用于向调用进程的地址空间加载指定模块,而该指定模块可能导致其他模块被加载”。函数原型与参数说明如下所示:
1 | HMODULE WINAPI LoadLibrary( |