Add experimental TLS loader

This commit is contained in:
momo5502 2018-12-27 10:56:21 +01:00
parent e1333db8a2
commit 2d5a4e43b3
2 changed files with 137 additions and 0 deletions

99
src/loader/tls_loader.cpp Normal file
View File

@ -0,0 +1,99 @@
#include <std_include.hpp>
#include "tls_loader.hpp"
#include "utils/nt.hpp"
std::mutex tls_loader::mutex_;
std::vector<std::unique_ptr<tls_loader::tls_entry>> tls_loader::tls_entries_;
//static thread_local tls_loader::tls_executer $;
void tls_loader::handle(IMAGE_TLS_DIRECTORY* tls_directory)
{
std::lock_guard _(mutex_);
tls_entries_.push_back(std::make_unique<tls_entry>(tls_directory));
}
void tls_loader::execute(const bool is_attaching)
{
std::lock_guard _(mutex_);
for (auto& entry : tls_entries_)
{
entry->execute(is_attaching);
}
}
tls_loader::tls_entry::tls_entry(IMAGE_TLS_DIRECTORY* tls_directory) : tls_directory_(tls_directory)
{
this->tls_index_ = 18;//TlsAlloc();
*reinterpret_cast<DWORD*>(this->tls_directory_->AddressOfIndex) = this->tls_index_;
this->execute(true);
}
tls_loader::tls_entry::~tls_entry()
{
//TlsFree(this->tls_index_);
this->allocator_.clear();
}
void tls_loader::tls_entry::execute(const bool is_attaching)
{
if (is_attaching) this->attach();
else this->detach();
}
void tls_loader::tls_entry::attach()
{
const size_t data_size = this->tls_directory_->EndAddressOfRawData - this->tls_directory_->StartAddressOfRawData;
const size_t size = data_size + this->tls_directory_->SizeOfZeroFill;
const auto data = this->allocator_.allocate(size);
std::memcpy(data, PVOID(this->tls_directory_->StartAddressOfRawData), data_size);
const auto tls_indices = reinterpret_cast<LPVOID*>(__readfsdword(0x2C));
tls_indices[this->tls_index_] = data;
auto callbacks = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(this->tls_directory_->AddressOfCallBacks);
if (callbacks)
{
utils::nt::module self;
while (*callbacks)
{
(*callbacks)(self.get_ptr(), DLL_THREAD_ATTACH, nullptr);
++callbacks;
}
}
}
void tls_loader::tls_entry::detach()
{
auto callbacks = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(this->tls_directory_->AddressOfCallBacks);
if (callbacks)
{
utils::nt::module self;
while (*callbacks)
{
(*callbacks)(self.get_ptr(), DLL_THREAD_DETACH, nullptr);
++callbacks;
}
}
const auto tls_indices = reinterpret_cast<LPVOID*>(__readfsdword(0x2C));
const auto data = tls_indices[this->tls_index_];
//const auto data = TlsGetValue(this->tls_index_);
//this->allocator_.free(data);
}
tls_loader::tls_executer::tls_executer()
{
execute(true);
}
tls_loader::tls_executer::~tls_executer()
{
execute(false);
}

38
src/loader/tls_loader.hpp Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include "utils/memory.hpp"
class tls_loader final
{
public:
class tls_executer final
{
public:
tls_executer();
~tls_executer();
};
static void handle(IMAGE_TLS_DIRECTORY* tls_directory);
private:
class tls_entry final
{
public:
tls_entry(IMAGE_TLS_DIRECTORY* tls_directory);
~tls_entry();
void execute(bool is_attaching);
private:
utils::memory::allocator allocator_;
IMAGE_TLS_DIRECTORY* tls_directory_;
DWORD tls_index_;
void attach();
void detach();
};
static std::mutex mutex_;
static std::vector<std::unique_ptr<tls_entry>> tls_entries_;
static void execute(bool is_attaching);
};