Basic TLS with patching + int 0x80
This commit is contained in:
parent
af18453950
commit
724c56d8aa
|
@ -19,8 +19,34 @@ void Flush() {
|
||||||
spdlog::details::registry::instance().flush_all();
|
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
|
#ifdef _WIN64
|
||||||
static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept {
|
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;
|
const u32 ec = pExp->ExceptionRecord->ExceptionCode;
|
||||||
switch (ec) {
|
switch (ec) {
|
||||||
case EXCEPTION_ACCESS_VIOLATION: {
|
case EXCEPTION_ACCESS_VIOLATION: {
|
||||||
|
|
|
@ -95,8 +95,62 @@ Module* Linker::FindModule(/*u32 id*/)
|
||||||
return &m_modules[0];
|
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
|
//get elf header, program header
|
||||||
const auto elf_header = m->elf.GetElfHeader();
|
const auto elf_header = m->elf.GetElfHeader();
|
||||||
const auto elf_pheader = m->elf.GetProgramHeader();
|
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);
|
LOG_INFO_IF(debug_loader, "segment_mode ..........: {}\n", segment_mode);
|
||||||
|
|
||||||
m->elf.LoadSegment(segment_addr, elf_pheader[i].p_offset, segment_file_size);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue