めいくりぷとのブログ

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

プロセス/実行ファイルのPE情報を取得する。

まずは、適当な構造体を用意します。
自分の場合は、x86/x64共用で動作する関数を作りたかったので、オフセットが異なる構造体だけ unionで定義します。

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;


ReadProcessMemoryを使い取得することも可能ですが、
今回はPEだけなのでMapViewOfFileで当該プロセス/実行ファイルのメモリをマッピングさせて取得します。

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, Invalid Parameter. \n");
		return FALSE;
	}

	// Create file handle from target file name.
	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));
				}
			}
		}

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

	CloseHandle(hMapFile);
	CloseHandle(hFile);

	return bResult;
}

int main(void)
{
	PE_INFO pe;
	WCHAR wszPath[MAX_PATH];

	if (GetModuleFileName(NULL, wszPath, MAX_PATH) != 0)
	{
		if (GetPEInfo(wszPath, &pe))
		{
#ifdef _WIN64
			printf("entry point: %p\n", pe.OptionalHeader64.ImageBase, pe.OptionalHeader64.AddressOfEntryPoint);
#else
			printf("entry point: %p\n", pe.OptionalHeader32.ImageBase, pe.OptionalHeader32.AddressOfEntryPoint);
#endif
		}
	}

	getchar();

	return 0;
}

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