/******************************************************************** Created: 2012/02/01 18:17 Filename: NativeAPI.h Author: rrrfff Url: http://blog.csdn.net/rrrfff *********************************************************************/ #ifndef USE_NATIVEAPI #define USE_NATIVEAPI #include "../RLib.h" #include <WinNT.h> #include <winternl.h> ////////////////////////////////////////////////////////////////////////// typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; typedef struct _INITIAL_TEB { struct { PVOID OldStackBase; PVOID OldStackLimit; } OldInitialTeb; PVOID StackBase; PVOID StackLimit; PVOID StackAllocationBase; } INITIAL_TEB, *PINITIAL_TEB; typedef enum _BASE_CONTEXT_TYPE { BaseContextTypeProcess, BaseContextTypeThread, BaseContextTypeFiber } BASE_CONTEXT_TYPE, *PBASE_CONTEXT_TYPE; typedef struct __TEB { NT_TIB Tib; PVOID EnvironmentPointer; CLIENT_ID Cid; PVOID ActiveRpcInfo; PVOID ThreadLocalStoragePointer; PPEB Peb; ULONG LastErrorValue; ULONG CountOfOwnedCriticalSections; PVOID CsrClientThread; PVOID Win32ThreadInfo; ULONG Win32ClientInfo[0x1F]; PVOID WOW32Reserved; ULONG CurrentLocale; ULONG FpSoftwareStatusRegister; PVOID SystemReserved1[0x36]; PVOID Spare1; ULONG ExceptionCode; ULONG SpareBytes1[0x28]; PVOID SystemReserved2[0xA]; ULONG GdiRgn; ULONG GdiPen; ULONG GdiBrush; CLIENT_ID RealClientId; PVOID GdiCachedProcessHandle; ULONG GdiClientPID; ULONG GdiClientTID; PVOID GdiThreadLocaleInfo; PVOID UserReserved[5]; PVOID GlDispatchTable[0x118]; ULONG GlReserved1[0x1A]; PVOID GlReserved2; PVOID GlSectionInfo; PVOID GlSection; PVOID GlTable; PVOID GlCurrentRC; PVOID GlContext; NTSTATUS LastStatusValue; UNICODE_STRING StaticUnicodeString; WCHAR StaticUnicodeBuffer[0x105]; PVOID DeallocationStack; PVOID TlsSlots[0x40]; LIST_ENTRY TlsLinks; PVOID Vdm; PVOID ReservedForNtRpc; PVOID DbgSsReserved[0x2]; ULONG HardErrorDisabled; PVOID Instrumentation[0x10]; PVOID WinSockData; ULONG GdiBatchCount; ULONG Spare2; ULONG Spare3; ULONG Spare4; PVOID ReservedForOle; ULONG WaitingOnLoaderLock; PVOID StackCommit; PVOID StackCommitMax; PVOID StackReserved; } TEB_, *PTEB_; typedef struct __PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA LoaderData; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PVOID FastPebLock; PVOID/*PPEBLOCKROUTINE*/FastPebLockRoutine; PVOID/*PPEBLOCKROUTINE */FastPebUnlockRoutine; ULONG EnvironmentUpdateCount; PVOID/*PPVOID*/ KernelCallbackTable; PVOID EventLogSection; PVOID EventLog; PVOID/*PPEB_FREE_BLOCK*/FreeList; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[0x2]; PVOID ReadOnlySharedMemoryBase; PVOID ReadOnlySharedMemoryHeap; PVOID/*PPVOID*/ ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; ULONG NumberOfProcessors; ULONG NtGlobalFlag; BYTE Spare2[0x4]; LARGE_INTEGER CriticalSectionTimeout; ULONG HeapSegmentReserve; ULONG HeapSegmentCommit; ULONG HeapDeCommitTotalFreeThreshold; ULONG HeapDeCommitFreeBlockThreshold; ULONG NumberOfHeaps; ULONG MaximumNumberOfHeaps; PVOID/*PPVOID*/ *ProcessHeaps; PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; PVOID GdiDCAttributeList; PVOID LoaderLock; ULONG OSMajorVersion; ULONG OSMinorVersion; ULONG OSBuildNumber; ULONG OSPlatformId; ULONG ImageSubSystem; ULONG ImageSubSystemMajorVersion; ULONG ImageSubSystemMinorVersion; ULONG GdiHandleBuffer[0x22]; ULONG PostProcessInitRoutine; ULONG TlsExpansionBitmap; BYTE TlsExpansionBitmapBits[0x80]; ULONG SessionId; } PEB_, *PPEB_; typedef struct _FILE_NETWORK_OPEN_INFORMATION { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG FileAttributes; } FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; typedef struct _FILE_DISPOSITION_INFORMATION { BOOLEAN Delete; } FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; typedef struct _FILE_RENAME_INFORMATION { BOOLEAN ReplaceIfExists; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[MAX_PATH + 4]; } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; typedef struct _FILE_POSITION_INFORMATION { LARGE_INTEGER CurrentByteOffset; } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; typedef struct _FILE_END_OF_FILE_INFORMATION { LARGE_INTEGER EndOfFile; } FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; typedef enum _THREAD_INFORMATION_CLASS { ThreadBasicInformation, ThreadTimes, ThreadPriority, ThreadBasePriority, ThreadAffinityMask, ThreadImpersonationToken, ThreadDescriptorTableEntry, ThreadEnableAlignmentFaultFixup, ThreadEventPair, ThreadQuerySetWin32StartAddress, ThreadZeroTlsCell, ThreadPerformanceCount, ThreadAmILastThread, ThreadIdealProcessor, ThreadPriorityBoost, ThreadSetTlsArrayAddress, ThreadIsIoPendingRRRFFF,//重定义 ThreadHideFromDebugger } THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS; // // Determine if an argument is present by testing the value of the pointer // to the argument value. // #define ARGUMENT_PRESENT(ArgumentPointer) (\ (CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) ) #define NtCurrentPeb() (PPEB_(((TEB_ *)NtCurrentTeb())->Peb)) #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) #define ROUND_UP(x, align) (((int) (x) + (align - 1)) & ~(align - 1)) #define SET_THREAD_ENTRY_ROUTINE 9 extern "C" { HANDLE NTAPI BaseGetNamedObjectDirectory(); POBJECT_ATTRIBUTES NTAPI BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, IN PUNICODE_STRING ObjectName); VOID NTAPI BaseInitializeContext(OUT PCONTEXT Context,IN PVOID Parameter OPTIONAL,IN PVOID InitialPc OPTIONAL, IN PVOID InitialSp OPTIONAL,IN BASE_CONTEXT_TYPE ContextType); VOID NTAPI RtlAcquirePebLock(VOID); VOID NTAPI RtlReleasePebLock(VOID); HANDLE NTAPI CreateRemoteThreadS(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); NTSTATUS NTAPI BaseCreateStack(IN HANDLE Process, IN SIZE_T StackSize, IN SIZE_T MaximumStackSize, OUT PINITIAL_TEB InitialTeb); PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(PVOID); PVOID RtlImageDirectoryEntryToData(IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size); VOID BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam); VOID NTAPI BaseProcessStart(LPVOID lpfnStartRoutine); NTSTATUS NTAPI NtOpenDirectoryObject(__out PHANDLE DirectoryHandle, __in ACCESS_MASK DesiredAccess, __in POBJECT_ATTRIBUTES ObjectAttributes); NTSTATUS NTAPI NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PULONG RegionSize, ULONG AllocationType, ULONG Protect); NTSTATUS NTAPI NtFreeVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PULONG RegionSize, ULONG FreeType); NTSTATUS NTAPI NtProtectVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UnsafeBaseAddress, IN OUT SIZE_T *UnsafeNumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG UnsafeOldAccessProtection); NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREAD_INFORMATION_CLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength ); NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL); NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL); NTSTATUS NTAPI NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout OPTIONAL); NTSTATUS NTAPI NtTerminateThread(HANDLE ThreadHandle, LONG ExitStatus); NTSTATUS NTAPI NtCreateThread(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, HANDLE ProcessHandle, PCLIENT_ID ClientId, PCONTEXT ThreadContext, PINITIAL_TEB InitialTeb, BOOLEAN CreateSuspended); }; extern "C" { NTSTATUS NTAPI NtQueryFullAttributesFile( __in POBJECT_ATTRIBUTES ObjectAttributes, __out PFILE_NETWORK_OPEN_INFORMATION FileInformation ); NTSTATUS NTAPI NtSetInformationFile( __in HANDLE FileHandle, __out PIO_STATUS_BLOCK IoStatusBlock, __in PVOID FileInformation, __in ULONG Length, __in FILE_INFORMATION_CLASS FileInformationClass ); NTSTATUS NTAPI NtQueryInformationFile( __in HANDLE FileHandle, __out PIO_STATUS_BLOCK IoStatusBlock, __out PVOID FileInformation, __in ULONG Length, __in FILE_INFORMATION_CLASS FileInformationClass ); NTSTATUS NTAPI NtReadFile( __in HANDLE FileHandle, __in_opt HANDLE Event, __in_opt PIO_APC_ROUTINE ApcRoutine, __in_opt PVOID ApcContext, __out PIO_STATUS_BLOCK IoStatusBlock, __out PVOID Buffer, __in ULONG Length, __in_opt PLARGE_INTEGER ByteOffset, __in_opt PULONG Key ); NTSTATUS NTAPI NtWriteFile( __in HANDLE FileHandle, __in_opt HANDLE Event, __in_opt PIO_APC_ROUTINE ApcRoutine, __in_opt PVOID ApcContext, __out PIO_STATUS_BLOCK IoStatusBlock, __in PVOID Buffer, __in ULONG Length, __in_opt PLARGE_INTEGER ByteOffset, __in_opt PULONG Key ); }; #endif
/******************************************************************** Created: 2012/02/01 18:17 Filename: NativeAPI.cpp Author: rrrfff Url: http://blog.csdn.net/rrrfff *********************************************************************/ #include "../Lib_Base.h" #include "NativeAPI.h" #pragma comment(lib, "Lib/ntoskrnl.lib") /************************************************************************/ POBJECT_ATTRIBUTES NTAPI BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,IN PUNICODE_STRING ObjectName) { HANDLE RootDirectory; ULONG Attributes; PVOID SecurityDescriptor = NULL; if (ARGUMENT_PRESENT(ObjectName) ) { if ( ARGUMENT_PRESENT(ObjectName) ) { RootDirectory = BaseGetNamedObjectDirectory(); } else { RootDirectory = NULL; } if ( ARGUMENT_PRESENT(ObjectName) ) { Attributes |= OBJ_OPENIF; } InitializeObjectAttributes( ObjectAttributes, ObjectName, Attributes, RootDirectory, SecurityDescriptor ); return ObjectAttributes; }else{ return NULL; } } NTSTATUS NTAPI BaseCreateStack(IN HANDLE Process, IN SIZE_T StackSize, IN SIZE_T MaximumStackSize, OUT PINITIAL_TEB InitialTeb) { NTSTATUS Status; PCH Stack; BOOLEAN GuardPage; SIZE_T RegionSize; ULONG OldProtect; SIZE_T ImageStackSize, ImageStackCommit; PIMAGE_NT_HEADERS NtHeaders; PPEB_ Peb; ULONG PageSize; Peb = NtCurrentPeb(); //BaseStaticServerData = BASE_SHARED_SERVER_DATA; PageSize = System::AppBase::GetSystemInfo()->PhysicalPageSize/*BASE_SYSINFO.PageSize*/; // // If the stack size was not supplied, then use the sizes from the // image header. // NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress); ImageStackSize = NtHeaders->OptionalHeader.SizeOfStackReserve; ImageStackCommit = NtHeaders->OptionalHeader.SizeOfStackCommit; if ( !MaximumStackSize ) { MaximumStackSize = ImageStackSize; } if (!StackSize) { StackSize = ImageStackCommit; } else { // // Now Compute how much additional stack space is to be // reserved. This is done by... If the StackSize is <= // Reserved size in the image, then reserve whatever the image // specifies. Otherwise, round up to 1Mb. // if ( StackSize >= MaximumStackSize ) { MaximumStackSize = ROUND_UP(StackSize, (1024*1024)); } } // // Align the stack size to a page boundry and the reserved size // to an allocation granularity boundry. // StackSize = ROUND_UP( StackSize, PageSize ); MaximumStackSize = ROUND_UP( MaximumStackSize, System::AppBase::GetSystemInfo()->AllocationGranularity ); #if !defined (_IA64_) // // Reserve address space for the stack // Stack = NULL, Status = NtAllocateVirtualMemory( Process, (PVOID *)&Stack, 0, &MaximumStackSize, MEM_RESERVE, PAGE_READWRITE ); #else // // Take RseStack into consideration. // RSE stack has same size as memory stack, has same StackBase, // has a guard page at the end, and grows upwards towards higher // memory addresses // // // Reserve address space for the two stacks // { SIZE_T TotalStackSize = MaximumStackSize * 2; Stack = NULL, Status = NtAllocateVirtualMemory( Process, (PVOID *)&Stack, 0, &TotalStackSize, MEM_RESERVE, PAGE_READWRITE ); } #endif // IA64 if ( !NT_SUCCESS( Status ) ) { return Status; } InitialTeb->OldInitialTeb.OldStackBase = NULL; InitialTeb->OldInitialTeb.OldStackLimit = NULL; InitialTeb->StackAllocationBase = Stack; InitialTeb->StackBase = Stack + MaximumStackSize; #if defined (_IA64_) InitialTeb->OldInitialTeb.OldBStoreLimit = NULL; #endif //IA64 Stack += MaximumStackSize - StackSize; if (MaximumStackSize > StackSize) { Stack -= PageSize; StackSize += PageSize; GuardPage = TRUE; } else { GuardPage = FALSE; } // // Commit the initially valid portion of the stack // #if !defined(_IA64_) Status = NtAllocateVirtualMemory( Process, (PVOID *)&Stack, 0, &StackSize, MEM_COMMIT, PAGE_READWRITE ); #else { // // memory and rse stacks are expected to be contiguous // reserver virtual memory for both stack at once // SIZE_T NewCommittedStackSize = StackSize * 2; Status = NtAllocateVirtualMemory( Process, (PVOID *)&Stack, 0, &NewCommittedStackSize, MEM_COMMIT, PAGE_READWRITE ); } #endif //IA64 if ( !NT_SUCCESS( Status ) ) { // // If the commit fails, then delete the address space for the stack // RegionSize = 0; NtFreeVirtualMemory( Process, (PVOID *)&Stack, &RegionSize, MEM_RELEASE ); return Status; } InitialTeb->StackLimit = Stack; #if defined(_IA64_) InitialTeb->BStoreLimit = Stack + 2 * StackSize; #endif // // if we have space, create a guard page. // if (GuardPage) { RegionSize = PageSize; Status = NtProtectVirtualMemory( Process, (PVOID *)&Stack, &RegionSize, PAGE_GUARD | PAGE_READWRITE, &OldProtect ); if ( !NT_SUCCESS( Status ) ) { return Status; } InitialTeb->StackLimit = (PVOID)((PUCHAR)InitialTeb->StackLimit + RegionSize); #if defined(_IA64_) // // additional code to Create RSE stack guard page // Stack = ((PCH)InitialTeb->StackBase) + StackSize - PageSize; RegionSize = PageSize; Status = NtProtectVirtualMemory( Process, (PVOID *)&Stack, &RegionSize, PAGE_GUARD | PAGE_READWRITE, &OldProtect ); if ( !NT_SUCCESS( Status ) ) { return Status; } InitialTeb->BStoreLimit = (PVOID)Stack; #endif // IA64 } return STATUS_SUCCESS; } HANDLE BaseNamedObjectDirectory = NULL; HANDLE NTAPI BaseGetNamedObjectDirectory(VOID) { OBJECT_ATTRIBUTES Obja; NTSTATUS Status; ACCESS_MASK DirAccess = DIRECTORY_ALL_ACCESS & ~(DELETE | WRITE_DAC | WRITE_OWNER); RtlAcquirePebLock(); if ( !BaseNamedObjectDirectory ) { InitializeObjectAttributes( &Obja, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &BaseNamedObjectDirectory, DirAccess, &Obja ); if ( !NT_SUCCESS(Status) ) { BaseNamedObjectDirectory = NULL; } } RtlReleasePebLock(); return BaseNamedObjectDirectory; } VOID NTAPI BaseProcessStart(LPVOID lpfnStartRoutine) { DWORD retValue = 0; __try { //将主线程的入口函数设置为mainCRTStartup NtSetInformationThread(GetCurrentThread(),ThreadQuerySetWin32StartAddress, &lpfnStartRoutine,sizeof(lpfnStartRoutine)); //retValue = lpfnStartRoutine(); __asm { call lpfnStartRoutine mov retValue, eax } } __except(retValue=GetExceptionCode(), UnhandledExceptionFilter(GetExceptionInformation())) { //if(BaseRunningInServerProcess) // ExitThread(retValue); //else ExitProcess(retValue); } } VOID NTAPI BaseInitializeContext(OUT PCONTEXT Context, IN PVOID Parameter OPTIONAL, IN PVOID InitialPc OPTIONAL, IN PVOID InitialSp OPTIONAL, IN BASE_CONTEXT_TYPE ContextType) /*++ Routine Description: This function initializes a context structure so that it can be used in a subsequent call to NtCreateThread. Arguments: Context - Supplies a context buffer to be initialized by this routine. Parameter - Supplies the thread's parameter. InitialPc - Supplies an initial program counter value. InitialSp - Supplies an initial stack pointer value. NewThread - Supplies a flag that specifies that this is a new thread, or a new process. Return Value: Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly aligned. Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly aligned. --*/ { Context->Eax = (ULONG)InitialPc; Context->Ebx = (ULONG)Parameter; Context->SegGs = 0; Context->SegFs = 0x38/*KGDT_R3_TEB*/; Context->SegEs = 0x20/*KGDT_R3_DATA*/; Context->SegDs = 0x20/*KGDT_R3_DATA*/; Context->SegSs = 0x20/*KGDT_R3_DATA*/; Context->SegCs = 0x18/*KGDT_R3_CODE*/; // // Start the thread at IOPL=3. // Context->EFlags = 0x3000; // // Always start the thread at the thread start thunk. // Context->Esp = (ULONG) InitialSp; if ( ContextType == BaseContextTypeThread ) { Context->Eip = (ULONG) BaseProcessStart; } else if ( ContextType == BaseContextTypeFiber ) { Context->Eip = (ULONG) BaseProcessStart; } else { Context->Eip = (ULONG) BaseProcessStart; } // // add code to check alignment and raise exception... // Context->ContextFlags = CONTEXT_FULL; Context->Esp -= sizeof(Parameter); // Reserve room for ret address } HANDLE APIENTRY CreateRemoteThreadS(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; POBJECT_ATTRIBUTES pObja; HANDLE Handle; CONTEXT ThreadContext; INITIAL_TEB InitialTeb; CLIENT_ID ClientId; // Allocate a stack for this thread Status = BaseCreateStack(hProcess, dwStackSize, 0L, &InitialTeb ); // Create an initial context BaseInitializeContext( &ThreadContext, lpParameter, (PVOID)lpStartAddress, InitialTeb.StackBase, BaseContextTypeThread); //pObja = BaseFormatObjectAttributes(&Obja, lpThreadAttributes, NULL); Status = NtCreateThread( &Handle, THREAD_ALL_ACCESS, pObja, hProcess, &ClientId, &ThreadContext, &InitialTeb, TRUE ); return Handle; }