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

免责声明:请勿在恶意软件中使用提供的代码。
引言
所以,这实际上不是关于一些酷炫黑客技巧的超级解释论文,只是一个小小的建议。 我不会在这里解释很多代码,因为它会 *很多*。 本文基于我的另一篇文章: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? 我们只知道诸如:Process32Next
,CreateToolHelpSnapShot
,Process32First
之类的函数。 不,我们知道的更多...
~~~~[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.c 和 nt.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
屏幕截图

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

... 或者以程序员的方式进行操作
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 系统,我们开始吧!

此致,cross <cross[at]x1machine.com>
历史
- 2009 年 5 月 9 日:初始版本