めいくりぷとのブログ

技術的なことやゲームのことやら・・・

マニュアルマッピングされたシステムモジュールをアンロードして、正規のモジュールにすり替える。

    EXTERN_C
    NTSTATUS
    NTAPI LdrLoadDll(
        _In_  PWCHAR          PathToFile OPTIONAL,
        _In_  ULONG           Flags OPTIONAL,
        _In_  PUNICODE_STRING ModuleFileName,
        _Out_ PHANDLE         ModuleHandle
        );
 
    VOID Detour_LdrLoadDll()
    {
        static decltype(&LdrLoadDll) _LdrLoadDll = LdrLoadDll;
 
        decltype(&LdrLoadDll) LdrLoadDll_Hook = [](
            _In_  PWCHAR          PathToFile OPTIONAL,
            _In_  ULONG           Flags OPTIONAL,
            _In_  PUNICODE_STRING ModuleFileName,
            _Out_ PHANDLE         ModuleHandle) -> NTSTATUS
        {
            IMAGE_EXPORT_DIRECTORY *pExportDirectory;
            NTSTATUS ntStatus;
            HMODULE  hModule;
            HMODULE  hModuleOriginal;
 
            ntStatus = _LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle);
            if (NT_SUCCESS(ntStatus))
            {
                hModule = reinterpret_cast<HMODULE>(*ModuleHandle);
                if (hModule != NULL)
                {
                    pExportDirectory = ImageExportDirectory(reinterpret_cast<PVOID>(hModule));
                    if (pExportDirectory != NULL)
                    {
                        hModuleOriginal = GetModuleHandleA(reinterpret_cast<LPCSTR>(PBYTE(hModule) + pExportDirectory->Name));
                        if (hModuleOriginal != NULL &&
                            hModuleOriginal != hModule)
                        {
                            // _tprintf(L"%p, %s\n", hModule, ModuleFileName->Buffer);
                            FreeLibrary(hModule);
                            *ModuleHandle = hModuleOriginal;
                        }
                    }                  
                }
            }
 
            return ntStatus;
        };
 
        DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_LdrLoadDll), LdrLoadDll_Hook);
    }

ウィンドウ検出のBypass

	BOOL Detour_GetWindowThreadProcessId()
	{
		static decltype(&GetWindowThreadProcessId) _GetWindowThreadProcessId = GetWindowThreadProcessId;

		decltype(&GetWindowThreadProcessId) GetWindowThreadProcessId_Hook = [](
			_In_      HWND    hWnd,
			_Out_opt_ LPDWORD lpdwProcessId) -> DWORD
		{
			HMODULE	hModule;
			DWORD	dwStatus;
			DWORD	dwTemp;

			GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<LPCWSTR>(_ReturnAddress()), &hModule);
			if (hModule == GetModuleHandle(TARGET_MODULE) ||
				hModule == NULL)
			{
				dwStatus = _GetWindowThreadProcessId(hWnd, &dwTemp);
				if (dwTemp != GetCurrentProcessId())
					dwTemp = GetCurrentProcessId();

				return dwStatus;
			}

			return _GetWindowThreadProcessId(hWnd, lpdwProcessId);
		};

		return DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_GetWindowThreadProcessId), GetWindowThreadProcessId_Hook);
	}

プロセス検出と最小化とそのBypass

プロセス検出&最小化

// ProcessMinimizer.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

#include <Windows.h>
#include <winternl.h>
#include <ntstatus.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
#pragma comment(lib, "ntdll.lib")

EXTERN_C
NTSTATUS 
WINAPI 
NtQuerySystemInformation(
	_In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
	_Inout_   PVOID                    SystemInformation,
	_In_      ULONG                    SystemInformationLength,
	_Out_opt_ PULONG                   ReturnLength
	);

_Success_(return != NULL)
HWND
WINAPI
GetWindowHandle(
	_In_  DWORD dwProcessId
	)
{
	HWND hWnd = GetTopWindow(NULL);

	do
	{
		if (GetWindowLong(hWnd, GWL_HWNDPARENT) != 0 || !IsWindowVisible(hWnd))
			continue;
	
		DWORD dwTemp = 0;
		GetWindowThreadProcessId(hWnd, &dwTemp);
		if (dwProcessId == dwTemp)
			return hWnd;
	
	} while ((hWnd = GetNextWindow(hWnd, GW_HWNDNEXT)) != NULL);

	return NULL;
}

_Success_(NT_SUCCESS(return))
NTSTATUS
NTAPI
ProcessMinimizer(
	)
{
	NTSTATUS ntStatus;
	SIZE_T nLength;
	PVOID pBuffer;
	SYSTEM_PROCESS_INFORMATION *pProcessInformation;

	ntStatus = NtQuerySystemInformation(SystemProcessInformation, NULL, sizeof(SYSTEM_PROCESS_INFORMATION), &nLength);
	if (ntStatus == STATUS_INFO_LENGTH_MISMATCH)
		pBuffer = VirtualAlloc(NULL, nLength, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

	if (reinterpret_cast<PVOID*>(pBuffer) != NULL)
	{
		ntStatus = NtQuerySystemInformation(SystemProcessInformation, pBuffer, nLength, NULL);
		if (NT_SUCCESS(ntStatus))
		{
			pProcessInformation = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(pBuffer);
			while (pProcessInformation != NULL
				&& pProcessInformation->NextEntryOffset > 0)
			{				
				DWORD dwProcessId = reinterpret_cast<DWORD>(pProcessInformation->UniqueProcessId);
				if (dwProcessId != GetCurrentProcessId())
				{
					HWND hWnd = GetWindowHandle(dwProcessId);
					HANDLE hProcess;
					WCHAR szFileName[MAX_PATH];

					if (hWnd != NULL)
					{
						PostMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, NULL);

						hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
						if (hProcess != INVALID_HANDLE_VALUE)
						{
							GetModuleFileNameEx(hProcess, NULL, szFileName, MAX_PATH);
							_tprintf(L"Minimize ProcessID: %08X ProcessName: %s\n", dwProcessId, szFileName);
						}
						else
						{
							_tprintf(L"Minimize ProcessID: %08X ProcessName: Unknown\n", dwProcessId);
						}
					}
				}

				pProcessInformation = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(
					reinterpret_cast<PBYTE>(pProcessInformation) + pProcessInformation->NextEntryOffset);
			}			
		}

                VirtualFree(pBuffer, 0, MEM_RELEASE);
	}

	return ntStatus;
}

int main()
{
	ProcessMinimizer();

	getchar();

    return 0;
}

Bypass

BOOL Detour_NtQuerySystemInformation()
{
	static decltype(&NtQuerySystemInformation) _NtQuerySystemInformation = NtQuerySystemInformation;

	decltype(&NtQuerySystemInformation) NtQuerySystemInformation_Hook = [](
		_In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
		_Inout_   PVOID                    SystemInformation,
		_In_      ULONG                    SystemInformationLength,
		_Out_opt_ PULONG                   ReturnLength) -> NTSTATUS
	{
		NTSTATUS ntStatus;

		ntStatus = _NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
		if (NT_SUCCESS(ntStatus))
			if (SystemInformationClass == SystemProcessInformation)
				PSYSTEM_PROCESS_INFORMATION(SystemInformation)->NextEntryOffset = 0;

		return ntStatus;
	};

	return DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_NtQuerySystemInformation), NtQuerySystemInformation_Hook);
}

ファイルのハッシュ値を取得する。

BOOL CCalcHash::GetMD2(__in LPCSTR lpcszFileName, __inout BYTE pbData[16])
{
	return GetFileHashA(lpcszFileName, pbData, 16, CALG_MD2);
}

BOOL CCalcHash::GetMD4(__in LPCSTR lpcszFileName, __inout BYTE pbData[16])
{
	return GetFileHashA(lpcszFileName, pbData, 16, CALG_MD4);
}

BOOL CCalcHash::GetMD5(__in LPCSTR lpcszFileName, __inout BYTE pbData[16])
{
	return GetFileHashA(lpcszFileName, pbData, 16, CALG_MD5);
}

BOOL CCalcHash::GetSHA1(__in LPCSTR lpcszFileName, __inout BYTE pbData[20])
{
	return GetFileHashA(lpcszFileName, pbData, 20, CALG_SHA1);
}

BOOL CCalcHash::GetMD2(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[16])
{
	return GetFileHashW(lpcwszFileName, pbData, 16, CALG_MD2);
}

BOOL CCalcHash::GetMD4(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[16])
{
	return GetFileHashW(lpcwszFileName, pbData, 16, CALG_MD4);
}

BOOL CCalcHash::GetMD5(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[16])
{
	return GetFileHashW(lpcwszFileName, pbData, 16, CALG_MD5);
}

BOOL CCalcHash::GetSHA1(__in LPCWSTR lpcwszFileName, __inout BYTE pbData[20])
{
	return GetFileHashW(lpcwszFileName, pbData, 20, CALG_SHA1);
}

BOOL CCalcHash::GetFileHashA(__in LPCSTR lpcszFileName, __inout BYTE* pbData, __in DWORD dwLength, __in DWORD dwFlags)
{
	INT nLength = MultiByteToWideChar(CP_ACP, 0, lpcszFileName, -1, NULL, 0);
	if (nLength == 0)
		return FALSE;

	std::unique_ptr<WCHAR> wszBuffer(new WCHAR[nLength]);
	if (MultiByteToWideChar(CP_ACP, 0, lpcszFileName, nLength, wszBuffer.get(), nLength) == 0)
		return FALSE;

	return GetFileHashW(wszBuffer.get(), pbData, dwLength, dwFlags);
}


BOOL CCalcHash::GetFileHashW(__in LPCWSTR lpcwszFileName, __inout BYTE* pbData, __in DWORD dwLength, __in DWORD dwFlags)
{
	BOOL bResult;
	HCRYPTPROV hProv;
	HCRYPTHASH hHash;
	HANDLE hFile;
	ULARGE_INTEGER lSize;
	BYTE pbHash[MAX_HASH_SIZE];

	if (lpcwszFileName == NULL || dwLength == 0 || dwLength > _countof(pbHash))
		return FALSE;

	ZeroMemory(pbHash, dwLength);

	hFile = CreateFile(lpcwszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return FALSE;	

	lSize.LowPart = GetFileSize(hFile, &lSize.HighPart);
	bResult = FALSE;
	hProv = NULL;
	hHash = NULL;

	if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET))
	{
		ULARGE_INTEGER lPos;
		DWORD dwReadBytes;
		BYTE pbTemp[64000]; // 64kb		

		if (CryptCreateHash(hProv, dwFlags, NULL, 0, &hHash))
		{
			lPos.QuadPart = 0;			

			while (TRUE)
			{
				ReadFile(hFile, pbTemp, _countof(pbTemp), &dwReadBytes, NULL);
				if (dwReadBytes <= 0)
					break;

				lPos.QuadPart += dwReadBytes;
				if (!CryptHashData(hHash, pbTemp, dwReadBytes, 0))
					break;

				if (lPos.QuadPart == lSize.QuadPart)
				{
					if (CryptGetHashParam(hHash, HP_HASHVAL, pbHash, &dwLength, 0))
					{
						memcpy_s(pbData, dwLength, pbHash, dwLength);

						if (!bResult)
						{
							bResult = TRUE;
							break;
						}
					}
				}
			}
		}
	}

	if (!bResult) 
		ZeroMemory(pbHash, dwLength);

	if (hHash) 
		CryptDestroyHash(hHash);

	if (hProv) 
		CryptReleaseContext(hProv, 0);

	CloseHandle(hFile);	

	return bResult;
}

システムDLLのPDBファイルをダウンロードする。

NtQueryInformationProcess から現在のプロセスのPEBを取得し、std::list<> に LDR_DATA_TABLE_ENTRY へのポインタを格納し、GetPdbOfSystemFileW(...) を呼び出します。
今回はGetCurrentProcess()を使い現在プロセスのを取得していますが、
任意のプロセスハンドルのを取得する場合は、ReadProcessMemoryでPEBなど読み取りましょう。

#include "stdafx.h"

#include <list>
#include <winternl.h>
#include <DbgHelp.h>
#include <dia2.h>

#pragma comment(lib, "dbghelp.lib")
#pragma comment(lib, "diaguids.lib")
#pragma comment(lib, "ntdll.lib")

extern "C" NTSTATUS NTAPI NtQueryInformationProcess(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

BOOL WINAPI GetPdbOfSystemFileW(__in LPCWSTR lpszFileName, __out LPWSTR lpszPdbPath)
{
	SYMSRV_INDEX_INFOW SymInfo = { 0 };
	WCHAR szCurPath[MAX_PATH], szSysFile[MAX_PATH];
	WCHAR szSymName[MAX_PATH];

	GetCurrentDirectory(MAX_PATH, szCurPath);
	StringCchPrintf(szSymName, MAX_PATH, L"srv*%s*http://msdl.microsoft.com/download/symbols", szCurPath);

	GetSystemDirectory(szSysFile, MAX_PATH);
	StringCchPrintf(szSysFile, MAX_PATH, L"%s\\%s", szSysFile, lpszFileName);

	SymSetOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_DEBUG);
	if (!SymInitializeW(GetCurrentProcess(), szSymName, FALSE))
		return FALSE;

	SymInfo.sizeofstruct = sizeof(SYMSRV_INDEX_INFOW);
	if (!SymSrvGetFileIndexInfoW(lpszFileName, &SymInfo, 0))
		return FALSE;

	if (!SymFindFileInPathW(GetCurrentProcess(), NULL, SymInfo.pdbfile, &SymInfo.guid, SymInfo.age, 0, SSRVOPT_GUIDPTR, lpszPdbPath, NULL, NULL))
		return FALSE;

	return TRUE;
}

NTSTATUS NTAPI GetLoaderDataTableEntries(__out std::list<LDR_DATA_TABLE_ENTRY*> *pModules)
{
	PROCESS_BASIC_INFORMATION pbi;
	NTSTATUS ntStatus;

	PEB_LDR_DATA *pLdrData;
	LIST_ENTRY *pCurrentList;
	LIST_ENTRY *pList;
	LDR_DATA_TABLE_ENTRY *pLdrTable;

	if (!pModules)
		return STATUS_INVALID_PARAMETER;

	ntStatus = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL);
	if (NT_SUCCESS(ntStatus))
	{
		pLdrData = pbi.PebBaseAddress->Ldr;
		if (pLdrData != NULL)
		{			
			pCurrentList = pLdrData->InLoadOrderModuleList.Flink;
			pList = pLdrData->InLoadOrderModuleList.Blink;

			while (pCurrentList != pList)
			{
				pLdrTable = reinterpret_cast<LDR_DATA_TABLE_ENTRY*>(pCurrentList);
				if (pLdrTable != NULL)
				{
					pModules->push_back(pLdrTable);

					pCurrentList = pLdrTable->InLoadOrderModuleList.Flink;
					continue;
				}
				break;
			}
		}
	}

	return ntStatus;
}

int main()
{
	std::list<LDR_DATA_TABLE_ENTRY*> ModuleList;

	if (NT_SUCCESS(GetLoaderDataTableEntries(&ModuleList)))
	{
		for (LDR_DATA_TABLE_ENTRY* pLdrTable : ModuleList)
		{
			WCHAR szPdbFile[MAX_PATH];

			if (GetPdbOfSystemFileW(pLdrTable->FullDllName.Buffer, szPdbFile))
			{
				_tprintf(L"%s\n", szPdbFile);
			}
			else
			{
				_tprintf(L"%s is not found. \n", pLdrTable->FullDllName.Buffer);
			}
		}
	}

	getchar();

    return 0;
}

特に意味ない

何を思ってか、ラッパーAPI書いてる。

BOOL XAPI::DeviceIoControl(
	_In_        HANDLE       hDevice,
	_In_        DWORD        dwIoControlCode,
	_In_opt_    LPVOID       lpInBuffer,
	_In_        DWORD        nInBufferSize,
	_Out_opt_   LPVOID       lpOutBuffer,
	_In_        DWORD        nOutBufferSize,
	_Out_opt_   LPDWORD      lpBytesReturned,
	_Inout_opt_ LPOVERLAPPED lpOverlapped)
{
	IO_STATUS_BLOCK IoStatusBlock;
	NTSTATUS ntStatus;
	
	if (!lpOverlapped)
	{
		if ((dwIoControlCode >> 16) == 0x9)
		{
			ntStatus = NtFsControlFile(hDevice, NULL, NULL, NULL, 
				&IoStatusBlock, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize);
		}
		else
		{
			ntStatus = NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, 
				&IoStatusBlock, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize);
		}

		if (ntStatus == STATUS_PENDING)
		{
			ntStatus = NtWaitForSingleObject(hDevice, 0, NULL);
			if (NT_SUCCESS(ntStatus))
			{
				ntStatus = IoStatusBlock.Status;
				if (NT_SUCCESS(ntStatus))
				{
					if (lpBytesReturned)
						*lpBytesReturned = IoStatusBlock.Information;

					return TRUE;
				}
			}

			if ((ntStatus & 0xC0000000) != 0xC0000000 && lpBytesReturned)
				*lpBytesReturned = IoStatusBlock.Information;

			BaseSetLastNTError(ntStatus);
			return FALSE;
		}

		if (NT_SUCCESS(ntStatus))
		{
			if (lpBytesReturned)
				*lpBytesReturned = IoStatusBlock.Information;
			return TRUE;
		}

		BaseSetLastNTError(ntStatus);
		return FALSE;
	}

	lpOverlapped->Internal = STATUS_PENDING;
	if ((dwIoControlCode >> 16) == 0x9) 
	{
		ntStatus = NtFsControlFile(hDevice, lpOverlapped->hEvent, NULL, 
			reinterpret_cast<PVOID>(((DWORD)lpOverlapped->hEvent & 1) == NULL ? (DWORD)lpOverlapped : NULL),
			reinterpret_cast<PIO_STATUS_BLOCK>(lpOverlapped), 
			dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize);
	}
	else 
	{
		ntStatus = NtDeviceIoControlFile(hDevice, lpOverlapped->hEvent, NULL,
			reinterpret_cast<PVOID>(((DWORD)lpOverlapped->hEvent & 1) == NULL ? (DWORD)lpOverlapped : NULL),
			reinterpret_cast<PIO_STATUS_BLOCK>(lpOverlapped),
			dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize);
	}

	IoStatusBlock.Information = ntStatus;
	if ((ntStatus & 0xC0000000) != 0xC0000000 && lpBytesReturned)
		*lpBytesReturned = lpOverlapped->InternalHigh;

	if (IoStatusBlock.Information != STATUS_PENDING && (IoStatusBlock.Information & 0x80000000) == STATUS_SUCCESS)
		return TRUE;

	BaseSetLastNTError(IoStatusBlock.Information);
	return FALSE;
}

FARPROC XAPI::GetProcAddress(
	_In_ HMODULE hModule,
	_In_ LPCSTR  lpProcName)
{
	PIMAGE_EXPORT_DIRECTORY pExportDirectory;
	PIMAGE_NT_HEADERS pNtHeaders;
	PIMAGE_DOS_HEADER pDosHeader;
	DWORD dwOrdinal;

	if (!hModule)
		hModule = reinterpret_cast<HMODULE>(this->GetProcessEnvironmentBlock()->Reserved3[1]);

	pDosHeader = PIMAGE_DOS_HEADER(hModule);
	if (!pDosHeader)
		return NULL;

	pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(PBYTE(hModule) + pDosHeader->e_lfanew);
	if (!pNtHeaders || pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
		return NULL;

	pExportDirectory = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(PBYTE(hModule) + pNtHeaders->EXPORT_DIRECTORY.VirtualAddress);
	if (pExportDirectory == NULL)
		return NULL;

	dwOrdinal = reinterpret_cast<DWORD>(lpProcName);

	if (dwOrdinal < 0x10000)
	{
		if (dwOrdinal < pExportDirectory->Base)
			return NULL;

		dwOrdinal -= pExportDirectory->Base;
	}
	else
	{
		for (int i = 0; i < pExportDirectory->NumberOfNames; ++i)
		{
			if (!this->_stricmp(reinterpret_cast<LPCSTR>((reinterpret_cast<DWORD*>(PBYTE(hModule) + pExportDirectory->AddressOfNames))[i] + PBYTE(hModule)), lpProcName))
			{
				dwOrdinal = reinterpret_cast<WORD*>(PBYTE(hModule) + pExportDirectory->AddressOfNameOrdinals)[i];
				break;
			}
		}
	}

	return reinterpret_cast<FARPROC>(reinterpret_cast<DWORD*>(PBYTE(hModule) + pExportDirectory->AddressOfFunctions)[dwOrdinal] + PBYTE(hModule));
}

HMODULE XAPI::GetModuleHandleW(_In_ LPCWSTR lpModuleName)
{
	PPEB pProcessEnvironmentBlock;
	HMODULE hModule;

	pProcessEnvironmentBlock = this->GetProcessEnvironmentBlock();
	if (!pProcessEnvironmentBlock)
		return NULL;

	if (lpModuleName != NULL)
	{
		PLDR_DATA_TABLE_ENTRY pLdrTable;
		PPEB_LDR_DATA pLdrData;
		PLIST_ENTRY pEndList;
		PLIST_ENTRY pCurrentList;

		pLdrData = pProcessEnvironmentBlock->Ldr;
		if (pLdrData != NULL)
		{
			pEndList = pLdrData->InLoadOrderModuleList.Blink;
			pCurrentList = pLdrData->InLoadOrderModuleList.Flink;

			while (pCurrentList != pEndList)
			{
				pLdrTable = reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(pCurrentList);

				if (this->_wcsicmp(pLdrTable->BaseDllName.Buffer, lpModuleName) == NO_ERROR)
					hModule = reinterpret_cast<HMODULE>(pLdrTable->BaseAddress);

				pCurrentList = pLdrTable->InLoadOrderModuleList.Flink;
			}
		}
	}
	else
	{
		hModule = reinterpret_cast<HMODULE>(pProcessEnvironmentBlock->Reserved3[1]);
	}

	return hModule;
}

HANDLE XAPI::OpenProcess(
	_In_ DWORD dwDesiredAccess,
	_In_ BOOL  bInheritHandle,
	_In_ DWORD dwProcessId)
{
	NTSTATUS Status;
	HANDLE ProcessHandle;
	CLIENT_ID ClientId;
	OBJECT_ATTRIBUTES ObjectAttributes;

	ClientId.UniqueProcess = dwProcessId;
	ClientId.UniqueThread = NULL;
	InitializeObjectAttributes(&ObjectAttributes, NULL, bInheritHandle ? OBJ_INHERIT : NULL, NULL, NULL);

	Status = this->NtOpenProcess(&ProcessHandle, dwDesiredAccess, &ObjectAttributes, &ClientId);
	if (!NT_SUCCESS(Status))
	{
		this->BaseSetLastNTError(Status);
		return INVALID_HANDLE_VALUE;
	}

	return ProcessHandle;
}

__declspec(naked) NTSTATUS XSysEnter::NtAllocateVirtualMemory(
	_In_    HANDLE    ProcessHandle,
	_Inout_ PVOID     *BaseAddress,
	_In_    ULONG_PTR ZeroBits,
	_Inout_ PSIZE_T   RegionSize,
	_In_    ULONG     AllocationType,
	_In_    ULONG     Protect)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtAllocateVirtualMemory
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0018
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtDeviceIoControlFile(
	_In_  HANDLE           FileHandle,
	_In_  HANDLE           Event,
	_In_  PIO_APC_ROUTINE  ApcRoutine,
	_In_  PVOID            ApcContext,
	_Out_ PIO_STATUS_BLOCK IoStatusBlock,
	_In_  ULONG            IoControlCode,
	_In_  PVOID            InputBuffer,
	_In_  ULONG            InputBufferLength,
	_Out_ PVOID            OutputBuffer,
	_In_  ULONG            OutputBufferLength)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtDeviceIoControlFile
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0028
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtFreeVirtualMemory(
	_In_    HANDLE  ProcessHandle,
	_Inout_ PVOID   *BaseAddress,
	_Inout_ PSIZE_T RegionSize,
	_In_    ULONG   FreeType)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtFreeVirtualMemory
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0010
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtFsControlFile(
	_In_      HANDLE           FileHandle,
	_In_opt_  HANDLE           Event,
	_In_opt_  PIO_APC_ROUTINE  ApcRoutine,
	_In_opt_  PVOID            ApcContext,
	_Out_     PIO_STATUS_BLOCK IoStatusBlock,
	_In_      ULONG            FsControlCode,
	_In_opt_  PVOID            InputBuffer,
	_In_      ULONG            InputBufferLength,
	_Out_opt_ PVOID            OutputBuffer,
	_In_      ULONG            OutputBufferLength)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtFsControlFile
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0028
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtOpenProcess(
	_Out_    PHANDLE            ProcessHandle,
	_In_     ACCESS_MASK        DesiredAccess,
	_In_     POBJECT_ATTRIBUTES ObjectAttributes,
	_In_opt_ PCLIENT_ID         ClientId)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtOpenProcess
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0010
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtQueryInformationProcess(
	_In_      HANDLE           ProcessHandle,
	_In_      PROCESSINFOCLASS ProcessInformationClass,
	_Out_     PVOID            ProcessInformation,
	_In_      ULONG            ProcessInformationLength,
	_Out_opt_ PULONG           ReturnLength)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtQueryInformationProcess
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0014
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtQuerySystemInformation(
	_In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
	_Inout_   PVOID                    SystemInformation,
	_In_      ULONG                    SystemInformationLength,
	_Out_opt_ PULONG                   ReturnLength)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtQuerySystemInformation
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0010
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtReadVirtualMemory(
	_In_  HANDLE  ProcessHandle,
	_In_  LPCVOID BaseAddress,
	_Out_ LPVOID  Buffer,
	_In_  SIZE_T  NumberOfBytesToRead,
	_Out_ PSIZE_T NumberOfBytesReaded)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtReadVirtualMemory
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x0014
	}

	VMProtectEnd();
}

__declspec(naked) NTSTATUS XSysEnter::NtWaitForSingleObject(
	_In_ HANDLE         Handle,
	_In_ BOOLEAN        Alertable,
	_In_ PLARGE_INTEGER Timeout)
{
	VMProtectBeginUltra(__FUNCTION__);

	__asm
	{
		mov eax, SCT_NtWaitForSingleObject
		mov edx, fs:[0x000000C0]
		call edx
		ret 0x000C
	}

	VMProtectEnd();
}

Example

NTSTATUS GetProcessList()
{
	XAPI *pAPI = XAPI::GetInstance();
	NTSTATUS ntStatus;
	LPVOID lpBuffer;
	ULONG ulReturnLength;
	SYSTEM_PROCESS_INFORMATION *pProcessInformation;

	if (!pAPI)
		return STATUS_UNSUCCESSFUL;

	VMProtectBeginVirtualization(__FUNCTION__);

	ntStatus = pAPI->NtQuerySystemInformation(SystemProcessInformation, NULL, sizeof(SYSTEM_PROCESS_INFORMATION), &ulReturnLength);
	if (ntStatus == STATUS_INFO_LENGTH_MISMATCH)
		lpBuffer = pAPI->VirtualAlloc(NULL, ulReturnLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	ntStatus = pAPI->NtQuerySystemInformation(SystemProcessInformation, lpBuffer, ulReturnLength, NULL);
	if (NT_SUCCESS(ntStatus))
	{
		pProcessInformation = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(lpBuffer);
		while (pProcessInformation
			&& pProcessInformation->NextEntryDelta)
		{			
			HANDLE hProcess = pAPI->OpenProcess(PROCESS_ALL_ACCESS, FALSE, pProcessInformation->ProcessId);

			wprintf(L"ProcessID: %08X, ProcessHandle: %08X, ProcessName: %s\n", pProcessInformation->ProcessId, hProcess, pProcessInformation->ProcessName.Buffer);

			pProcessInformation = reinterpret_cast<SYSTEM_PROCESS_INFORMATION*>(
				reinterpret_cast<PBYTE>(pProcessInformation) + pProcessInformation->NextEntryDelta);
		}
	}

	pAPI->VirtualFree(lpBuffer, 0, MEM_RELEASE);

	VMProtectEnd();

	return ntStatus;
}

int main()
{
	GetProcessList();

	getchar();

	return 0;
}