Basic TLS with patching + int 0x80

This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2024-01-20 14:29:23 +02:00
parent af18453950
commit 724c56d8aa
2 changed files with 86 additions and 2 deletions

View File

@ -19,8 +19,34 @@ void Flush() {
spdlog::details::registry::instance().flush_all();
}
thread_local uint8_t TLS[1024];
uint64_t tls_access(int64_t tls_offset) {
if (tls_offset == 0) {
return (uint64_t)TLS;
}
}
#ifdef _WIN64
static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept {
if (*(uint8_t *)pExp->ContextRecord->Rip == 0xcd) {
int reg = *(uint8_t *)(pExp->ContextRecord->Rip + 1) - 0x80;
int sizes = *(uint8_t *)(pExp->ContextRecord->Rip + 2);
int pattern_size = sizes & 0xF;
int imm_size = sizes >> 4;
int64_t tls_offset;
if (imm_size == 4)
tls_offset = *(int32_t *)(pExp->ContextRecord->Rip + pattern_size);
else
tls_offset = *(int64_t *)(pExp->ContextRecord->Rip + pattern_size);
(&pExp->ContextRecord->Rax)[reg] = tls_access(tls_offset); /* TLS_ACCESS */
pExp->ContextRecord->Rip += pattern_size + imm_size;
return EXCEPTION_CONTINUE_EXECUTION;
}
const u32 ec = pExp->ExceptionRecord->ExceptionCode;
switch (ec) {
case EXCEPTION_ACCESS_VIOLATION: {

View File

@ -95,8 +95,62 @@ Module* Linker::FindModule(/*u32 id*/)
return &m_modules[0];
}
void Linker::LoadModuleToMemory(Module* m)
{
struct TLSPattern{
uint8_t pattern[5];
uint8_t pattern_size;
uint8_t imm_size;
uint8_t target_reg;
};
constexpr TLSPattern tls_patterns[] = {
{{0x64, 0x48, 0xA1}, 3, 8, 0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm]
{{0x64, 0x48, 0x8B, 0x4, 0x25}, 5, 4, 0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0]
{{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx
{{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx
{{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx
{{0x64, 0x48, 0x8B, 0x24, 0x25}, 5, 4, 4}, // rsp
{{0x64, 0x48, 0x8B, 0x2C, 0x25}, 5, 4, 5}, // rbp
{{0x64, 0x48, 0x8B, 0x34, 0x25}, 5, 4, 6}, // rsi
{{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi
{{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8
{{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9
{{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10},// r10
{{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11},// r11
{{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12},// r12
{{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13},// r13
{{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14},// r14
{{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15},// r15
};
void PatchTLS(u64 segment_addr, u64 segment_size) {
uint8_t* code = (uint8_t*)segment_addr;
auto remaining_size = segment_size;
while (remaining_size) {
for (auto& tls_pattern : tls_patterns) {
auto total_size = tls_pattern.pattern_size + tls_pattern.imm_size;
if (remaining_size >= total_size) {
if (memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) == 0) {
if (tls_pattern.imm_size == 4)
printf("PATTERN32 FOUND @ %p, reg: %d offset: %X\n", code, tls_pattern.target_reg, *(uint32_t*)(code + tls_pattern.pattern_size));
else
printf("PATTERN64 FOUND @ %p, reg: %d offset: %lX\n", code, tls_pattern.target_reg, *(uint64_t*)(code + tls_pattern.pattern_size));
code[0] = 0xcd;
code[1] = 0x80 + tls_pattern.target_reg;
code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4);
code += total_size - 1;
remaining_size -= total_size - 1;
break;
}
}
}
code++;
remaining_size--;
}
}
void Linker::LoadModuleToMemory(Module* m) {
//get elf header, program header
const auto elf_header = m->elf.GetElfHeader();
const auto elf_pheader = m->elf.GetProgramHeader();
@ -130,6 +184,10 @@ void Linker::LoadModuleToMemory(Module* m)
LOG_INFO_IF(debug_loader, "segment_mode ..........: {}\n", segment_mode);
m->elf.LoadSegment(segment_addr, elf_pheader[i].p_offset, segment_file_size);
if (elf_pheader[i].p_flags & PF_EXEC) {
PatchTLS(segment_addr, segment_file_size);
}
}
else
{