RtlCreateUserThread函數當然也是ntdll導出的函數,這個比之前的NtCreateThreadEx是要強點的,最起碼還能看得見參數有幾個,hhhhh,難頂啊。
其實CreateRemote和Nt系列和Rtl系列的注入方式和思路基本是一致的,但是這裏還是按照慣例,bb一下我的實現思路(這思路我願意稱之爲套娃):
- 從控制檯得到想要實施注入的目標進程名字
- 得到當前進程所在的目錄(GetCurrentDirectory),並保存
- 得到當前進程的位數 (IsWow64Process)
- 根據進程名字得到當前進程的Id
- 根據進程Id得到當前進程的完整路徑
- 通過進程完整路徑對PE文件解析得到目標進程位數
- 目標與當前進程的位數進行匹配,決定加載哪一個dll(x86 or x64)
- 根據當前進程目錄,得到dll完整路徑
- 通過GetModuleHandle得ntdll和kernel32模塊得句柄
- 通過GetProcAddress分別從ntdll和kernel32中得到RtlCreateUserThread和LoadLibraryA
- 通過目標進程Id,打開目標進程,獲得進程句柄
- 在目標進程中申請內存
- 在申請好的內存中寫入Dll完整路徑
- 利用RtlCreateUserThread啓動遠程線程執行加載Dll,完成注入
重要部分源碼(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)
今日自勉:永遠不要停下自己前進的腳步。