Skip to content

Instantly share code, notes, and snippets.

@hfiref0x

hfiref0x/fusion.c

Created Sep 13, 2020
Embed
What would you like to do?
#include <fusion.h>
typedef HRESULT(WINAPI* pfnCreateAssemblyEnum)(
_Out_ IAssemblyEnum** pEnum,
_In_opt_ IUnknown* pUnkReserved,
_In_opt_ IAssemblyName* pName,
_In_ DWORD dwFlags,
_Reserved_ LPVOID pvReserved);
typedef HRESULT(WINAPI* pfnCreateAssemblyCache)(
_Out_ IAssemblyCache** ppAsmCache,
_In_ DWORD dwReserved);
HRESULT FusionGetAssemblyName(
_In_ IAssemblyName* pInterface,
_Out_ LPWSTR *lpAssemblyName
)
{
HRESULT hr = E_FAIL;
DWORD bufferSize = 0;
LPWSTR pwzName;
*lpAssemblyName = NULL;
pInterface->lpVtbl->GetName(pInterface, &bufferSize, 0);
if (bufferSize == 0)
return E_FAIL;
pwzName = (LPWSTR)supHeapAlloc(bufferSize * sizeof(WCHAR));
if (pwzName) {
hr = pInterface->lpVtbl->GetName(pInterface, &bufferSize, pwzName);
if (!SUCCEEDED(hr)) {
supHeapFree(pwzName);
}
else {
*lpAssemblyName = pwzName;
}
}
return hr;
}
HRESULT FusionGetAssemblyPath(
_In_ IAssemblyCache* pInterface,
_In_ LPWSTR lpAssemblyName,
_Out_ LPWSTR *lpAssemblyPath
)
{
HRESULT hr = E_FAIL;
ASSEMBLY_INFO asmInfo;
LPWSTR assemblyPath;
RtlSecureZeroMemory(&asmInfo, sizeof(asmInfo));
pInterface->lpVtbl->QueryAssemblyInfo(pInterface,
QUERYASMINFO_FLAG_GETSIZE,
lpAssemblyName,
&asmInfo);
if (asmInfo.cchBuf == 0) //empty pszCurrentAssemblyPathBuf
return E_FAIL;
assemblyPath = (LPWSTR)supHeapAlloc(asmInfo.cchBuf * sizeof(WCHAR));
if (assemblyPath == NULL)
return E_FAIL;
asmInfo.pszCurrentAssemblyPathBuf = assemblyPath;
hr = pInterface->lpVtbl->QueryAssemblyInfo(pInterface,
QUERYASMINFO_FLAG_VALIDATE,
lpAssemblyName,
&asmInfo);
if (!SUCCEEDED(hr)) {
supHeapFree(asmInfo.pszCurrentAssemblyPathBuf);
}
else {
*lpAssemblyPath = assemblyPath;
}
return hr;
}
VOID TestFusion()
{
WCHAR szBuffer[MAX_PATH];
HMODULE hFusion = NULL;
pfnCreateAssemblyEnum CreateAssemblyEnum;
pfnCreateAssemblyCache CreateAssemblyCache;
IAssemblyEnum* asmEnum = NULL;
IAssemblyCache* asmCache = NULL;
IAssemblyName* asmName = NULL;
LPWSTR lpAssemblyName = NULL, lpAssemblyPath = NULL;
HRESULT hr;
do {
_strcpy(szBuffer, g_ctx->szSystemRoot);
_strcat(szBuffer, TEXT("Microsoft.NET\\Framework64\\v4.0.30319\\"));
_strcat(szBuffer, TEXT("fusion.dll"));
hFusion = LoadLibraryEx(szBuffer, NULL, 0);
if (hFusion == NULL)
break;
CreateAssemblyEnum = (pfnCreateAssemblyEnum)GetProcAddress(hFusion, "CreateAssemblyEnum");
CreateAssemblyCache = (pfnCreateAssemblyCache)GetProcAddress(hFusion, "CreateAssemblyCache");
if (CreateAssemblyEnum == NULL || CreateAssemblyCache == NULL)
break;
hr = CreateAssemblyEnum(&asmEnum, NULL, NULL, ASM_CACHE_GAC, NULL);
if ((FAILED(hr)) || (asmEnum == NULL))
break;
hr = CreateAssemblyCache(&asmCache, 0);
if ((FAILED(hr)) || (asmCache == NULL))
break;
do {
hr = asmEnum->lpVtbl->GetNextAssembly(asmEnum, NULL, &asmName, 0);
if (!SUCCEEDED(hr) || asmName == NULL)
break;
if (SUCCEEDED(FusionGetAssemblyName(asmName, &lpAssemblyName))) {
OutputDebugString(TEXT(">>"));
OutputDebugString(lpAssemblyName);
OutputDebugString(TEXT("\r\n"));
}
asmName->lpVtbl->Finalize(asmName);
asmName->lpVtbl->Release(asmName);
asmName = NULL;
if (SUCCEEDED(FusionGetAssemblyPath(asmCache, lpAssemblyName, &lpAssemblyPath))) {
OutputDebugString(TEXT("====================="));
OutputDebugString(lpAssemblyPath);
OutputDebugString(TEXT("\r\n"));
}
if (lpAssemblyName) {
supHeapFree(lpAssemblyName);
lpAssemblyName = NULL;
}
if (lpAssemblyPath) {
supHeapFree(lpAssemblyPath);
lpAssemblyPath = NULL;
}
} while (TRUE);
asmCache->lpVtbl->Release(asmCache);
asmEnum->lpVtbl->Release(asmEnum);
} while(FALSE);
if (hFusion)
FreeLibrary(hFusion);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment