// NetAnalyze.cpp : implementation file
//
#include "stdafx.h"
#include "resource.h"
#include "PEAnalyzeDlg.h"
#include "NetAnalyze.h"
// CNetAnalyze
CNetAnalyze::CNetAnalyze(IMAGE_NT_HEADERS* pHeader, LOADED_IMAGE* pImage, CPEAnalyzeDlg* pDlg) : m_ntHeader(pHeader), m_image(*pImage), m_outDlg(pDlg)
{
CoInitialize(NULL);
HRESULT hRes = CoCreateInstance(CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER, IID_IMetaDataDispenserEx, (void**)&m_dispenser);
if(FAILED(hRes) || m_dispenser == NULL)
{
m_outDlg->AppendOutputString(CString(_T("Failed to load MetaDataDispenser!")));
return;
}
IMAGE_COR20_HEADER* netHeader = (IMAGE_COR20_HEADER*)ImageRvaToVa(m_ntHeader, m_image.MappedAddress, m_ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
if(netHeader == NULL)
{
m_outDlg->AppendOutputString(CString(_T("No valid .NET-assembly!")));
return;
}
LPCVOID metaData = (LPCVOID)ImageRvaToVa(m_ntHeader, m_image.MappedAddress, netHeader->MetaData.VirtualAddress, NULL);
if(metaData == NULL)
{
m_outDlg->AppendOutputString(CString(_T("No metadata associated!")));
return;
}
hRes = m_dispenser->OpenScopeOnMemory(metaData, netHeader->MetaData.Size, 0, IID_IMetaDataImport2, (IUnknown**)&m_importer);
if(FAILED(hRes) || m_importer == NULL)
{
m_outDlg->AppendOutputString(CString(_T("Failed to open scope on metatdata memory!")));
return;
}
hRes = m_dispenser->OpenScopeOnMemory(metaData, netHeader->MetaData.Size, 0, IID_IMetaDataAssemblyImport, (IUnknown**)&m_assemblyReader);
if(FAILED(hRes) || m_assemblyReader == NULL)
{
m_outDlg->AppendOutputString(CString(_T("Failed to open assembly scope on metadata memory!")));
return;
}
m_outDlg->AppendOutputString(CString(_T("Ready to parse metadata...")));
}
CNetAnalyze::~CNetAnalyze()
{
if(m_dispenser)
m_dispenser->Release();
if(m_importer)
m_importer->Release();
if(m_assemblyReader)
m_assemblyReader->Release();
}
void CNetAnalyze::LoadMetaData()
{
WCHAR module[MAX_PATH];
ULONG nameLen;
m_importer->GetScopeProps(module, MAX_PATH, &nameLen, NULL);
m_outDlg->AppendOutputString(CString(_T("Loading module '")) + module + _T("'..."));
LoadTypes();
LoadTypeReferences();
LoadAssemblyReferences();
}
void CNetAnalyze::LoadTypes()
{
HCORENUM corEnum = 0;
mdTypeDef typeDefs[10];
ULONG numTypeDefs = 0;
while(SUCCEEDED(m_importer->EnumTypeDefs(&corEnum, typeDefs, 10, &numTypeDefs)))
{
if(numTypeDefs == 0)
break;
for(ULONG i = 0; i < numTypeDefs; ++i)
ParseTypeDef(typeDefs[i]);
}
m_importer->CloseEnum(corEnum);
}
void CNetAnalyze::ParseTypeDef(mdTypeDef& def)
{
WCHAR typeDefName[MAX_PATH];
ULONG nameLen;
DWORD flags;
mdToken extend;
HRESULT hRes = m_importer->GetTypeDefProps(def, typeDefName, MAX_PATH, &nameLen, &flags, &extend);
if(FAILED(hRes))
return;
m_outDlg->AppendOutputString(CString(typeDefName));
LoadMethods(def);
// TODO:
// Implement fields, properties, ...
}
void CNetAnalyze::LoadMethods(mdTypeDef& def)
{
HCORENUM corEnum = 0;
mdMethodDef typeDefs[10];
ULONG numTypeDefs = 0;
while(SUCCEEDED(m_importer->EnumMethods(&corEnum, def, typeDefs, 10, &numTypeDefs)))
{
if(numTypeDefs == 0)
break;
for(ULONG i = 0; i < numTypeDefs; ++i)
LoadMethodInfo(typeDefs[i], def);
}
m_importer->CloseEnum(corEnum);
}
void CNetAnalyze::LoadMethodInfo(mdMethodDef& def, mdTypeDef& type)
{
WCHAR methodName[MAX_PATH];
ULONG nameLen;
DWORD flags;
PCCOR_SIGNATURE sig;
/// TODO:
/// Implement PCCOR_SIGNATURE and the last (yet unused) parameters of GetMethodProps
HRESULT hRes = m_importer->GetMethodProps(def, &type, methodName, MAX_PATH, &nameLen, &flags, &sig, &nameLen, &nameLen, &nameLen);
if(FAILED(hRes))
return;
m_outDlg->AppendOutputString(CString(methodName));
}
void CNetAnalyze::LoadTypeReferences()
{
HCORENUM corEnum = NULL;
mdTypeRef refs[10];
ULONG numRefs = 0;
while(SUCCEEDED(m_importer->EnumTypeRefs(&corEnum, refs, 10, &numRefs)))
{
if(numRefs == 0)
break;
for(ULONG i = 0; i < numRefs; ++i)
ParseTypeReference(refs[i]);
}
}
void CNetAnalyze::ParseTypeReference(mdTypeRef& ref)
{
mdToken refToken;
WCHAR refName[MAX_PATH];
ULONG nameLen;
HRESULT hRes = m_importer->GetTypeRefProps(ref, &refToken, refName, MAX_PATH, &nameLen);
if(FAILED(hRes))
return;
m_outDlg->AppendOutputString(CString(refName));
}
void CNetAnalyze::LoadAssemblyReferences()
{
HCORENUM corEnum = NULL;
mdAssemblyRef refs[10];
ULONG numRefs = 0;
while(SUCCEEDED(m_assemblyReader->EnumAssemblyRefs(&corEnum, refs, 10, &numRefs)))
{
if(numRefs == 0)
return;
for(ULONG i = 0; i < numRefs; ++i)
ParseAssemblyReference(refs[i]);
}
}
void CNetAnalyze::ParseAssemblyReference(mdAssemblyRef& ref)
{
WCHAR refName[MAX_PATH];
ULONG nameLen;
HRESULT hRes = m_assemblyReader->GetAssemblyRefProps(ref, NULL, NULL, refName, MAX_PATH, &nameLen, NULL, NULL, NULL, NULL);
if(FAILED(hRes))
return;
m_outDlg->AppendOutputString(CString(refName));
}
// CNetAnalyze member functions