函数原型
HANDLE CreateRemoteThread(
HANDLE hProcess, // handle to process
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier
);
参数说明:
hProcess
[输入] 进程句柄
lpThreadAttributes
[输入] 线程安全描述字,指向SECURITY_ATTRIBUTES结构的指针
dwStackSize
[输入] 线程栈大小,以字节表示
lpStartAddress
[输入] 一个LPTHREAD_START_ROUTINE类型的指针,指向在远程进程中执行的函数地址
lpParameter
[输入] 传入参数
dwCreationFlags
[输入] 创建线程的其它标志
lpThreadId
[输出] 线程身份标志,如果为NULL,则不返回
返回值
成功返回新线程句柄,失败返回NULL,并且可调用GetLastError获得错误值。
CreateRemoteThread的注入步骤。
1.提权
2.根据进程ID打开对方进程OpenProcess,得到进程句柄
3.根据进程句柄在目标进程中申请内存VirtualAllocEx
4.在目标进程中刚刚申请的内存空间中写入所需参数(Dll的完整路径)WriteProcessMemory
5.用GetProcAddress得到LoadLibraryW的模块加载地址
6.启动远程线程CreateRemoteThread,并在第四参数传入该线程需要执行的函数名(即LoadLibrary)
DWORD EnablePrivilege(HANDLE ProcessHandle, BOOL IsEnable, LPCTSTR RequireLevel)
{
DWORD LastError = 0;
HANDLE TokenHandle = NULL;
if (!OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
{
LastError = GetLastError();
if (TokenHandle)
{
CloseHandle(TokenHandle);
TokenHandle = NULL;
return LastError;
}
}
TOKEN_PRIVILEGES TokenPrivileges = { 0 };
LUID v1;
if (!LookupPrivilegeValue(NULL, RequireLevel, &v1))
{
LastError = GetLastError();
CloseHandle(TokenHandle);
TokenHandle = NULL;
return LastError;
}
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Luid = v1;
if (IsEnable)
{
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else
{
TokenPrivileges.Privileges[0].Attributes = IsEnable = SE_PRIVILEGE_ENABLED;
}
AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges,
sizeof(TOKEN_PRIVILEGES), NULL, NULL);
LastError = GetLastError();
CloseHandle(TokenHandle);
TokenHandle = NULL;
return LastError;
}
#include "Inject.h"
void _tmain(int argc, TCHAR **argv, TCHAR **envp)
{
_tsetlocale(LC_ALL, _T("chs"));
DWORD ProcessId;
HANDLE ProcessHandle;
TCHAR DllFullPath[MAX_PATH] = _T("DllPath");
SIZE_T DllFullPathLength;
LPVOID VirtualAddress;
BOOL IsOk = FALSE;
_tscanf_s(_T("%d"), &ProcessId);
EnablePrivilege(GetCurrentProcess(), TRUE, SE_DEBUG_NAME);
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
DllFullPathLength = (_tcslen(DllFullPath) + 1) * sizeof(TCHAR);
VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, DllFullPathLength, MEM_COMMIT, PAGE_READWRITE);
IsOk = WriteProcessMemory(ProcessHandle, VirtualAddress, DllFullPath, DllFullPathLength, NULL);
HANDLE ThreadHandle = CreateRemoteThread(ProcessHandle,
NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, //当前模块中导入函数
VirtualAddress, 0, NULL);
if (ThreadHandle == NULL)
{
VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE);
goto Exit;
}
//等待远程线程结束
WaitForSingleObject(ThreadHandle, INFINITE);
if (VirtualAddress != NULL)
{
VirtualFreeEx(ProcessHandle, VirtualAddress, DllFullPathLength, MEM_RELEASE);
}
Exit:
if (ProcessHandle != NULL)
{
CloseHandle(ProcessHandle);
}
_tprintf_s(_T("Press Any Key To Continue.\r\n"));
_gettchar();
}
5.18日更新
因为在整理注入,发现两种和CreateRemoteThread思想基本一致的方法,所以就不再开一篇博客,写在这里吧。
RtlCreateUserThread 这是一个ntdll导出的函数,但是没有公开,需要自己构建函数指针。
typedef DWORD(WINAPI * pRtlCreateUserThread)(
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOL CreateSuspended,
IN ULONG StackZeroBits,
IN OUT PULONG StackReserved,
IN OUT PULONG StackCommit,
IN LPVOID StartAddress,
IN LPVOID StartParameter,
OUT HANDLE ThreadHandle,
OUT LPVOID ClientID
);
IsOk = __RtlCreateUserThread(
ProcessHandle,
NULL,
0,
0,
0,
0,
(PTHREAD_START_ROUTINE)LoadLibrary,
VirtualAddress,
&ThreadHandle,
NULL);
NtCreateThreadEx同样是ntdll导出的函数,未公开,自己构建函数指针。
typedef NTSTATUS(WINAPI *LPFUN_NtCreateThreadEx) (
PHANDLE hThread,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
ULONG StackZeroBits,
ULONG SizeOfStackCommit,
ULONG SizeOfStackReserve,
LPVOID lpBytesBuffer
);
IsOk = __NtCreateThreadEx(
&ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
ProcessHandle,
(LPTHREAD_START_ROUTINE)LoadLibrary,
VirtualAddress,
FALSE,
NULL,
NULL,
NULL,
NULL);
注入过程和CreateRemoteThread基本类似,只不过这两个函数需要GetProcAddresss获得函数地址。