概述:远程加载和释放 DLL,仅记录学习笔记,无参考意义。
CreateRemoteThread的用法参考文章 CreateRemoteThread 的简单使用
说明
主要就是在目标进程中调用 LoadLibrary 和 FreeLibrary 这两个函数。没有什么技术含量,会以下几个 API 就可以
- CreateRemoteThread
- LoadLibrary
- Freelibrary
- OpenProcess
- VirtualAllocEx
- GetProcAddress
- CreateToolhelp32Snapshot
注意点
卸载 dll 时需要判断 dll 是否存在。
需要调用 CreateToolhelp32Snapshot 通过 MODULEENTRY32 枚举进程加载的模块有哪些。MODULEENTRY32 结构体如下所示
- szModule:模块名
- szExePath:模块加载的路径
typedef struct tagMODULEENTRY32
{
DWORD dwSize;
DWORD th32ModuleID; // This module
DWORD th32ProcessID; // owning process
DWORD GlblcntUsage; // Global usage count on the module
DWORD ProccntUsage; // Module usage count in th32ProcessID's context
BYTE * modBaseAddr; // Base address of module in th32ProcessID's context
DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr
HMODULE hModule; // The hModule of this module in th32ProcessID's context
char szModule[MAX_MODULE_NAME32 + 1];
char szExePath[MAX_PATH];
} MODULEENTRY32;
typedef MODULEENTRY32 * PMODULEENTRY32;
typedef MODULEENTRY32 * LPMODULEENTRY32;Code
代码部分分别封装了两个函数 InjectDll 和 FreeDll。
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#pragma comment(lib,"Advapi32.lib")
BOOL InjectDll(UINT32 ProcessId, char *DllPath)
{
if (strstr(DllPath, "\\\\") != 0)
{
printf("[!]Wrong Dll path\n");
return FALSE;
}
if (strstr(DllPath, "\\") == 0)
{
printf("[!]Need Dll full path\n");
return FALSE;
}
size_t len = strlen(DllPath) + 1;
LPVOID pThreadData = NULL;
HANDLE ProcessHandle = NULL;
HANDLE hThread = NULL;
BOOL bRet = FALSE;
__try
{
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
if (ProcessHandle == NULL)
{
printf("[!]OpenProcess error\n");
__leave;
}
pThreadData = VirtualAllocEx(ProcessHandle, NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pThreadData == NULL)
{
CloseHandle(ProcessHandle);
printf("[!]VirtualAllocEx error\n");
__leave;
}
BOOL bWriteOK = WriteProcessMemory(ProcessHandle, pThreadData, DllPath, len, NULL);
if (!bWriteOK)
{
CloseHandle(ProcessHandle);
printf("[!]WriteProcessMemory error\n");
__leave;
}
LPTHREAD_START_ROUTINE LoadLibraryAddress = NULL;
HMODULE Kernel32Module = GetModuleHandle("Kernel32");
LoadLibraryAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryA");
hThread = CreateRemoteThread(ProcessHandle, NULL, 0, LoadLibraryAddress, pThreadData, 0, NULL);
if (hThread == NULL)
{
CloseHandle(ProcessHandle);
printf("[!]CreateRemoteThread error\n");
__leave;
}
WaitForSingleObject(hThread, INFINITE);
bRet = TRUE;
}
__finally
{
if (pThreadData != NULL)
VirtualFreeEx(ProcessHandle, pThreadData, 0, MEM_RELEASE);
if (hThread != NULL)
CloseHandle(hThread);
if (ProcessHandle != NULL)
CloseHandle(ProcessHandle);
}
return bRet;
}
BOOL FreeDll(UINT32 ProcessId, char *DllFullPath)
{
BOOL bMore = FALSE, bFound = FALSE;
HANDLE hSnapshot;
HMODULE hModule = NULL;
MODULEENTRY32 me = { sizeof(me) };
BOOL bSuccess = FALSE;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
bMore = Module32First(hSnapshot, &me);
for (; bMore; bMore = Module32Next(hSnapshot, &me)) {
if (!_tcsicmp((LPCTSTR)me.szModule, DllFullPath) || !_tcsicmp((LPCTSTR)me.szExePath, DllFullPath))
{
bFound = TRUE;
break;
}
}
if (!bFound) {
CloseHandle(hSnapshot);
return FALSE;
}
BOOL bRet = FALSE;
HANDLE ProcessHandle = NULL;
__try
{
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
if (ProcessHandle == NULL)
{
printf("[!]OpenProcess error\n");
__leave;
}
LPTHREAD_START_ROUTINE FreeLibraryAddress = NULL;
HMODULE Kernel32Module = GetModuleHandle("Kernel32");
FreeLibraryAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "FreeLibrary");
HANDLE hThread = NULL;
hThread = CreateRemoteThread(ProcessHandle, NULL, 0, FreeLibraryAddress, me.modBaseAddr, 0, NULL);
if (hThread == NULL)
{
CloseHandle(ProcessHandle);
printf("[!]CreateRemoteThread error\n");
__leave;
}
WaitForSingleObject(hThread, INFINITE);
bRet = TRUE;
}
__finally
{
if (ProcessHandle != NULL)
CloseHandle(ProcessHandle);
}
return bRet;
}
BOOL EnableDebugPrivilege(BOOL fEnable)
{
BOOL fOk = FALSE;
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return(fOk);
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("Use CreateRemoteThread to inject dll,usually used under XP.\n\n");
printf("Usage:\n");
printf("%s <PID> <Dll Path>\n", argv[0]);
return 0;
}
if (!EnableDebugPrivilege(TRUE))
{
printf("[!]AdjustTokenPrivileges Failed.<%d>\n", GetLastError());
}
if (!InjectDll((DWORD)atoi(argv[1]), argv[2]))
{
printf("[!]InjectDll error \n");
return 1;
}
if (!FreeDll((DWORD)atoi(argv[1]), argv[2]))
{
printf("[!]FreeDll error \n");
return 1;
}
printf("[+]InjectDll success\n");
return 0;
}