414 lines
12 KiB
C
414 lines
12 KiB
C
#include "progwrp.h"
|
|
|
|
NTSYSAPI PVOID RtlAllocateHeap(
|
|
PVOID HeapHandle,
|
|
ULONG Flags,
|
|
SIZE_T Size
|
|
);
|
|
|
|
NTSYSAPI VOID RtlFreeHeap(
|
|
PVOID HeapHandle,
|
|
ULONG Flags,
|
|
PVOID BaseAddress
|
|
);
|
|
|
|
#define RtlMoveMemory RtlMoveMemory
|
|
|
|
VOID NTAPI RtlMoveMemory(
|
|
PVOID Destination,
|
|
PVOID Source,
|
|
SIZE_T Length
|
|
);
|
|
|
|
typedef struct {
|
|
ULONG Ptr0;
|
|
ULONG Ptr1;
|
|
ULONG Ptr2;
|
|
}TlsHack;
|
|
|
|
typedef struct _THREAD_BASIC_INFORMATION {
|
|
NTSTATUS ExitStatus;
|
|
PVOID TebBaseAddress;
|
|
CLIENT_ID ClientId;
|
|
KAFFINITY AffinityMask;
|
|
KPRIORITY Priority;
|
|
KPRIORITY BasePriority;
|
|
} THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
|
|
|
|
|
|
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
|
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
|
|
|
|
__declspec(dllexport) VOID WINAPI TLSInit_DllMain_ThreadAttach(ULONG_PTR DllBase);
|
|
|
|
/*
|
|
Since I will not rewrite the entirety of the fairly complex LdrLoadDll and friends (although if you look at NT 4,
|
|
it is relatively simple), I will implement implicit TLS initialization code in DllMain.
|
|
|
|
There are two separate functions, which do two separate things:
|
|
-Process attach function: performs calls to TLS callback functions and increments the TLS index for the DLL based on the
|
|
count of pointers stashed in Teb->ThreadLocalStoragePointer.
|
|
|
|
|
|
*/
|
|
|
|
VOID AddToTlsList(ULONG_PTR DllBase)
|
|
/*
|
|
The previous TLS allocation system broke down after further enhancements were made to Supermium. Evidently it was no longer doing
|
|
the job.
|
|
|
|
Now, a list of all modules is maintained; when progwrp is first initialized, the TEB is f
|
|
*/
|
|
{
|
|
EnterCriticalSection(&SrwSharedCs2);
|
|
|
|
LeaveCriticalSection(&SrwSharedCs2);
|
|
}
|
|
|
|
PIMAGE_TLS_DIRECTORY __stdcall GetTlsDirectory(ULONG_PTR DllBase, PULONG_PTR ImageBase)
|
|
{
|
|
PIMAGE_DOS_HEADER DosHeader;
|
|
DWORD OptionalHeaderOffset;
|
|
IMAGE_NT_HEADERS* ImageOptionalHeader;
|
|
ULONG_PTR Base;
|
|
|
|
DosHeader = (PIMAGE_DOS_HEADER)DllBase;
|
|
|
|
if (!RtlPcToFileHeader(DllBase, &Base))
|
|
return NULL;
|
|
|
|
OptionalHeaderOffset = DosHeader->e_lfanew;
|
|
|
|
ImageOptionalHeader = (IMAGE_NT_HEADERS*)(OptionalHeaderOffset + DllBase);
|
|
|
|
*ImageBase = ImageOptionalHeader->OptionalHeader.ImageBase;
|
|
|
|
if (!ImageOptionalHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress)
|
|
return NULL;
|
|
|
|
return (PIMAGE_TLS_DIRECTORY)(ImageOptionalHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress + DllBase);
|
|
}
|
|
|
|
__declspec(dllexport) VOID WINAPI TLSInit_DllMain_ProcessAttach(ULONG_PTR DllBase)
|
|
{
|
|
return;
|
|
PIMAGE_TLS_DIRECTORY TlsDirectory;
|
|
PIMAGE_TLS_CALLBACK* TlsCallbacks;
|
|
PIMAGE_TLS_CALLBACK TlsCall;
|
|
PTEB_CUSTOM CustomTeb;
|
|
PULONG TlsIdx;
|
|
ULONG_PTR* ThreadLocalStoragePointer, ImageBase;
|
|
|
|
if (!DllBase)
|
|
return;
|
|
|
|
CustomTeb = (PTEB_CUSTOM)NtCurrentTeb();
|
|
|
|
if (LOBYTE(GetVersion()) >= 6 || (LOBYTE(GetVersion()) < 6 && CustomTeb->ProcessEnvironmentBlock->SystemReserved == 1))
|
|
return; // Nothing to do here
|
|
|
|
TlsDirectory = GetTlsDirectory(DllBase, &ImageBase);
|
|
|
|
if (!TlsDirectory)
|
|
return;
|
|
|
|
TlsCallbacks = (PIMAGE_TLS_CALLBACK*)((TlsDirectory->AddressOfCallBacks)); // - ImageBase) + DllBase);
|
|
|
|
TlsIdx = (PULONG)((TlsDirectory->AddressOfIndex));// - ImageBase)); + DllBase);
|
|
|
|
if (*TlsIdx)
|
|
return;
|
|
|
|
ThreadLocalStoragePointer = CustomTeb->ThreadLocalStoragePointer;
|
|
|
|
if (ThreadLocalStoragePointer)
|
|
{
|
|
while (*ThreadLocalStoragePointer > 0 && !(*ThreadLocalStoragePointer % 4))
|
|
// Make sure only valid pointers are counted, and not padding that can also bookend the list of pointers
|
|
{
|
|
++*TlsIdx;
|
|
++ThreadLocalStoragePointer;
|
|
}
|
|
|
|
}
|
|
|
|
if (TlsCallbacks)
|
|
{
|
|
while (*TlsCallbacks)
|
|
{
|
|
TlsCall = *TlsCallbacks;
|
|
TlsCall((PVOID)DllBase, 1, NULL);
|
|
++TlsCallbacks;
|
|
}
|
|
}
|
|
|
|
TLSInit_DllMain_ThreadAttach(DllBase);
|
|
}
|
|
|
|
VOID WINAPI TLSInit_DllMain_ProcessAttach_Internal(ULONG_PTR DllBase)
|
|
/*
|
|
This function is relatively simple:
|
|
-get the VA of the TLS directory, add the loaded image base to it
|
|
-use the size of the current ThreadLocalStoragePointer to set the TLS index in the DLL
|
|
-call the TLS callbacks
|
|
*/
|
|
{
|
|
PLDR_DATA_TABLE_ENTRY DataTableEntry, DataTableEntryInit;
|
|
PIMAGE_TLS_DIRECTORY TlsDirectory;
|
|
PIMAGE_TLS_CALLBACK* TlsCallbacks;
|
|
PIMAGE_TLS_CALLBACK TlsCall;
|
|
PTEB_CUSTOM CustomTeb;
|
|
PULONG TlsIdx;
|
|
ULONG_PTR* ThreadLocalStoragePointer, ImageBase;
|
|
ULONG ulLength;
|
|
LONG i;
|
|
PSYSTEM_PROCESS_INFORMATION spi;
|
|
PULONG_PTR TlsBaseCountTemp, TlsBasesOld;
|
|
|
|
if (!DllBase)
|
|
return;
|
|
|
|
if (DllBase == GetModuleHandleW(NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->ImagePathName.Buffer))
|
|
return;
|
|
|
|
CustomTeb = (PTEB_CUSTOM)NtCurrentTeb();
|
|
|
|
if ((LOBYTE(GetVersion()) >= 6))
|
|
return; // Nothing to do here
|
|
|
|
TlsDirectory = GetTlsDirectory(DllBase, &ImageBase);
|
|
|
|
if (!TlsDirectory)
|
|
return;
|
|
|
|
TlsCallbacks = (PIMAGE_TLS_CALLBACK*)((TlsDirectory->AddressOfCallBacks)); // - ImageBase) + DllBase);
|
|
|
|
TlsIdx = (PULONG)((TlsDirectory->AddressOfIndex));// - ImageBase)); + DllBase);
|
|
|
|
if (*TlsIdx)
|
|
return;
|
|
|
|
ThreadLocalStoragePointer = CustomTeb->ThreadLocalStoragePointer;
|
|
|
|
if (ThreadLocalStoragePointer)
|
|
{
|
|
while (*ThreadLocalStoragePointer > 0 && !(*ThreadLocalStoragePointer % 4))
|
|
// Make sure only valid pointers are counted, and not padding that can also bookend the list of pointers
|
|
{
|
|
++*TlsIdx;
|
|
++ThreadLocalStoragePointer;
|
|
}
|
|
|
|
}
|
|
|
|
if (TlsCallbacks)
|
|
{
|
|
while (*TlsCallbacks)
|
|
{
|
|
TlsCall = *TlsCallbacks;
|
|
TlsCall((PVOID)DllBase, 1, NULL);
|
|
++TlsCallbacks;
|
|
}
|
|
}
|
|
|
|
if (!TlsBasesLength || TlsBasesCount >= (TlsBasesLength - 1))
|
|
{
|
|
TlsBaseCountTemp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ULONG_PTR) * (32 + TlsBasesLength));
|
|
TlsBasesOld = TlsBases;
|
|
for (i = 0; i < TlsBasesCount; i++)
|
|
TlsBaseCountTemp[i] = TlsBases[i];
|
|
TlsBases = TlsBaseCountTemp;
|
|
TlsBasesLength += 32;
|
|
if(TlsBasesOld)
|
|
HeapFree(GetProcessHeap(), 0, TlsBasesOld);
|
|
}
|
|
|
|
TlsBases[TlsBasesCount] = DllBase;
|
|
++TlsBasesCount;
|
|
/*
|
|
NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &ulLength);
|
|
|
|
spi = (PSYSTEM_PROCESS_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
|
|
|
|
if (!spi)
|
|
return;
|
|
|
|
if (NtQuerySystemInformation(SystemProcessInformation, spi, ulLength, NULL))
|
|
return;
|
|
|
|
while (spi->UniqueProcessId != CustomTeb->UniqueProcess)
|
|
{
|
|
if (!spi->NextEntryOffset)
|
|
return;
|
|
spi = spi->NextEntryOffset + (ULONG_PTR)spi;
|
|
}
|
|
|
|
sti = (ULONG_PTR)spi + sizeof(SYSTEM_PROCESS_INFORMATION); // A slight problem here, the struct size got bigger in Windows 2000. Perhaps it will have to be derived from somewhere for anything older.
|
|
|
|
for (i = 0; i < spi->NumberOfThreads; i++)
|
|
{
|
|
hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, sti->ClientId.UniqueThread);
|
|
if (hThread)
|
|
{
|
|
NtQueryInformationThread(hThread, 0, &tbi, sizeof(THREAD_BASIC_INFORMATION), NULL);
|
|
SuspendThread(hThread);
|
|
DataTableEntry = (PLDR_DATA_TABLE_ENTRY)NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->Reserved2[1];
|
|
DataTableEntryInit = DataTableEntry;
|
|
do
|
|
{
|
|
TLSInit_DllMain_ThreadAttach_Internal(DataTableEntry->DllBase, tbi.TebBaseAddress);
|
|
DataTableEntry = DataTableEntry->Reserved1[0];
|
|
} while (DataTableEntry != DataTableEntryInit);
|
|
ResumeThread(hThread);
|
|
CloseHandle(hThread);
|
|
}
|
|
++sti;
|
|
}*/
|
|
for (i = 0; i < TlsBasesCount; i++)
|
|
{
|
|
TLSInit_DllMain_ThreadAttach_Internal(TlsBases[i], NULL);
|
|
}
|
|
// HeapFree(GetProcessHeap(), 0, spi);
|
|
spi = NULL;
|
|
}
|
|
|
|
__declspec(dllexport) VOID WINAPI TLSInit_DllMain_ThreadAttach(ULONG_PTR DllBase)
|
|
{
|
|
return;
|
|
int i;
|
|
PIMAGE_TLS_DIRECTORY TlsDirectory;
|
|
PTEB_CUSTOM CustomTeb;
|
|
PULONG TlsIdx;
|
|
TlsHack* TlsHackEntry;
|
|
ULONG_PTR* ThreadLocalStoragePointer;
|
|
ULONG_PTR* ThreadLocalStoragePointerNew, ImageBase;
|
|
|
|
|
|
if (!DllBase)
|
|
return;
|
|
|
|
CustomTeb = (PTEB_CUSTOM)NtCurrentTeb();
|
|
|
|
if (LOBYTE(GetVersion()) >= 6 || (LOBYTE(GetVersion()) < 6 && CustomTeb->ProcessEnvironmentBlock->SystemReserved == 1))
|
|
return; // Nothing to do here
|
|
|
|
TlsDirectory = GetTlsDirectory(DllBase, &ImageBase);
|
|
|
|
if (!TlsDirectory)
|
|
return;
|
|
|
|
ThreadLocalStoragePointer = CustomTeb->ThreadLocalStoragePointer;
|
|
|
|
TlsIdx = (PULONG)((TlsDirectory->AddressOfIndex)); //- ImageBase)); + DllBase);
|
|
|
|
if (CustomTeb->SystemReserved1[0x35] >= *TlsIdx)
|
|
return;
|
|
|
|
CustomTeb->SystemReserved1[0x35] = *TlsIdx;
|
|
ThreadLocalStoragePointerNew = (ULONG_PTR*)HeapAlloc(CustomTeb->ProcessEnvironmentBlock->ProcessHeap, HEAP_ZERO_MEMORY, (*TlsIdx + 2) * sizeof(ULONG_PTR));
|
|
|
|
if (ThreadLocalStoragePointer)
|
|
{
|
|
for (i = 0; i < *TlsIdx; i++)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
TlsHackEntry = (TlsHack*)ThreadLocalStoragePointer[i];
|
|
TlsHackEntry->Ptr2 = 0; // Provisional Supermium 121 hack.
|
|
}
|
|
ThreadLocalStoragePointerNew[i] = ThreadLocalStoragePointer[i];
|
|
}
|
|
}
|
|
|
|
ThreadLocalStoragePointerNew[*TlsIdx] = (ULONG_PTR)HeapAlloc(CustomTeb->ProcessEnvironmentBlock->ProcessHeap, HEAP_ZERO_MEMORY,
|
|
TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
|
|
|
|
if(CustomTeb->SystemReserved1[0x35] == *TlsIdx)
|
|
ThreadLocalStoragePointerNew[*TlsIdx + 1] = 0xABABABAB;
|
|
|
|
RtlMoveMemory((PVOID)ThreadLocalStoragePointerNew[*TlsIdx], (PVOID)(TlsDirectory->StartAddressOfRawData),
|
|
TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
|
|
|
|
// if (ThreadLocalStoragePointer)
|
|
// HeapFree(CustomTeb->ProcessEnvironmentBlock->ProcessHeap, 0, ThreadLocalStoragePointer);
|
|
|
|
CustomTeb->ThreadLocalStoragePointer = ThreadLocalStoragePointerNew;
|
|
}
|
|
|
|
VOID WINAPI TLSInit_DllMain_ThreadAttach_Internal(ULONG_PTR DllBase, ULONG_PTR TebAddr)
|
|
{
|
|
int i;
|
|
PIMAGE_TLS_DIRECTORY TlsDirectory;
|
|
PTEB_CUSTOM CustomTeb;
|
|
PULONG TlsIdx;
|
|
TlsHack* TlsHackEntry;
|
|
ULONG_PTR* ThreadLocalStoragePointer;
|
|
ULONG_PTR* ThreadLocalStoragePointerNew, ImageBase;
|
|
CHAR Buffer[256];
|
|
CHAR ModuleName[128];
|
|
DWORD BufferWritten;
|
|
|
|
memset(Buffer, 0, 256);
|
|
|
|
|
|
if (!DllBase)
|
|
return;
|
|
if (!TebAddr)
|
|
CustomTeb = (PTEB_CUSTOM)NtCurrentTeb();
|
|
else
|
|
CustomTeb = TebAddr;
|
|
|
|
if ((LOBYTE(GetVersion()) >= 6))
|
|
return; // Nothing to do here
|
|
|
|
TlsDirectory = GetTlsDirectory(DllBase, &ImageBase);
|
|
|
|
if (!TlsDirectory)
|
|
return;
|
|
|
|
ThreadLocalStoragePointer = CustomTeb->ThreadLocalStoragePointer;
|
|
|
|
TlsIdx = (PULONG)((TlsDirectory->AddressOfIndex)); //- ImageBase)); + DllBase);
|
|
|
|
if (CustomTeb->SystemReserved1[0x35] >= *TlsIdx) {
|
|
// GetModuleFileNameA(DllBase, ModuleName, 128);
|
|
// int buffer_size = wsprintfA(Buffer, "Thread ID %d: TLS failed due to TlsIdx below current max slot, %d out of %d, %s\r\n", GetCurrentThreadId(),
|
|
// CustomTeb->SystemReserved1[0x35], *TlsIdx, ModuleName);
|
|
|
|
// WriteFile(g_hFile, Buffer, buffer_size, &BufferWritten, NULL);
|
|
return;
|
|
}
|
|
|
|
CustomTeb->SystemReserved1[0x35] = *TlsIdx;
|
|
ThreadLocalStoragePointerNew = (ULONG_PTR*)HeapAlloc(CustomTeb->ProcessEnvironmentBlock->ProcessHeap, HEAP_ZERO_MEMORY, (*TlsIdx + 2) * sizeof(ULONG_PTR));
|
|
|
|
if (ThreadLocalStoragePointer)
|
|
{
|
|
for (i = 0; i < *TlsIdx; i++)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
TlsHackEntry = (TlsHack*)ThreadLocalStoragePointer[i];
|
|
// TlsHackEntry->Ptr2 = 0; // Provisional Supermium 121 hack.
|
|
}
|
|
ThreadLocalStoragePointerNew[i] = ThreadLocalStoragePointer[i];
|
|
}
|
|
}
|
|
|
|
//int buffer_size = wsprintfA(Buffer, "Thread ID %d: TLS request successful\r\n", GetCurrentThreadId());
|
|
|
|
//WriteFile(g_hFile, Buffer, buffer_size, &BufferWritten, NULL);
|
|
|
|
ThreadLocalStoragePointerNew[*TlsIdx] = (ULONG_PTR)HeapAlloc(CustomTeb->ProcessEnvironmentBlock->ProcessHeap, HEAP_ZERO_MEMORY,
|
|
TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
|
|
// if (CustomTeb->SystemReserved1[0x35] == *TlsIdx)
|
|
// ThreadLocalStoragePointerNew[*TlsIdx + 1] = 0xABABABAB;
|
|
|
|
RtlMoveMemory((PVOID)ThreadLocalStoragePointerNew[*TlsIdx], (PVOID)(TlsDirectory->StartAddressOfRawData),
|
|
TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
|
|
|
|
// if (ThreadLocalStoragePointer)
|
|
// HeapFree(CustomTeb->ProcessEnvironmentBlock->ProcessHeap, 0, ThreadLocalStoragePointer);
|
|
|
|
CustomTeb->ThreadLocalStoragePointer = ThreadLocalStoragePointerNew;
|
|
} |