diff options
author | George Hazan <ghazan@miranda.im> | 2018-05-27 18:46:14 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2018-05-27 18:46:14 +0300 |
commit | f4d63038321dc6b1abe0f7fdb0e824ba66d3917f (patch) | |
tree | a17eaeffb00b6ee013b0a853d8f82e7872e621e7 | |
parent | 2828be06827872993527bb103bd1ffb546a7a935 (diff) |
dll sniffer that blocks load of any module whose build number is different than his own
-rw-r--r-- | src/mir_app/src/dll_sniffer.cpp | 183 |
1 files changed, 119 insertions, 64 deletions
diff --git a/src/mir_app/src/dll_sniffer.cpp b/src/mir_app/src/dll_sniffer.cpp index c4e64b31ed..0aaf974421 100644 --- a/src/mir_app/src/dll_sniffer.cpp +++ b/src/mir_app/src/dll_sniffer.cpp @@ -25,37 +25,60 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h"
#include "plugins.h"
-static IMAGE_SECTION_HEADER *getSectionByRVA(IMAGE_SECTION_HEADER *pISH, int nSections, IMAGE_DATA_DIRECTORY *pIDD)
+DWORD dwVersion = 0;
+
+static void ProcessResourcesDirectory(PIMAGE_RESOURCE_DIRECTORY pIRD, PBYTE pBase, DWORD dwType);
+
+static void ProcessResourceEntry(PIMAGE_RESOURCE_DIRECTORY_ENTRY pIRDE, PBYTE pBase, DWORD dwType)
+{
+ if (pIRDE->DataIsDirectory)
+ ProcessResourcesDirectory(PIMAGE_RESOURCE_DIRECTORY(pBase + pIRDE->OffsetToDirectory), pBase, dwType == 0 ? pIRDE->Name : dwType);
+ else if (dwType == 16) {
+ PIMAGE_RESOURCE_DATA_ENTRY pItem = PIMAGE_RESOURCE_DATA_ENTRY(pBase + pIRDE->OffsetToData);
+ dwVersion = pItem->OffsetToData;
+ }
+}
+
+static void ProcessResourcesDirectory(PIMAGE_RESOURCE_DIRECTORY pIRD, PBYTE pBase, DWORD dwType)
{
- for (int i=0; i < nSections; i++, pISH++)
- if (pIDD->VirtualAddress >= pISH->VirtualAddress && pIDD->VirtualAddress + pIDD->Size <= pISH->VirtualAddress + pISH->SizeOfRawData )
- return pISH;
+ UINT i;
+
+ PIMAGE_RESOURCE_DIRECTORY_ENTRY pIRDE = PIMAGE_RESOURCE_DIRECTORY_ENTRY(pIRD + 1);
+ for (i = 0; i < pIRD->NumberOfNamedEntries; i++, pIRDE++)
+ ProcessResourceEntry(pIRDE, pBase, dwType);
+
+ for (i = 0; i < pIRD->NumberOfIdEntries; i++, pIRDE++)
+ ProcessResourceEntry(pIRDE, pBase, dwType);
+}
- return nullptr;
+__forceinline bool Contains(PIMAGE_SECTION_HEADER pISH, DWORD address, DWORD size = 0)
+{
+ return (address >= pISH->VirtualAddress && address + size <= pISH->VirtualAddress + pISH->SizeOfRawData);
}
MUUID* GetPluginInterfaces(const wchar_t* ptszFileName, bool& bIsPlugin)
{
+ int nChecks = 0;
bIsPlugin = false;
- HANDLE hFile = CreateFile( ptszFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr );
+ HANDLE hFile = CreateFile(ptszFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
return nullptr;
MUUID* pResult = nullptr;
BYTE* ptr = nullptr;
- HANDLE hMap = CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr );
+ HANDLE hMap = CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
__try {
__try {
- if (!hMap )
+ if (!hMap)
__leave;
- DWORD dwHSize = 0, filesize = GetFileSize( hFile, &dwHSize );
+ DWORD dwHSize = 0, filesize = GetFileSize(hFile, &dwHSize);
if (!filesize || filesize == INVALID_FILE_SIZE || dwHSize)
__leave;
- if ( filesize < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) )
+ if (filesize < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS))
__leave;
ptr = (BYTE*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
@@ -64,91 +87,123 @@ MUUID* GetPluginInterfaces(const wchar_t* ptszFileName, bool& bIsPlugin) PIMAGE_NT_HEADERS pINTH = {};
PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)ptr;
- if ( pIDH->e_magic == IMAGE_DOS_SIGNATURE )
+ if (pIDH->e_magic == IMAGE_DOS_SIGNATURE)
pINTH = (PIMAGE_NT_HEADERS)(ptr + pIDH->e_lfanew);
else
__leave;
- if ((PBYTE)pINTH + sizeof(IMAGE_NT_HEADERS) >= ptr + filesize )
+ if ((PBYTE)pINTH + sizeof(IMAGE_NT_HEADERS) >= ptr + filesize)
__leave;
- if ( pINTH->Signature != IMAGE_NT_SIGNATURE )
+ if (pINTH->Signature != IMAGE_NT_SIGNATURE)
__leave;
- int nSections = pINTH->FileHeader.NumberOfSections;
- if (!nSections )
+ DWORD nSections = pINTH->FileHeader.NumberOfSections;
+ if (!nSections)
__leave;
+ // try to found correct offset independent of architectures
INT_PTR base;
PIMAGE_DATA_DIRECTORY pIDD;
- if ( pINTH->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 &&
- pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER32) &&
- pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
- {
- pIDD = (PIMAGE_DATA_DIRECTORY)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory ));
+ if (pINTH->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 &&
+ pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER32) &&
+ pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ pIDD = (PIMAGE_DATA_DIRECTORY)((PBYTE)pINTH + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory));
base = *(DWORD*)((PBYTE)pINTH + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.ImageBase));
}
- else if ( pINTH->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 &&
- pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER64) &&
- pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
- {
- pIDD = (PIMAGE_DATA_DIRECTORY)( (PBYTE)pINTH + offsetof( IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory ));
- base = *(ULONGLONG*)((PBYTE)pINTH + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.ImageBase ));
+ else if (pINTH->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 &&
+ pINTH->FileHeader.SizeOfOptionalHeader >= sizeof(IMAGE_OPTIONAL_HEADER64) &&
+ pINTH->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ pIDD = (PIMAGE_DATA_DIRECTORY)((PBYTE)pINTH + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory));
+ base = *(ULONGLONG*)((PBYTE)pINTH + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.ImageBase));
}
else __leave;
+ // Resource directory
+ DWORD resAddr = pIDD[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+ DWORD resSize = pIDD[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size;
+ if (resSize < sizeof(IMAGE_EXPORT_DIRECTORY)) __leave;
+
// Export information entry
- DWORD expvaddr = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- DWORD expsize = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- if (expsize < sizeof(IMAGE_EXPORT_DIRECTORY)) __leave;
+ DWORD expAddr = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ DWORD expSize = pIDD[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
+ if (expSize < sizeof(IMAGE_EXPORT_DIRECTORY)) __leave;
BYTE* pImage = ptr + pIDH->e_lfanew + pINTH->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_NT_HEADERS) - sizeof(IMAGE_OPTIONAL_HEADER);
- IMAGE_SECTION_HEADER *pExp = getSectionByRVA((IMAGE_SECTION_HEADER *)pImage, nSections, pIDD);
- if (!pExp) __leave;
-
- BYTE *pSecStart = ptr + pExp->PointerToRawData - pExp->VirtualAddress;
- IMAGE_EXPORT_DIRECTORY *pED = (PIMAGE_EXPORT_DIRECTORY)&pSecStart[expvaddr];
- DWORD *ptrRVA = (DWORD*)&pSecStart[pED->AddressOfNames];
- WORD *ptrOrdRVA = (WORD*)&pSecStart[pED->AddressOfNameOrdinals];
- DWORD *ptrFuncList = (DWORD*)&pSecStart[pED->AddressOfFunctions];
-
- MUUID* pIds = nullptr;
- bool bHasLoad = false, bHasUnload = false, bHasMuuids = false;
- for (size_t i=0; i < pED->NumberOfNames; i++, ptrRVA++, ptrOrdRVA++) {
- char *szName = (char*)&pSecStart[*ptrRVA];
- if (!mir_strcmp(szName, "Load"))
- bHasLoad = true;
- else if (!mir_strcmp(szName, "Unload"))
- bHasUnload = true;
- else if (!mir_strcmp(szName, "MirandaInterfaces")) {
- bHasMuuids = true;
- pIds = (MUUID*)&pSecStart[ptrFuncList[*ptrOrdRVA]];
+
+ for (DWORD idx = 0; idx < nSections; idx++) {
+ PIMAGE_SECTION_HEADER pISH = (PIMAGE_SECTION_HEADER)(pImage + idx * sizeof(IMAGE_SECTION_HEADER));
+ if (((PBYTE)pISH + sizeof(IMAGE_SECTION_HEADER) > pImage + filesize) || (pISH->PointerToRawData + pISH->SizeOfRawData > filesize))
+ __leave;
+
+ // process export table
+ if (expSize >= sizeof(IMAGE_EXPORT_DIRECTORY) && Contains(pISH, expAddr, expSize)) {
+ BYTE *pSecStart = ptr + pISH->PointerToRawData - pISH->VirtualAddress;
+ IMAGE_EXPORT_DIRECTORY *pED = (PIMAGE_EXPORT_DIRECTORY)&pSecStart[expAddr];
+ DWORD *ptrRVA = (DWORD*)&pSecStart[pED->AddressOfNames];
+ WORD *ptrOrdRVA = (WORD*)&pSecStart[pED->AddressOfNameOrdinals];
+ DWORD *ptrFuncList = (DWORD*)&pSecStart[pED->AddressOfFunctions];
+
+ MUUID* pIds = nullptr;
+ bool bHasLoad = false, bHasUnload = false, bHasMuuids = false;
+ for (size_t i = 0; i < pED->NumberOfNames; i++, ptrRVA++, ptrOrdRVA++) {
+ char *szName = (char*)&pSecStart[*ptrRVA];
+ if (!mir_strcmp(szName, "Load"))
+ bHasLoad = true;
+ else if (!mir_strcmp(szName, "Unload"))
+ bHasUnload = true;
+ else if (!mir_strcmp(szName, "MirandaInterfaces")) {
+ bHasMuuids = true;
+ pIds = (MUUID*)&pSecStart[ptrFuncList[*ptrOrdRVA]];
+ }
+ }
+
+ if (!bHasLoad || !bHasUnload)
+ __leave;
+
+ nChecks++;
+
+ // a plugin might have no interfaces
+ if (bHasMuuids) {
+ int nLength = 1; // one for MIID_LAST
+ for (MUUID* p = pIds; *p != miid_last; p++)
+ nLength++;
+
+ pResult = (MUUID*)mir_alloc(sizeof(MUUID)*nLength);
+ if (pResult)
+ memcpy(pResult, pIds, sizeof(MUUID)*nLength);
+ }
}
- }
- // a plugin might have no interfaces
- if (bHasLoad && bHasUnload)
- bIsPlugin = true;
+ // process resource version
+ if (resSize > 0 && Contains(pISH, resAddr, resSize)) {
+ dwVersion = 0;
- if (!bHasLoad || !bHasMuuids || !bHasUnload)
- __leave;
+ BYTE *pSecStart = ptr + pISH->PointerToRawData - pISH->VirtualAddress;
+ IMAGE_RESOURCE_DIRECTORY *pIRD = (IMAGE_RESOURCE_DIRECTORY*)&pSecStart[resAddr];
+ ProcessResourcesDirectory(pIRD, &pSecStart[resAddr], 0);
- int nLength = 1; // one for MIID_LAST
- for (MUUID* p = pIds; *p != miid_last; p++)
- nLength++;
+ // patch version
+ if (dwVersion) {
+ UINT blockSize;
+ VS_FIXEDFILEINFO *vsffi;
+ VerQueryValue(&pSecStart[dwVersion], L"\\", (PVOID*)&vsffi, &blockSize);
- pResult = (MUUID*)mir_alloc(sizeof(MUUID)*nLength);
- if (pResult)
- memcpy(pResult, pIds, sizeof(MUUID)*nLength);
+ UINT v[4] = { MIRANDA_VERSION_FILEVERSION };
+ if (MAKELONG(v[1], v[0]) == vsffi->dwProductVersionMS && MAKELONG(v[3], v[2]) == vsffi->dwProductVersionLS)
+ nChecks++;
+ }
+ }
+ }
}
- __except(EXCEPTION_EXECUTE_HANDLER)
+ __except (EXCEPTION_EXECUTE_HANDLER)
{};
}
- __finally
- {
+ __finally {
if (ptr) UnmapViewOfFile(ptr);
if (hMap) CloseHandle(hMap);
CloseHandle(hFile);
};
+ bIsPlugin = nChecks == 2;
return pResult;
}
|