typedef unsigned int uint; struct IconStreamsHeader { uint cbSize; uint unknown1; uint Flags; uint IconEntries; uint unknown3; }; struct IconStreamsItem { WCHAR ExePath[MAX_PATH + 4]; uint Visibility; uint Unk1; WCHAR szTip[MAX_PATH]; uint Unk2; uint Unk3; uint Unk4; char Stuff[3*16]; WCHAR szOldTip[MAX_PATH]; uint Index; }; static_assert(sizeof(IconStreamsHeader) == 5*4); static_assert(sizeof(IconStreamsItem) == 1640); static void ROT13(WCHAR* data, size_t len) { for (size_t n = 0; n < len; ++n) { WCHAR c = data[n]; if (c >= 'a' && c <= 'm') data[n] = c + 13; else if (c >= 'n' && c <= 'z') data[n] = c - 13; else if (c >= 'A' && c <= 'M') data[n] = c + 13; else if (c >= 'N' && c <= 'Z') data[n] = c - 13; } } void HexDump(std::wostream& strm, const char* data, size_t len, size_t line) { for (size_t n = 0; n < len; ++n) { strm << std::hex << std::setw(2) << std::setfill(L'0') << (unsigned int)(unsigned char)data[n] << L" "; if (n > 0 && (((n+1) % line) == 0)) { strm << L" |"; for (size_t j = 0; j < line; ++j) { char c = data[n - line + 1 + j]; strm << (isprint((unsigned char)c) ? c : '.'); } strm << std::endl; } } strm << std::endl; } struct RegKey { HKEY hkey; const WCHAR* Subkey; }; RegKey rk[] = { { HKEY_CURRENT_USER, L"Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\TrayNotify" }, { HKEY_CLASSES_ROOT, L"Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\TrayNotify" }, }; #include #include void DumpKey(char* data) { IconStreamsHeader* header = reinterpret_cast(data); if (header->cbSize == sizeof(*header)) { std::wcout << L"Unk1: " << header->unknown1 << std::endl; std::wcout << L"Flags: " << header->Flags << std::endl; std::wcout << L"IconEntries: " << header->IconEntries << std::endl; std::wcout << L"Unk3: " << header->unknown3 << std::endl; IconStreamsItem* item = reinterpret_cast(header + 1); for (size_t n = 0; n < header->IconEntries; ++n) { ROT13(item[n].ExePath, _countof(item[n].ExePath)); ROT13(item[n].szTip, _countof(item[n].szTip)); ROT13(item[n].szOldTip, _countof(item[n].szOldTip)); bool hasNull = false; for (size_t j = 0; j < _countof(item[n].szTip); ++j) { bool isNull = item[n].szTip[j] == '\0'; if (!hasNull && isNull) hasNull = true; else if (hasNull && !isNull) __debugbreak(); } std::wcout << L"ExePath:" << item[n].ExePath << std::endl; std::wcout << L"Visibility: " << item[n].Visibility << std::endl; std::wcout << L"Unk1: " << std::hex << item[n].Unk1 << std::endl; std::wcout << L"szTip:" << item[n].szTip << std::endl; std::wcout << L"Unk2: " << std::hex << item[n].Unk2 << std::endl; std::wcout << L"Unk3: " << std::hex << item[n].Unk3 << std::endl; std::wcout << L"Unk4: " << std::hex << item[n].Unk4 << std::endl; HexDump(std::wcout, item[n].Stuff, sizeof(item[n].Stuff), 32); std::wcout << L"szOldTip:" << item[n].szOldTip << std::endl; std::wcout << "Index: " << std::dec << item[n].Index << std::endl << std::endl; } } } bool test() { _setmode(_fileno(stdout), _O_U16TEXT); DWORD dwType = 0, dwLen = sizeof(IconStreamsItem) * 100 + sizeof(IconStreamsHeader); CComHeapPtr tmp; tmp.AllocateBytes(dwLen); for (size_t n = 0; n < _countof(rk); ++n) { std::wcout << L"Dumping: " << rk[n].Subkey << std::endl; LSTATUS hr = SHGetValueW(rk[n].hkey, rk[n].Subkey, L"IconStreams", &dwType, tmp.m_pData, &dwLen); if (SUCCEEDED(hr) && dwType == REG_BINARY) { DumpKey(tmp.m_pData); } } _setmode(_fileno(stdout), _O_TEXT); return false; }