void OutputPair(const NameValuePairs &v, const char *name) { Integer x; bool b = v.GetValue(name, x); assert(b); cout << name << ": \\\n "; x.Encode(HexEncoder(new FileSink(cout), false, 64, "\\\n ").Ref(), x.MinEncodedSize()); cout << endl; }
bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac, unsigned long *pMacFileLocation) { std::auto_ptr<MessageAuthenticationCode> mac(NewIntegrityCheckingMAC()); unsigned int macSize = mac->DigestSize(); SecByteBlock tempMac; SecByteBlock &actualMac = pActualMac ? *pActualMac : tempMac; actualMac.resize(macSize); unsigned long tempLocation; unsigned long &macFileLocation = pMacFileLocation ? *pMacFileLocation : tempLocation; macFileLocation = 0; HashFilter verifier(*mac, new ArraySink(actualMac, actualMac.size())); // FileSink verifier("c:\\dt.tmp"); FileStore file(moduleFilename); #ifdef CRYPTOPP_WIN32_AVAILABLE // try to hash from memory first HMODULE h = GetModuleHandle(moduleFilename); const byte *memBase = (const byte *)h; IMAGE_DOS_HEADER *ph = (IMAGE_DOS_HEADER *)h; IMAGE_NT_HEADERS *phnt = (IMAGE_NT_HEADERS *)((byte *)h + ph->e_lfanew); IMAGE_SECTION_HEADER *phs = IMAGE_FIRST_SECTION(phnt); DWORD nSections = phnt->FileHeader.NumberOfSections; DWORD currentFilePos = 0; while (nSections--) { switch (phs->Characteristics) { default: break; case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: unsigned int sectionSize = STDMIN(phs->SizeOfRawData, phs->Misc.VirtualSize); const byte *sectionMemStart = memBase + phs->VirtualAddress; unsigned int sectionFileStart = phs->PointerToRawData; unsigned int subSectionStart = 0, nextSubSectionStart; do { const byte *subSectionMemStart = sectionMemStart + subSectionStart; unsigned int subSectionFileStart = sectionFileStart + subSectionStart; unsigned int subSectionSize = sectionSize - subSectionStart; nextSubSectionStart = 0; unsigned int entriesToReadFromDisk[] = {IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IAT}; for (unsigned int i=0; i<sizeof(entriesToReadFromDisk)/sizeof(entriesToReadFromDisk[0]); i++) { const IMAGE_DATA_DIRECTORY &entry = phnt->OptionalHeader.DataDirectory[entriesToReadFromDisk[i]]; const byte *entryMemStart = memBase + entry.VirtualAddress; if (subSectionMemStart <= entryMemStart && entryMemStart < subSectionMemStart + subSectionSize) { subSectionSize = entryMemStart - subSectionMemStart; nextSubSectionStart = entryMemStart - sectionMemStart + entry.Size; } } file.TransferTo(verifier, subSectionFileStart - currentFilePos); if (subSectionMemStart <= expectedModuleMac && expectedModuleMac < subSectionMemStart + subSectionSize) { // skip over the MAC verifier.Put(subSectionMemStart, expectedModuleMac - subSectionMemStart); verifier.Put(expectedModuleMac + macSize, subSectionSize - macSize - (expectedModuleMac - subSectionMemStart)); macFileLocation = subSectionFileStart + (expectedModuleMac - subSectionMemStart); } else verifier.Put(subSectionMemStart, subSectionSize); file.Skip(subSectionSize); currentFilePos = subSectionFileStart + subSectionSize; subSectionStart = nextSubSectionStart; } while (nextSubSectionStart != 0); } phs++; } #endif file.TransferAllTo(verifier); #ifdef CRYPTOPP_WIN32_AVAILABLE // if that fails (could be caused by debug breakpoints or DLL base relocation modifying image in memory), // hash from disk instead if (memcmp(expectedModuleMac, actualMac, macSize) != 0) { OutputDebugString("In memory integrity check failed. This may be caused by debug breakpoints or DLL relocation.\n"); file.Initialize(MakeParameters("InputFileName", moduleFilename)); verifier.Detach(new ArraySink(actualMac, actualMac.size())); if (macFileLocation) { file.TransferTo(verifier, macFileLocation); file.Skip(macSize); } file.TransferAllTo(verifier); } #endif if (memcmp(expectedModuleMac, actualMac, macSize) == 0) return true; #ifdef CRYPTOPP_WIN32_AVAILABLE std::string hexMac; HexEncoder(new StringSink(hexMac)).PutMessageEnd(actualMac, actualMac.size()); OutputDebugString((moduleFilename + (" integrity check failed. Actual MAC is: " + hexMac) + "\n").c_str()); #endif return false; }
bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac, unsigned long *pMacFileLocation) { std::auto_ptr<MessageAuthenticationCode> mac(NewIntegrityCheckingMAC()); unsigned int macSize = mac->DigestSize(); SecByteBlock tempMac; SecByteBlock &actualMac = pActualMac ? *pActualMac : tempMac; actualMac.resize(macSize); unsigned long tempLocation; unsigned long &macFileLocation = pMacFileLocation ? *pMacFileLocation : tempLocation; macFileLocation = 0; MeterFilter verifier(new HashFilter(*mac, new ArraySink(actualMac, actualMac.size()))); // MeterFilter verifier(new FileSink("c:\\dt.tmp")); std::ifstream moduleStream; #ifdef CRYPTOPP_WIN32_AVAILABLE HMODULE h; { char moduleFilenameBuf[MAX_PATH] = ""; if (moduleFilename == NULL) { #if (defined(_MSC_VER) && _MSC_VER >= 1400) // ifstream doesn't support wide filename on other compilers wchar_t wideModuleFilename[MAX_PATH]; if (GetModuleFileNameW(s_hModule, wideModuleFilename, MAX_PATH) > 0) { moduleStream.open(wideModuleFilename, std::ios::in | std::ios::binary); h = GetModuleHandleW(wideModuleFilename); } else #endif { GetModuleFileNameA(s_hModule, moduleFilenameBuf, MAX_PATH); moduleFilename = moduleFilenameBuf; } } #endif if (moduleFilename != NULL) { moduleStream.open(moduleFilename, std::ios::in | std::ios::binary); #ifdef CRYPTOPP_WIN32_AVAILABLE h = GetModuleHandleA(moduleFilename); moduleFilename = NULL; } #endif } if (!moduleStream) { #ifdef CRYPTOPP_WIN32_AVAILABLE OutputDebugString("Crypto++ DLL integrity check failed. Cannot open file for reading."); #endif return false; } FileStore file(moduleStream); #ifdef CRYPTOPP_WIN32_AVAILABLE // try to hash from memory first const byte *memBase = (const byte *)h; const IMAGE_DOS_HEADER *ph = (IMAGE_DOS_HEADER *)memBase; const IMAGE_NT_HEADERS *phnt = (IMAGE_NT_HEADERS *)(memBase + ph->e_lfanew); const IMAGE_SECTION_HEADER *phs = IMAGE_FIRST_SECTION(phnt); DWORD nSections = phnt->FileHeader.NumberOfSections; size_t currentFilePos = 0; size_t checksumPos = (byte *)&phnt->OptionalHeader.CheckSum - memBase; size_t checksumSize = sizeof(phnt->OptionalHeader.CheckSum); size_t certificateTableDirectoryPos = (byte *)&phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY] - memBase; size_t certificateTableDirectorySize = sizeof(phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY]); size_t certificateTablePos = phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; size_t certificateTableSize = phnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; verifier.AddRangeToSkip(0, checksumPos, checksumSize); verifier.AddRangeToSkip(0, certificateTableDirectoryPos, certificateTableDirectorySize); verifier.AddRangeToSkip(0, certificateTablePos, certificateTableSize); while (nSections--) { switch (phs->Characteristics) { default: break; case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: unsigned int sectionSize = STDMIN(phs->SizeOfRawData, phs->Misc.VirtualSize); const byte *sectionMemStart = memBase + phs->VirtualAddress; unsigned int sectionFileStart = phs->PointerToRawData; size_t subSectionStart = 0, nextSubSectionStart; do { const byte *subSectionMemStart = sectionMemStart + subSectionStart; size_t subSectionFileStart = sectionFileStart + subSectionStart; size_t subSectionSize = sectionSize - subSectionStart; nextSubSectionStart = 0; unsigned int entriesToReadFromDisk[] = {IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IAT}; for (unsigned int i=0; i<sizeof(entriesToReadFromDisk)/sizeof(entriesToReadFromDisk[0]); i++) { const IMAGE_DATA_DIRECTORY &entry = phnt->OptionalHeader.DataDirectory[entriesToReadFromDisk[i]]; const byte *entryMemStart = memBase + entry.VirtualAddress; if (subSectionMemStart <= entryMemStart && entryMemStart < subSectionMemStart + subSectionSize) { subSectionSize = entryMemStart - subSectionMemStart; nextSubSectionStart = entryMemStart - sectionMemStart + entry.Size; } } #if defined(_MSC_VER) && _MSC_VER >= 1400 // first byte of _CRT_DEBUGGER_HOOK gets modified in memory by the debugger invisibly, so read it from file if (IsDebuggerPresent()) { if (subSectionMemStart <= (byte *)&_CRT_DEBUGGER_HOOK && (byte *)&_CRT_DEBUGGER_HOOK < subSectionMemStart + subSectionSize) { subSectionSize = (byte *)&_CRT_DEBUGGER_HOOK - subSectionMemStart; nextSubSectionStart = (byte *)&_CRT_DEBUGGER_HOOK - sectionMemStart + 1; } } #endif if (subSectionMemStart <= expectedModuleMac && expectedModuleMac < subSectionMemStart + subSectionSize) { // found stored MAC macFileLocation = (unsigned long)(subSectionFileStart + (expectedModuleMac - subSectionMemStart)); verifier.AddRangeToSkip(0, macFileLocation, macSize); } file.TransferTo(verifier, subSectionFileStart - currentFilePos); verifier.Put(subSectionMemStart, subSectionSize); file.Skip(subSectionSize); currentFilePos = subSectionFileStart + subSectionSize; subSectionStart = nextSubSectionStart; } while (nextSubSectionStart != 0); } phs++; } #endif file.TransferAllTo(verifier); #ifdef CRYPTOPP_WIN32_AVAILABLE // if that fails (could be caused by debug breakpoints or DLL base relocation modifying image in memory), // hash from disk instead if (memcmp(expectedModuleMac, actualMac, macSize) != 0) { OutputDebugString("In memory integrity check failed. This may be caused by debug breakpoints or DLL relocation.\n"); moduleStream.clear(); moduleStream.seekg(0); verifier.Initialize(MakeParameters(Name::OutputBuffer(), ByteArrayParameter(actualMac, (unsigned int)actualMac.size()))); // verifier.Initialize(MakeParameters(Name::OutputFileName(), (const char *)"c:\\dt2.tmp")); verifier.AddRangeToSkip(0, checksumPos, checksumSize); verifier.AddRangeToSkip(0, certificateTableDirectoryPos, certificateTableDirectorySize); verifier.AddRangeToSkip(0, certificateTablePos, certificateTableSize); verifier.AddRangeToSkip(0, macFileLocation, macSize); FileStore(moduleStream).TransferAllTo(verifier); } #endif if (memcmp(expectedModuleMac, actualMac, macSize) == 0) return true; #ifdef CRYPTOPP_WIN32_AVAILABLE std::string hexMac; HexEncoder(new StringSink(hexMac)).PutMessageEnd(actualMac, actualMac.size()); OutputDebugString((("Crypto++ DLL integrity check failed. Actual MAC is: " + hexMac) + "\n").c_str()); #endif return false; }
bool ValidateBaseCode() { bool pass = true, fail; byte data[255]; for (unsigned int i=0; i<255; i++) data[i] = i; const char *hexEncoded = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627" "28292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F" "505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F7071727374757677" "78797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" "A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7" "C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFE"; const char *base32Encoded = "AAASEA2EAWDAQCAJBIFS2DIQB6IBCESVCSKTNF22DEPBYHA7D2RUAIJCENUCKJTHFAWUWK3NFWZC8NBT" "GI3VIPJYG66DUQT5HS8V6R4AIFBEGTCFI3DWSUKKJPGE4VURKBIXEW4WKXMFQYC3MJPX2ZK8M7SGC2VD" "NTUYN35IPFXGY5DPP3ZZA6MUQP4HK7VZRB6ZW856RX9H9AEBSKB2JBNGS8EIVCWMTUG27D6SUGJJHFEX" "U4M3TGN4VQQJ5HW9WCS4FI7EWYVKRKFJXKX43MPQX82MDNXVYU45PP72ZG7MZRF7Z496BSQC2RCNMTYH" "3DE6XU8N3ZHN9WGT4MJ7JXQY49NPVYY55VQ77Z9A6HTQH3HF65V8T4RK7RYQ55ZR8D29F69W8Z5RR8H3" "9M7939R8"; const char *base64AndHexEncoded = "41414543417751464267634943516F4C4441304F4478415245684D554652595847426B6147787764" "486838674953496A4A43556D4A7967704B6973734C5334764D4445794D7A51310A4E6A63344F546F" "375044302B50304242516B4E4552555A4853456C4B5330784E546B395155564A5456465657563168" "5A576C746358563566594746695932526C5A6D646F615770720A6247317562334278636E4E306458" "5A3365486C3665337839666E2B4167594B44684957476834694A696F754D6A5936506B4A47536B35" "53566C7065596D5A71626E4A32656E3643680A6F714F6B7061616E714B6D717136797472712B7773" "624B7A744C573274376935757275387662362F774D484377385446787366497963724C7A4D334F7A" "39445230745055316462580A324E6E6132397A6433742F6734654C6A354F586D352B6A7036757673" "3765377638504879382F5431397666342B6672372F50332B0A"; cout << "\nBase64, base32 and hex coding validation suite running...\n\n"; fail = !TestFilter(HexEncoder().Ref(), data, 255, (const byte *)hexEncoded, strlen(hexEncoded)); cout << (fail ? "FAILED " : "passed "); cout << "Hex Encoding\n"; pass = pass && !fail; fail = !TestFilter(HexDecoder().Ref(), (const byte *)hexEncoded, strlen(hexEncoded), data, 255); cout << (fail ? "FAILED " : "passed "); cout << "Hex Decoding\n"; pass = pass && !fail; fail = !TestFilter(Base32Encoder().Ref(), data, 255, (const byte *)base32Encoded, strlen(base32Encoded)); cout << (fail ? "FAILED " : "passed "); cout << "Base32 Encoding\n"; pass = pass && !fail; fail = !TestFilter(Base32Decoder().Ref(), (const byte *)base32Encoded, strlen(base32Encoded), data, 255); cout << (fail ? "FAILED " : "passed "); cout << "Base32 Decoding\n"; pass = pass && !fail; fail = !TestFilter(Base64Encoder(new HexEncoder).Ref(), data, 255, (const byte *)base64AndHexEncoded, strlen(base64AndHexEncoded)); cout << (fail ? "FAILED " : "passed "); cout << "Base64 Encoding\n"; pass = pass && !fail; fail = !TestFilter(HexDecoder(new Base64Decoder).Ref(), (const byte *)base64AndHexEncoded, strlen(base64AndHexEncoded), data, 255); cout << (fail ? "FAILED " : "passed "); cout << "Base64 Decoding\n"; pass = pass && !fail; return pass; }