Thanks to a hint, I've been able to understand how to use the %GS
register. So the plan to access the TLS is as follows: when a thread starts it saves the pointer to its state (more specifically, a segment selector for a new segment whose base is a pointer to a structure with thread-specific data and with no limit) at the address %FS:0x14
(which corresponds to the Arbitrary Data Slot of the Windows Thread Information Block).
And at certain moments, that selector is copied into the %GS
register:
At first, I thought that the %GS
is being reset every time the scheduler preempts the thread. But experiments have shown that %GS
is only being reset when calling Windows API functions. I was confused by the fact that I was unable to set this register via the SetThreadContext
at all – that's why I thought that this register is not persisted in the thread context.
Implementing this approach would require changing the way foreign functions are called and to take it into account when implementing thread hijacking via stack frame planting.