


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