介绍:
前面写过一片远程线程注入的文章,用到的是CreateRemoteThread函数来远程注入线程的,这次我们用NtCreateThreadEx来创建远程线程,其实并没有技术的升级,而是进行了创建远程线程函数的升级,下面是CreateRemoteThread在Reactos中的源码
/* Create the Kernel Thread Object */
Status = NtCreateThread(&hThread,
THREAD_ALL_ACCESS,
ObjectAttributes,
hProcess,
&ClientId,
&Context,
&InitialTeb,
TRUE);
可以发现CreaeteRemoteThread函数实现中调用了 NtCreateThread函数的,但我们这篇文章是使用NtCreateThreadEx 一个未公开的函数,使用方法和 CreaeteRemoteThread类似。
步骤:
- 获取进程ID __NtQuerySystemInformation
- 打开进程,获取进程句柄 SeEnableSeDebugPrivilege OpenProcess
- 在目标进程中申请内存空间 VirtualAllocEx
- 在目标进程中写入DLL完整路径 WriteProcessMemory
- 从Ntdll中获取NtCreateThreadEx地址,从Kernel32中获取LoadLibraryA/W地址
- 调用NtCreateThreadEx创建远程线程
代码:
获取进程ID
打开进程,获取进程句柄
在目标进程中申请内存空间
ULONG BufferLength = 0;
//在目标进程空间中申请内存
BufferLength = (_tcslen(BufferData) + 1) * sizeof(TCHAR);
//目标进程空间中申请内存
VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, BufferLength, MEM_COMMIT, PAGE_READWRITE);
在目标进程中写入DLL完整路径
ProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, BufferData, BufferLength, &ReturnLength)
BOOL ProcessMemoryWriteSafe(HANDLE ProcessHandle, LPVOID VirtualAddress, LPCVOID BufferData, SIZE_T BufferLength, SIZE_T* ReturnLength)
{
SIZE_T v1 = 0;
SIZE_T* v2 = 0;
int LastError = 0;
DWORD OldProtect = 0;
BOOL IsOk = FALSE;
if ((ProcessHandle == 0) || (VirtualAddress == 0) || (BufferData == 0) || (BufferLength == 0))
{
LastError = ERROR_INVALID_PARAMETER;
goto Exit;
}
if (!ReturnLength)
{
v2 = &v1;
}
else
{
v2 = ReturnLength;
}
if (!WriteProcessMemory(ProcessHandle, VirtualAddress, BufferData, BufferLength, v2))
/*BOOL WriteProcessMemory( ****函数能写入某一进程的内存区域
HANDLE hProcess, 由OpenProcess返回的进程句柄。如参数传数据为 INVALID_HANDLE_VALUE 【即-1】目标进程为自身进程
LPVOID lpBaseAddress, 要写的内存首地址 再写入之前,此函数将先检查目标地址是否可用,并能容纳待写入的数据
LPVOID lpBuffer, 指向要写的数据的指针。
DWORD nSize, 要写入的字节数。
LPDWORD lpNumberOfBytesWritten 实际数据的长度
);*/
{
if (VirtualProtectEx(ProcessHandle, VirtualAddress, BufferLength, PAGE_EXECUTE_READWRITE, &OldProtect))
{
if (WriteProcessMemory(ProcessHandle, VirtualAddress, BufferData, BufferLength, v2))
{
IsOk = TRUE;
}
else
{
LastError = GetLastError();
}
VirtualProtectEx(ProcessHandle, VirtualAddress, BufferLength, OldProtect, &OldProtect);
}
else
{
LastError = GetLastError();
}
}
else
{
IsOk = TRUE;
}
Exit:
SetLastError(LastError);
return IsOk;
}
从Ntdll中获取NtCreateThreadEx地址,从Kernel32中获取LoadLibraryA/W地址
//当前exe模块中没有该函数导入
__NtCreateThreadEx = (LPFN_NTCREATETHREADEX)GetProcAddress(NtdllModuleBase,
"NtCreateThreadEx");
if (__NtCreateThreadEx == NULL)
{
goto Exit;
}
//使用Kernel32模块中的导出函数地址 Anti(IAThook)
#ifdef UNICODE
__LoadLibrary = (LPFN_LOADLIBRARYW)GetProcAddress(Kernel32ModuleBase, "LoadLibraryW");
#else
__LoadLibrary = (LPFN_LOADLIBRARYA)GetProcAddress(Kernel32ModuleBase, "LoadLibraryA");
#endif
调用NtCreateThreadEx创建远程线程
//再目标进程中启动一个线程
HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
IsOk = __NtCreateThreadEx(&ThreadHandle,
THREAD_ALL_ACCESS, NULL, ProcessHandle, (LPTHREAD_START_ROUTINE)__LoadLibrary, VirtualAddress,
FALSE, NULL, NULL, NULL, NULL);
WaitForSingleObject(ThreadHandle, INFINITE);