使用NtCreateThreadEx將Dll注入目標進程

第一遍學習這個注入方法時候,只知道NtCreateThreadEx是未公開的nt函數,當時要定義一個函數指針出來,好像在看雪上找到的這個函數的聲明,,太久遠了,記不清了。
在Windows2000的源碼和Reactos中都無法找到NtCreateThreadEx的函數聲明和實現,所以試了下用IDA看看ntdll的導出表,哇,好開心找到了,但是,,好像什麼都沒有,只有一個系統調用號,沒有任何參數的信息。
在這裏插入圖片描述
我最後在https://securityxploded.com/ntcreatethreadex.php找到了有關這個函數的聲明,它是未文檔化的。。難頂
廢話不多說,對於注入來說,NtCreateThreadEx也是經常用的一種方法,只是這個函數沒有被微軟文檔化,這點比較d疼。接下來說說實現思路,基本和CreateRemoteThread差不多:

  1. 從控制檯得到想要實施注入的目標進程名字
  2. 得到當前進程所在的目錄,並保存
  3. 得到當前進程的位數
  4. 根據進程名字得到當前進程的Id
  5. 根據進程Id得到當前進程的完整路徑
  6. 通過進程完整路徑對PE文件解析得到目標進程位數
  7. 目標與當前進程的位數進行匹配,決定加載哪一個dll
  8. 根據當前進程目錄,得到dll完整路徑
  9. 通過GetModuleHandle得ntdll和kernel32模塊得句柄
  10. 通過GetProcAddress分別從ntdll和kernel32中得到NtCreateThreadEx和LoadLibraryA
  11. 通過目標進程Id,打開目標進程,獲得進程句柄
  12. 在目標進程中申請內存
  13. 在申請好的內存中寫入Dll完整路徑
  14. 利用NtCreateThreadEx啓動遠程線程執行加載Dll,完成注入

以下是代碼框架:

//.h
#pragma once
#include<Windows.h>
#include<iostream>
#include<tchar.h>


using namespace std;


//https://securityxploded.com/ntcreatethreadex.php
//Here is the prototype of NtCreateThreadEx function [undocumented]
typedef NTSTATUS(WINAPI* LPFN_NTCREATETHREADEX)(
	OUT PHANDLE ThreadHandle,
	IN ACCESS_MASK DesiredAccess,
	IN LPVOID ObjectAttributes,
	IN HANDLE ProcessHandle,
	IN LPTHREAD_START_ROUTINE ThreadProcedure,
	IN LPVOID ParameterData,
	IN BOOL CreateSuspended,
	IN SIZE_T StackZeroBits,
	IN SIZE_T SizeOfStackCommit,
	IN SIZE_T SizeOfStackReserve,
	OUT LPVOID BytesBuffer);




typedef HMODULE(WINAPI * LPFN_LOADLIBRARYW)(LPCWSTR lpLibFileName);
typedef HMODULE(WINAPI * LPFN_LOADLIBRARYA)(LPCSTR lpLibFileName);


//.cpp
#include"NtCreateThreadEx.h"
#include"Helper.h"




#ifdef UNICODE
LPFN_LOADLIBRARYW __LoadLibrary = NULL;
#else
LPFN_LOADLIBRARYA __LoadLibrary = NULL;
#endif

LPFN_NTCREATETHREADEX __NtCreateThreadEx = NULL;

int _tmain(int argc, TCHAR* argv[], TCHAR *envp[])
{
	//控制檯識別中文
	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 = 0x00000056f16ff2b0 "Taskmgr.exe"

	GetCurrentDirectory(MAX_PATH, CurrentFullPath);//保存當前進程的完整路徑

	IsWow64Process(GetCurrentProcess(), &SourceIsWow64);//得到當前進程位數
	
	ProcessId = KtGetProcessIdentify(ProcessImageName);//通過進程名得到進程Id

	if (ProcessId == 0)
	{
		return 0;
	}
	IsOk = KtGetProcessFullPath(TargetProcessFullPath,
		&TargetProcessPathLength, ProcessId, FALSE);
	
	if (IsOk == FALSE)
	{
		return 0;
	}
	//判斷目標進程位數
	KtIsWow64Process(TargetProcessFullPath, &TargetIsWow64);
	if (SourceIsWow64 == TRUE && TargetIsWow64 == TRUE)
	{
		_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
	}
	else if (SourceIsWow64 == FALSE && TargetIsWow64 == FALSE)
	{
		_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
	}
	//CurrentFullPath = 0x00000056f16ff3e0 "Z:\\Ring3層代碼\\[2]Ring3注入\\NtCreateThreadEx\\NtCreateThreadEx\\Dll.dll"

	HMODULE  NtdllModuleBase = NULL;
	HMODULE  Kernel32ModuleBase = NULL;
	NtdllModuleBase = GetModuleHandle(_T("NTDLL.DLL"));
	Kernel32ModuleBase = GetModuleHandle(_T("KERNEL32.DLL"));
	if (NtdllModuleBase == NULL || Kernel32ModuleBase == NULL) {

		KtCloseHandle(ProcessHandle);
		return 0;
	}
	//當前exe模塊中沒有該函數導入
	__NtCreateThreadEx = (LPFN_NTCREATETHREADEX)GetProcAddress(NtdllModuleBase,
		"NtCreateThreadEx");
	//__NtCreateThreadEx = ntdll.dll!0x00007ffb6580c0e0 (加載符號以獲取其他信息)

	if (__NtCreateThreadEx == NULL)
	{
		KtCloseHandle(ProcessHandle);
		return 0;
	}
#ifdef UNICODE
	__LoadLibrary = (LPFN_LOADLIBRARYW)GetProcAddress(Kernel32ModuleBase, "LoadLibraryW");
#else
	__LoadLibrary = (LPFN_LOADLIBRARYA)GetProcAddress(Kernel32ModuleBase, "LoadLibraryA");
#endif
	//__LoadLibrary = kernel32.dll!0x00007ffb63c7e710 (加載符號以獲取其他信息)
	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);
	//VirtualAddress = 0x0000021819010000
	if (VirtualAddress == NULL)
	{
		KtCloseHandle(ProcessHandle);
		return 0;
	}
	//目標進程空間中寫入數據
	if (KtProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, CurrentFullPath, BufferLength, &ReturnLength) == FALSE)
	{
		KtCloseHandle(ProcessHandle);
		return 0;
	}
	//再目標進程中啓動一個線程
	HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
	IsOk = __NtCreateThreadEx(&ThreadHandle,
		THREAD_ALL_ACCESS, NULL, ProcessHandle, (LPTHREAD_START_ROUTINE)__LoadLibrary, VirtualAddress,
		FALSE, NULL, NULL, NULL, NULL);
	if (IsOk < 0) 
	{


		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
		KtCloseHandle(ProcessHandle);
		return 0;
	}

	else
	{
		WaitForSingleObject(ThreadHandle, INFINITE);
		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
		KtCloseHandle(ProcessHandle);
	}
	return 0;
}
//.dllmain
// 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("NtCreateThreadEx"), _T("NtCreateThreadEx"), NULL);
	}
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Win7(32)注入Explorer和Win10注入Taskmgr.exe(64)兩個都測試通過,32和64都沒問題
在這裏插入圖片描述
在這裏插入圖片描述
今日份頭禿:爲什麼我的Win7(32)調用系統函數IsWow64Process返回的當前程序位數是64位???我醉了。。。。
今日份古詩分享:
“蓬頭稚子學垂綸,側坐莓苔草映身。”
這小孩真挺可愛的,蓬頭稚子,哈哈哈哈。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章