めいくりぷとのブログ

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

システム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;
}