めいくりぷとのブログ

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

特に意味ない

何を思ってか、ラッパー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;
}