From 724c56d8aa07782615023b1e9b288d086d2b9db5 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Sat, 20 Jan 2024 14:29:23 +0200 Subject: [PATCH] Basic TLS with patching + int 0x80 --- src/common/log.cpp | 26 +++++++++++++++++++ src/core/linker.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/common/log.cpp b/src/common/log.cpp index eba58f6f..2a3c5114 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -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: { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index fdedbee5..cc35c884 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -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 {