めいくりぷとのブログ

技術的なことをまったりと。

プロセスのセクション情報を取得する。

typedef struct _PE_INFO
{
	DWORD Signature;
	IMAGE_DOS_HEADER DosHeader;
	IMAGE_FILE_HEADER FileHeader;
	union
	{
		IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
		IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
	};
}PE_INFO, *PPE_INFO;

typedef struct _SYSTEM_SECTION
{
	CHAR  Name[8];			// _Out_
	DWORD VirtualAddress;	// _Out_
	DWORD VirtualSize;		// _Out_
}SYSTEM_SECTION, *PSYSTEM_SECTION;

typedef struct _PROCESS_SECTION_INFORMATION
{
	WORD		   NumberOfSections;
	SYSTEM_SECTION Information[1];
}PROCESS_SECTION_INFORMATION, *PPROCESS_SECTION_INFORMATION;

BOOL GetPEInfo(__in_z LPCWSTR lpszFileName, __out PPE_INFO pPEInfo)
{
	IMAGE_DOS_HEADER *pDosHeader;
	IMAGE_NT_HEADERS *pNtHeaders;

	HANDLE hFile, hMapFile;
	PVOID  pBuffer;
	BOOL   bResult;

	// Check NULL Pointer Exception.
	if (!pPEInfo)
	{
		_tprintf(L"NULL Pointer Exception\n");
		return FALSE;
	}

	// Create file handle from target file full-path.
	hFile = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		_tprintf(L"CreateFileW GLE = %08X\n", GetLastError());
		return FALSE;
	}

	// Returns : Mapped file handle, if failed return NULL.
	hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
	if (hMapFile == NULL)
	{
		_tprintf(L"CreateFileMappingW GLE = %08X\n", GetLastError());
		CloseHandle(hFile);
		return FALSE;
	}

	// Create buffer from mapped file handle
	pBuffer = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
	bResult = FALSE;

	if (pBuffer != NULL)
	{
		// dos header
		pDosHeader = PIMAGE_DOS_HEADER(pBuffer);
		if (pDosHeader != NULL &&
			pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) // MZ
		{
			// nt headers
			pNtHeaders = PIMAGE_NT_HEADERS(PBYTE(pBuffer) + pDosHeader->e_lfanew);
			if (pNtHeaders != NULL &&
				pNtHeaders->Signature == IMAGE_NT_SIGNATURE) // PE
			{
				pPEInfo->Signature = pNtHeaders->Signature;
				memcpy(&pPEInfo->DosHeader, pDosHeader, sizeof(IMAGE_DOS_HEADER));
				memcpy(&pPEInfo->FileHeader, &pNtHeaders->FileHeader, sizeof(IMAGE_FILE_HEADER));				

				// x86
				if (pNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
				{
					bResult			 = TRUE;
					RtlCopyMemory(
						&pPEInfo->OptionalHeader32,
						&(PIMAGE_NT_HEADERS32(pNtHeaders)->OptionalHeader), sizeof(IMAGE_OPTIONAL_HEADER32));
				}
				// x64
				else if (pNtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
				{
					bResult			 = TRUE;
					RtlCopyMemory(
						&pPEInfo->OptionalHeader64,
						&(PIMAGE_NT_HEADERS64(pNtHeaders)->OptionalHeader), sizeof(IMAGE_OPTIONAL_HEADER64));
				}
			}
		}

		// Unmap mapped file buffer
		UnmapViewOfFile(pBuffer);
	}
	else
	{
		_tprintf(L"MapViewOfFile GLE = %08X\n", GetLastError());
	}

	CloseHandle(hMapFile);
	CloseHandle(hFile);

	return bResult;
}

NTSTATUS
NTAPI
NtQuerySectionInformation(
	__in	 HANDLE						  ProcessHandle,
	__inout  PPROCESS_SECTION_INFORMATION SectionInformation,
	__in	 ULONG						  SectionInformationLength,
	__in_opt PULONG						  ReturnLength
	)
{
	IMAGE_SECTION_HEADER *pSectionHeader;
	NTSTATUS ntStatus;
	ULONG	 uLength;
	PVOID	 pBuffer;

	PE_INFO  peInfo;
	WCHAR	 szPath[MAX_PATH];

	// Check parameter.
	if (!SectionInformation && !ReturnLength)
		return STATUS_INVALID_PARAMETER;

	// Get file-name from process handle.
	if (GetModuleFileNameExW(ProcessHandle, NULL, szPath, MAX_PATH) == 0)
		return STATUS_ACCESS_DENIED;	

	// Get pe information.
	if (!GetPEInfo(szPath, &peInfo))
		return STATUS_ACCESS_DENIED;	

	uLength  = sizeof(SYSTEM_SECTION) * peInfo.FileHeader.NumberOfSections;
	ntStatus = STATUS_UNSUCCESSFUL;

	if (uLength > 0)
	{
		// STATUS_INFO_LENGTH_MISMATCH
		if ((uLength > SectionInformationLength) || !SectionInformation)
		{
			if (ReturnLength != NULL)
			{
				*ReturnLength = uLength;
				return STATUS_INFO_LENGTH_MISMATCH;
			}

			return STATUS_INVALID_PARAMETER;
		}		

		IMAGE_NT_HEADERS *pNtHeaders;
		ULONG_PTR ImageBase;
		ULONG_PTR SectionAlignment;
		ULONG	  SizeOfImage, SizeOfCode;

		// x86
		if (peInfo.FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
		{
			ImageBase	= peInfo.OptionalHeader32.ImageBase;
			SizeOfCode	= peInfo.OptionalHeader32.SizeOfCode;
			SizeOfImage = peInfo.OptionalHeader32.SizeOfImage;
			SectionAlignment = peInfo.OptionalHeader32.SectionAlignment;
		}
		// x64
		if (peInfo.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
		{
			ImageBase	= peInfo.OptionalHeader64.ImageBase;
			SizeOfCode	= peInfo.OptionalHeader64.SizeOfCode;
			SizeOfImage = peInfo.OptionalHeader64.SizeOfImage;
			SectionAlignment = peInfo.OptionalHeader64.SectionAlignment;
		}

		pBuffer = VirtualAlloc(NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

		if (pBuffer != NULL)
		{
			// 
			if (!ReadProcessMemory(ProcessHandle, reinterpret_cast<LPCVOID>(ImageBase), pBuffer, SizeOfCode, NULL))
			{
				// ReadProcessMemory failed.
				VirtualFree(pBuffer, 0, MEM_RELEASE);
				return STATUS_ACCESS_DENIED;
			}			

			// Read nt header.
			pNtHeaders = RtlImageNtHeader(pBuffer);
			if (pNtHeaders != NULL)
			{
				// Read section header.
				pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
				if (pSectionHeader != NULL)
				{
					for (int i = 0; i < peInfo.FileHeader.NumberOfSections; i++)
					{
						memcpy(SectionInformation->Information[i].Name, pSectionHeader[i].Name, 8);
						SectionInformation->Information[i].VirtualAddress = ImageBase + pSectionHeader[i].VirtualAddress;
						SectionInformation->Information[i].VirtualSize =
							pSectionHeader[i].Misc.VirtualSize + (SectionAlignment - pSectionHeader[i].Misc.VirtualSize % SectionAlignment);
					}

					SectionInformation->NumberOfSections = peInfo.FileHeader.NumberOfSections;
					if (ReturnLength)
						*ReturnLength = uLength;

					ntStatus = STATUS_SUCCESS;
				}
			}

			// Release memory
			VirtualFree(pBuffer, 0, MEM_RELEASE);
		}
	}

	return ntStatus;
}

int main(void)
{
	PROCESS_SECTION_INFORMATION *pSectionInformation;
	NTSTATUS ntStatus;
	ULONG	 uLength;
	PVOID	 pBuffer;
	HANDLE	 hProcess;
	
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
	if (hProcess != INVALID_HANDLE_VALUE)
	{
		ntStatus = NtQuerySectionInformation(hProcess, NULL, 0, &uLength);
		if (ntStatus == STATUS_INFO_LENGTH_MISMATCH)
			pBuffer = VirtualAlloc(NULL, uLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

		if (pBuffer != NULL)
		{
			pSectionInformation = reinterpret_cast<PROCESS_SECTION_INFORMATION*>(pBuffer);

			if (NT_SUCCESS(NtQuerySectionInformation(hProcess, pSectionInformation, uLength, NULL)))
			{
				for (WORD n = 0; n < pSectionInformation->NumberOfSections; n++)
				{
					printf("Section name: %s, Address: %p, Size: %08X \n", 
						pSectionInformation->Information[n].Name, 
						pSectionInformation->Information[n].VirtualAddress, 
						pSectionInformation->Information[n].VirtualSize);
				}
			}

			VirtualFree(pBuffer, 0, MEM_RELEASE);
		}
	}

	getchar();

	return 0;
}

結果:
f:id:mcrypt:20180326005354p:plain