diff --git a/afl_transforms/tools/zafl/zafl.cpp b/afl_transforms/tools/zafl/zafl.cpp index 58e7817d6f7efd725daebe4cb50189d9af0fe5fe..0dc8ae980a9509208dfdf78eb95554a9402fb0fb 100644 --- a/afl_transforms/tools/zafl/zafl.cpp +++ b/afl_transforms/tools/zafl/zafl.cpp @@ -30,6 +30,7 @@ #include <MEDS_DeadRegAnnotation.hpp> #include <MEDS_SafeFuncAnnotation.hpp> #include <utils.hpp> +#include <string.h> using namespace std; using namespace libTransform; @@ -138,6 +139,37 @@ zafl_blockid_t Zafl_t::get_blockid(unsigned p_max_mask) return blockid; } +static std::vector<RegisterName> get_free_regs(RegisterSet_t candidates) +{ + std::vector<RegisterName> free_regs; + + + for (auto f : candidates) + { + switch (f) + { + case rn_RAX: + case rn_RBX: + case rn_RCX: + case rn_RDX: + case rn_R8: + case rn_R9: + case rn_R10: + case rn_R11: + case rn_R12: + case rn_R13: + case rn_R14: + case rn_R15: + free_regs.push_back(f); + break; + default: + break; + } + } + + return free_regs; +} + /* zafl_trace_bits[zafl_prev_id ^ id]++; zafl_prev_id = id >> 1; @@ -147,39 +179,124 @@ void Zafl_t::afl_instrument_bb(Instruction_t *inst, const bool p_hasLeafAnnotati assert(inst); char buf[8192]; - auto tmp = inst; - auto live_flags = true; + std::vector<RegisterName> free_regs; // need 3 free regs + char *reg_temp = NULL; + char *reg_temp32 = NULL; + char *reg_temp16 = NULL; + char *reg_trace_map = NULL; + char *reg_prev_id = NULL; + bool save_temp = true; + bool save_trace_map = true; + bool save_prev_id = true; + auto tmp = inst; +// auto originalInstruction = inst; +// auto originalFallthrough = inst->GetFallthrough(); +// auto originalDisassembly = inst->getDisassembly(); - if (m_use_stars) + if (m_use_stars) + { live_flags = !(areFlagsDead(inst, m_stars_analysis_engine.getAnnotations())); + auto regset=get_dead_regs(inst, m_stars_analysis_engine.getAnnotations()); + free_regs = get_free_regs(regset); + if (free_regs.size() >= 1) { + reg_temp = strdup(Register::toString(free_regs[0]).c_str()); + reg_temp32 = strdup(Register::toString(Register::demoteTo32(free_regs[0])).c_str()); + reg_temp16 = strdup(Register::toString(Register::demoteTo16(free_regs[0])).c_str()); + save_temp = false; + } + if (free_regs.size() >= 2) { + reg_trace_map = strdup(Register::toString(free_regs[1]).c_str()); + save_trace_map = false; + } + if (free_regs.size() >= 3) { + reg_prev_id = strdup(Register::toString(free_regs[2]).c_str()); + save_prev_id = false; + } + } + if (!reg_temp) + reg_temp = strdup("rax"); + if (!reg_temp32) + reg_temp32 = strdup("eax"); + if (!reg_temp16) + reg_temp16 = strdup("ax"); + if (!reg_trace_map) + reg_trace_map = strdup("rcx"); + if (!reg_prev_id) + reg_prev_id = strdup("rdx"); + + cerr << "save_temp: " << save_temp << " save_trace_map: " << save_trace_map << " save_prev_id: " << save_prev_id << " live_flags: " << live_flags << endl; + cerr << "reg_temp: " << reg_temp << " " << reg_temp32 << " " << reg_temp16 + << " reg_trace_map: " << reg_trace_map + << " reg_prev_id: " << reg_prev_id << endl; + + // + // warning: first instrumentation must use insertAssemblyBefore + // + + auto inserted_before = false; if (p_hasLeafAnnotation) { // leaf function, must respect the red zone insertAssemblyBefore(getFileIR(), tmp, "lea rsp, [rsp-128]"); - tmp = insertAssemblyAfter(getFileIR(), tmp, "push rax"); + inserted_before = true; } - else + + if (save_temp) + { + if (inserted_before) + { + tmp = insertAssemblyAfter(getFileIR(), tmp, "push rax"); + } + else + { + insertAssemblyBefore(getFileIR(), tmp, "push rax"); + inserted_before = true; + } + } + + if (save_trace_map) { - insertAssemblyBefore(getFileIR(), tmp, "push rax"); + if (inserted_before) + tmp = insertAssemblyAfter(getFileIR(), tmp, "push rcx"); + else + { + insertAssemblyBefore(getFileIR(), tmp, "push rcx"); + inserted_before = true; + } } - tmp = insertAssemblyAfter(getFileIR(), tmp, "push rcx"); - tmp = insertAssemblyAfter(getFileIR(), tmp, "push rdx"); + if (save_prev_id) + { + if (inserted_before) + tmp = insertAssemblyAfter(getFileIR(), tmp, "push rdx"); + else + { + insertAssemblyBefore(getFileIR(), tmp, "push rdx"); + inserted_before = true; + } + } const auto blockid = get_blockid(); static unsigned labelid = 0; labelid++; - cout << "labelid: " << labelid << " baseid: " << inst->GetBaseID() << " instruction: " << inst->getDisassembly(); + cerr << "labelid: " << labelid << " baseid: " << inst->GetBaseID() << " instruction: " << inst->getDisassembly(); + if (live_flags) { - cout << " flags are live" << endl; - tmp = insertAssemblyAfter(getFileIR(), tmp, "pushf"); + cerr << " flags are live" << endl; + if (inserted_before) + tmp = insertAssemblyAfter(getFileIR(), tmp, "pushf"); + else + { + insertAssemblyBefore(getFileIR(), tmp, "pushf"); + inserted_before = true; + } } else { - cout << " flags are dead" << endl; + cerr << " flags are dead" << endl; } @@ -195,39 +312,74 @@ void Zafl_t::afl_instrument_bb(Instruction_t *inst, const bool p_hasLeafAnnotati 23: 66 89 02 mov WORD PTR [rdx],ax */ - sprintf(buf, "L%d: mov rdx, QWORD [rel L%d]", labelid, labelid); - tmp = insertAssemblyAfter(getFileIR(), tmp, buf); +// 0: 48 8b 15 00 00 00 00 mov rdx,QWORD PTR [rip+0x0] # 7 <f+0x7> + sprintf(buf, "P%d: mov %s, QWORD [rel P%d]", labelid, reg_prev_id, labelid); // rdx + if (inserted_before) + { + tmp = insertAssemblyAfter(getFileIR(), tmp, buf); + } + else + { + insertAssemblyBefore(getFileIR(), tmp, buf); + inserted_before = true; + } create_got_reloc(getFileIR(), m_prev_id, tmp); - sprintf(buf, "X%d: mov rcx, QWORD [rel X%d]", labelid, labelid); +// 7: 48 8b 0d 00 00 00 00 mov rcx,QWORD PTR [rip+0x0] # e <f+0xe> + sprintf(buf, "T%d: mov %s, QWORD [rel T%d]", labelid, reg_trace_map, labelid); // rcx tmp = insertAssemblyAfter(getFileIR(), tmp, buf); create_got_reloc(getFileIR(), m_trace_map, tmp); - tmp = insertAssemblyAfter(getFileIR(), tmp, "movzx eax,WORD [rdx]"); - - sprintf(buf, "xor ax,0x%x", blockid); +// e: 0f b7 02 movzx eax,WORD PTR [rdx] + sprintf(buf,"movzx %s,WORD [%s]", reg_temp32, reg_prev_id); tmp = insertAssemblyAfter(getFileIR(), tmp, buf); - - tmp = insertAssemblyAfter(getFileIR(), tmp, "movzx eax,ax"); - tmp = insertAssemblyAfter(getFileIR(), tmp, "add rax,QWORD [rcx]"); - tmp = insertAssemblyAfter(getFileIR(), tmp, "add BYTE [rax],0x1"); - - sprintf(buf, "mov eax, 0x%x", blockid >> 1); +// 11: 66 35 34 12 xor ax,0x1234 + sprintf(buf, "xor %s,0x%x", reg_temp16, blockid); + tmp = insertAssemblyAfter(getFileIR(), tmp, buf); +// 15: 0f b7 c0 movzx eax,ax + sprintf(buf,"movzx %s,%s", reg_temp32, reg_temp16); + tmp = insertAssemblyAfter(getFileIR(), tmp, buf); +// 18: 48 03 01 add rax,QWORD PTR [rcx] + sprintf(buf,"add %s,QWORD [%s]", reg_temp, reg_trace_map); + tmp = insertAssemblyAfter(getFileIR(), tmp, buf); +// 1b: 80 00 01 add BYTE PTR [rax],0x1 + sprintf(buf,"add BYTE [%s],0x1", reg_temp); + tmp = insertAssemblyAfter(getFileIR(), tmp, buf); +// 1e: b8 1a 09 00 00 mov eax,0x91a + sprintf(buf, "mov %s, 0x%x", reg_temp32, blockid >> 1); + tmp = insertAssemblyAfter(getFileIR(), tmp, buf); + sprintf(buf,"baseid: %d labelid: %d", tmp->GetBaseID(), labelid); +// 23: 66 89 02 mov WORD PTR [rdx],ax + sprintf(buf, "mov WORD [%s], %s", reg_prev_id, reg_temp16); tmp = insertAssemblyAfter(getFileIR(), tmp, buf); - tmp = insertAssemblyAfter(getFileIR(), tmp, "mov WORD [rdx], ax"); + sprintf(buf,"baseid: %d labelid: %d", tmp->GetBaseID(), labelid); if (live_flags) { tmp = insertAssemblyAfter(getFileIR(), tmp, "popf"); } - tmp = insertAssemblyAfter(getFileIR(), tmp, "pop rdx"); - tmp = insertAssemblyAfter(getFileIR(), tmp, "pop rcx"); - tmp = insertAssemblyAfter(getFileIR(), tmp, "pop rax"); + if (save_prev_id) + { + tmp = insertAssemblyAfter(getFileIR(), tmp, "pop rdx"); + } + if (save_trace_map) + { + tmp = insertAssemblyAfter(getFileIR(), tmp, "pop rcx"); + } + if (save_temp) + { + tmp = insertAssemblyAfter(getFileIR(), tmp, "pop rax"); + } if (p_hasLeafAnnotation) { tmp = insertAssemblyAfter(getFileIR(), tmp, "lea rsp, [rsp+128]"); } - + + free(reg_temp); + free(reg_temp32); + free(reg_temp16); + free(reg_trace_map); + free(reg_prev_id); } /*