void TlsCallback_1(_IMAGE_DOS_HEADER* dllHandle, DWORD reason, DWORD reserved) { if (reason != DLL_PROCESS_ATTACH) return; HMODULE mainModule = GetModuleHandle(nullptr); _IMAGE_DOS_HEADER* dosHeader = reinterpret_cast<_IMAGE_DOS_HEADER*>(mainModule); assert(dosHeader->e_magic == 'ZM' && "Invalid DOS signature for main module (through module handle)."); _IMAGE_NT_HEADERS* ntHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<char*>(dosHeader) + dosHeader->e_lfanew); assert(ntHeader->Signature == 'EP' && "Invalid PE signature for main module (through module handle)."); // Stack page allocation here, just don't do it, we don't need to. DWORD64 timestampCounter = ReadTimeStampCounter(); BYTE* timeArray = new BYTE[4100]; // Technically a static value in the client for (uint32_t i = 0; i < 4100; ++i) { timeArray[i] ^= timestampCounter; BYTE nextValue = timeArray[i + 1]; timestampCounter = nextValue + ReadTimeStampCounter() + (timestampCounter >> 3); } // This isn't actual code in the client, but that should be true. assert(dllHandle == dosHeader && "First argument of a TLS callback should point to the program's PE header!"); assert(dllHandle->e_magic == 'ZM' && "Invalid DOS signature for main module."); _IMAGE_NT_HEADERS* dllNtHeaders = reinterpret_cast<_IMAGE_NT_HEADERS*>(reinterpret_cast<char*>(dllHandle) + dllHandle->e_lfanew); assert(dllNtHeaders->Signature == 'EP' && "Invalid PE signature for main module"); /// This executable doesn't have a TLS directory (yet) // IMAGE_DATA_DIRECTORY* tlsDataDirectory = &dllNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]; // if (tlsDataDirectory->VirtualAddress == 0 && tlsDataDirectory->Size == 0) // assert(false && "TLS Data Directory not found!"); // // _IMAGE_TLS_DIRECTORY32* tlsDirectory = *reinterpret_cast<IMAGE_TLS_DIRECTORY32**>(reinterpret_cast<char*>(&dllHandle->e_maxalloc) + tlsDataDirectory->VirtualAddress); // assert(tlsDirectory != nullptr && "TLS Directory not found"); _PEB* ntCurrentPeb = NtCurrentTeb()->ProcessEnvironmentBlock; assert(ntCurrentPeb != nullptr && "PEB not found"); _LDR_DATA_TABLE_ENTRY* k32Module = nullptr; _LIST_ENTRY* head = &ntCurrentPeb->Ldr->InMemoryOrderModuleList; for (LIST_ENTRY* item = head->Flink; item != head; item = item->Flink) { k32Module = CONTAINING_RECORD(item, _LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); uint32_t nameHash = HashName(reinterpret_cast<UNICODE_STRING*>(&k32Module->Reserved4)); if (nameHash == 0xF42198D) break; else k32Module = nullptr; } assert(k32Module != nullptr && "Unable to find KERNEL32.dll in the PEB structure!"); _IMAGE_DOS_HEADER* k32DosHeader = reinterpret_cast<_IMAGE_DOS_HEADER*>(k32Module->DllBase); assert(k32DosHeader->e_magic == 'ZM' && "Incorrect DOS signature for KERNEL32.dll!"); _IMAGE_NT_HEADERS* k32NtHeader = reinterpret_cast<_IMAGE_NT_HEADERS*>(reinterpret_cast<char*>(k32DosHeader) + k32DosHeader->e_lfanew); assert(k32NtHeader->Signature == 'EP' && "Incorrect NT signature for KERNEL32.dll!"); _IMAGE_DATA_DIRECTORY* k32ExportDataDir = &k32NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (k32ExportDataDir->VirtualAddress != 0 && k32ExportDataDir->Size != 0) { IMAGE_EXPORT_DIRECTORY* k32Exports = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(reinterpret_cast<char*>(k32DosHeader->e_res) + k32ExportDataDir->VirtualAddress); assert(k32Exports->AddressOfNames != 0 && "KERNEL32.dll's export directory does not contain a valid pointer for AddressOfNames!"); assert(k32Exports->AddressOfNameOrdinals != 0 && "KERNEL32.dll's export directory does not contain a valid pointer for AddressOfNameOrdinals!"); assert(k32Exports->NumberOfNames != 0 && "KERNEL32.dll's export directory does not contain any names!"); WORD* ordinalTable = reinterpret_cast<WORD*>(reinterpret_cast<char*>(k32DosHeader) + k32Exports->AddressOfNameOrdinals); DWORD* nameTable = reinterpret_cast<DWORD*>(reinterpret_cast<char*>(k32DosHeader) + k32Exports->AddressOfNames); DWORD* functionTable = reinterpret_cast<DWORD*>(reinterpret_cast<char*>(k32DosHeader) + k32Exports->AddressOfFunctions); for (uint32_t i = 0; i < k32Exports->NumberOfNames; ++i) { char* functionName = reinterpret_cast<char*>(k32DosHeader) + nameTable[i]; } } }
100 years ago the Bolshevik revolution launched a Communist totalitarianism that murdered tens of millions & enslaved hundreds of millions.
— Garry Kasparov (@Kasparov63) November 7, 2017