当前位置 博文首页 > KOOKNUT的博客:RtlCreateUserThread实现Dll注入
RtlCreateUserThread函数当然也是ntdll导出的函数,这个比之前的NtCreateThreadEx是要强点的,最起码还能看得见参数有几个,hhhhh,难顶啊。
其实CreateRemote和Nt系列和Rtl系列的注入方式和思路基本是一致的,但是这里还是按照惯例,bb一下我的实现思路(这思路我愿意称之为套娃):
重要部分源码(Win 7 Win10测试):
#include"RtlCreateUserThread.h"
#include"Helper.h"
#ifdef UNICODE
LPFN_LOADLIBRARYW __LoadLibrary = NULL;
#else
LPFN_LOADLIBRARYA __LoadLibrary = NULL;
#endif
LPFN_RTLCREATEUSERTHREAD __RtlCreateUserThread = NULL;
int _tmain()
{
//控制台识别中文
setlocale(LC_ALL, "Chinese-simplified");
TCHAR ProcessImageName[MAX_PATH] = { 0 };//保存进程名字
TCHAR CurrentFullPath[MAX_PATH] = { 0 }; //当前进程的完整路径
TCHAR TargetProcessFullPath[MAX_PATH] = { 0 };//目标进程的完整路径
ULONG_PTR TargetProcessPathLength = MAX_PATH;
ULONG ProcessId = 0;//目标进程Id
HANDLE ProcessHandle = INVALID_HANDLE_VALUE;//进程句柄
LPVOID VirtualAddress = NULL;
SIZE_T ReturnLength = 0;
BOOL IsOk = FALSE;
//注入的启动程序和目标程序的位数
BOOL SourceIsWow64 = FALSE;
BOOL TargetIsWow64 = FALSE;
_tprintf(_T("输入一个进程ImageName\r\n"));
TCHAR RcceiveChar = _gettchar();//接受字符串
int i = 0;//用来偏移ProcessName字符数组
while (RcceiveChar != '\n')
{
ProcessImageName[i++] = RcceiveChar;
RcceiveChar = _gettchar();
//ProcessImageName = 0x000000db28fceed0 "Taskmgr.exe"
}
GetCurrentDirectory(MAX_PATH, CurrentFullPath);//保存当前进程的完整路径
IsWow64Process(GetCurrentProcess(), &SourceIsWow64);//得到当前进程位数
//SourceIsWow64 = 0x00000000
ProcessId = KtGetProcessIdentify(ProcessImageName);//通过进程名得到进程Id
//ProcessId = 0x00003aa0
if (ProcessId == 0)
{
return 0;
}
IsOk = KtGetProcessFullPath(TargetProcessFullPath,
&TargetProcessPathLength, ProcessId, FALSE);
if (IsOk == FALSE)
{
return 0;
}
//判断目标进程位数
KtIsWow64Process(TargetProcessFullPath, &TargetIsWow64);
//TargetIsWow64 = 0x00000000
if (SourceIsWow64 == TRUE && TargetIsWow64 == TRUE)
{
_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
}
else if (SourceIsWow64 == FALSE && TargetIsWow64 == FALSE)
{
_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
}
//_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));//Win 7 32位测试用 因为我的32位虚拟机这函数IsWow64Process得不到正确值
//CurrentFullPath = 0x000000db28fcf000 "Z:\\Ring3层代码\\[2]Ring3注入\\RtlCreateUserThread\\RtlCreateUserThread\\Dll.dll"
HMODULE NtdllModuleBase = NULL;
HMODULE Kernel32ModuleBase = NULL;
NtdllModuleBase = GetModuleHandle(_T("NTDLL.DLL"));
//NtdllModuleBase = ntdll.dll!0x00007ffe84160000 (加载符号以获取其他信息) {unused=0x00905a4d }
Kernel32ModuleBase = GetModuleHandle(_T("KERNEL32.DLL"));
//Kernel32ModuleBase = kernel32.dll!0x00007ffe83fa0000 (加载符号以获取其他信息) {unused=0x00905a4d }
if (NtdllModuleBase == NULL || Kernel32ModuleBase == NULL)
{
KtCloseHandle(ProcessHandle);
return 0;
}
//获取Native API函数的地址
__RtlCreateUserThread = (LPFN_RTLCREATEUSERTHREAD)GetProcAddress(NtdllModuleBase,
"RtlCreateUserThread");
//__RtlCreateUserThread = ntdll.dll!0x00007ffe84166080 (加载符号以获取其他信息)
if (__RtlCreateUserThread == NULL)
{
return 0;
}
#ifdef UNICODE
__LoadLibrary = (LPFN_LOADLIBRARYW)GetProcAddress(Kernel32ModuleBase, "LoadLibraryW");
#else
__LoadLibrary = (LPFN_LOADLIBRARYA)GetProcAddress(Kernel32ModuleBase, "LoadLibraryA");
#endif
if (__LoadLibrary == NULL) {
KtCloseHandle(ProcessHandle);
return 0;
}
ProcessHandle = KtOpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
ULONG BufferLength = 0;
//在目标进程空间中申请内存
BufferLength = (_tcslen(CurrentFullPath) + 1) * sizeof(TCHAR);
//目标进程空间中申请内存
VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, BufferLength, MEM_COMMIT, PAGE_READWRITE);
if (VirtualAddress == NULL)
{
KtCloseHandle(ProcessHandle);
return 0;
}
//目标进程空间中写入数据
if (KtProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, CurrentFullPath, BufferLength, &ReturnLength) == FALSE)
{
KtCloseHandle(ProcessHandle);
return 0;
}
HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
CLIENT_ID ClientId;
NTSTATUS Status = __RtlCreateUserThread(
ProcessHandle,
NULL,
0,
0,
0,
0,
(PTHREAD_START_ROUTINE)__LoadLibrary,
VirtualAddress,
&ThreadHandle,
&ClientId);
if (Status >= 0)
{
WaitForSingleObject(ThreadHandle, INFINITE);
VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
KtCloseHandle(ProcessHandle);
}
else
{
VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
KtCloseHandle(ProcessHandle);
return 0;
}
return 0;
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <tchar.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
MessageBox(NULL, _T("RtlCreateUserThread"), _T("RtlCreateUserThread"), NULL);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
测试通过Win7 x86(Explorer.exe)和Win10 x64(Taskmgr.exe)
今日自勉:永远不要停下自己前进的脚步。