Ejemplo n.º 1
0
bool
ref_is_far_var(mem_ref_t *ref)
{
    if (opnd_is_far_base_disp(ref->opnd))
        return true;
    return false;
}
Ejemplo n.º 2
0
static bool
ref_is_interested(mem_ref_t *ref)
{
    /* I still have no idea how far memory is calculated */
    if (opnd_is_far_base_disp(ref->opnd))
        return false;
    return true;
}
Ejemplo n.º 3
0
bool
ref_is_string_ref(mem_ref_t *ref)
{
    if (!opcode_is_rep_ins(ref->opcode))
        return false;
    if (!opnd_is_far_base_disp(ref->opnd))
        return false;

    return true;
}
Ejemplo n.º 4
0
bool
ref_is_tls(opnd_t opnd)
{
    reg_id_t seg;
    if (opnd_is_far_base_disp(opnd)) {
        seg = opnd_get_segment(opnd);
        if (seg == DR_SEG_FS || seg == DR_SEG_GS)
            return true;
    }
    return false;
}
Ejemplo n.º 5
0
/* returns whether found a syscall
 * - found_eax: whether the caller has seen "mov imm => %eax"
 * - found_edx: whether the caller has seen "mov $0x7ffe0300 => %edx",
 *              xref the comment below about "mov $0x7ffe0300 => %edx".
 */
static bool
process_syscall_instr(void *dcontext, instr_t *instr, bool found_eax, bool found_edx)
{
    /* ASSUMPTION: a mov imm of 0x7ffe0300 into edx followed by an
     * indirect call via edx is a system call on XP and later
     * On XP SP1 it's call *edx, while on XP SP2 it's call *(edx)
     * For wow it's a call through fs.
     * FIXME - core exports various is_*_syscall routines (such as
     * instr_is_wow64_syscall()) which we could use here instead of
     * duplicating if they were more flexible about when they could
     * be called (instr_is_wow64_syscall() for ex. asserts if not
     * in a wow process).
     */
    if (/* int 2e or x64 or win8 sysenter */
        (instr_is_syscall(instr) &&
         found_eax && (expect_int2e || expect_x64 || expect_sysenter)) ||
        /* sysenter case */
        (expect_sysenter && found_edx && found_eax &&
         instr_is_call_indirect(instr) &&
         /* XP SP{0,1}, 2003 SP0: call *edx */
         ((opnd_is_reg(instr_get_target(instr)) &&
           opnd_get_reg(instr_get_target(instr)) == REG_EDX) ||
          /* XP SP2, 2003 SP1: call *(edx) */
          (opnd_is_base_disp(instr_get_target(instr)) &&
           opnd_get_base(instr_get_target(instr)) == REG_EDX &&
           opnd_get_index(instr_get_target(instr)) == REG_NULL &&
           opnd_get_disp(instr_get_target(instr)) == 0))) ||
        /* wow case
         * we don't require found_ecx b/c win8 does not use ecx
         */
        (expect_wow && found_eax &&
         instr_is_call_indirect(instr) &&
         ((opnd_is_far_base_disp(instr_get_target(instr)) &&
           opnd_get_base(instr_get_target(instr)) == REG_NULL &&
           opnd_get_index(instr_get_target(instr)) == REG_NULL &&
           opnd_get_segment(instr_get_target(instr)) == SEG_FS) ||
          /* win10 has imm in edx and a near call */
          found_edx)))
        return true;
    return false;
}
Ejemplo n.º 6
0
/* returns false on failure */
static bool
decode_syscall_num(void *dcontext, byte *entry, syscall_info_t *info)
{
    /* FIXME: would like to fail gracefully rather than have a DR assertion
     * on non-code! => use DEBUG=0 INTERNAL=1 DR build!
     */
    bool found_syscall = false, found_eax = false, found_edx = false, found_ecx = false;
    bool found_ret = false;
    byte *pc;
    int num_instr = 0;
    instr_t *instr;
    if (entry == NULL)
        return false;
    info->num_args = -1; /* if find sysnum but not args */
    info->sysnum = -1;
    info->fixup_index = -1;
    instr = instr_create(dcontext);
    pc = entry;
    /* FIXME - we don't support decoding 64bit instructions in 32bit mode, but I want
     * this to work on 32bit machines.  Hack fix based on the wrapper pattern, we skip
     * the first instruction (mov r10, rcx) here, the rest should decode ok.
     * Xref PR 236203. */
    if (expect_x64 && *pc == 0x4c && *(pc+1) == 0x8b && *(pc+2) == 0xd1)
        pc += 3;
    while (true) {
        instr_reset(dcontext, instr);
        pc = decode(dcontext, pc, instr);
        if (verbose)
            dr_print_instr(dcontext, STDOUT, instr, "");
        if (pc == NULL || !instr_valid(instr))
            break;
        /* ASSUMPTION: a mov imm of 0x7ffe0300 into edx followed by an
         * indirect call via edx is a system call on XP and later
         * On XP SP1 it's call *edx, while on XP SP2 it's call *(edx)
         * For wow it's a call through fs.
         * FIXME - core exports various is_*_syscall routines (such as
         * instr_is_wow64_syscall()) which we could use here instead of
         * duplicating if they were more flexible about when they could
         * be called (instr_is_wow64_syscall() for ex. asserts if not
         * in a wow process).
         */
        if (/* int 2e or x64 or win8 sysenter */
            (instr_is_syscall(instr) && found_eax && (expect_int2e || expect_x64 || expect_sysenter)) ||
            /* sysenter case */
            (expect_sysenter && found_edx && found_eax &&
             instr_is_call_indirect(instr) &&
             /* XP SP{0,1}, 2003 SP0: call *edx */
             ((opnd_is_reg(instr_get_target(instr)) &&
               opnd_get_reg(instr_get_target(instr)) == REG_EDX) ||
              /* XP SP2, 2003 SP1: call *(edx) */
              (opnd_is_base_disp(instr_get_target(instr)) &&
               opnd_get_base(instr_get_target(instr)) == REG_EDX &&
               opnd_get_index(instr_get_target(instr)) == REG_NULL &&
               opnd_get_disp(instr_get_target(instr)) == 0))) ||
            /* wow case 
             * we don't require found_ecx b/c win8 does not use ecx
             */
            (expect_wow && found_eax &&
             instr_is_call_indirect(instr) &&
             opnd_is_far_base_disp(instr_get_target(instr)) &&
             opnd_get_base(instr_get_target(instr)) == REG_NULL &&
             opnd_get_index(instr_get_target(instr)) == REG_NULL &&
             opnd_get_segment(instr_get_target(instr)) == SEG_FS)) {
            found_syscall = true;
        } else if (instr_is_return(instr)) {
            if (!found_ret) {
                process_ret(instr, info);
                found_ret = true;
            }
            break;
        } else if (instr_is_cti(instr)) {
            if (instr_get_opcode(instr) == OP_call) {
                /* handle win8 x86 which has sysenter callee adjacent-"inlined"
                 *     ntdll!NtYieldExecution:
                 *     77d7422c b801000000      mov     eax,1
                 *     77d74231 e801000000      call    ntdll!NtYieldExecution+0xb (77d74237)
                 *     77d74236 c3              ret
                 *     77d74237 8bd4            mov     edx,esp
                 *     77d74239 0f34            sysenter
                 *     77d7423b c3              ret
                 */
                byte *tgt;
                assert(opnd_is_pc(instr_get_target(instr)));
                tgt = opnd_get_pc(instr_get_target(instr));
                /* we expect only ret or ret imm, and possibly some nops (in gdi32).
                 * XXX: what about jmp to shared ret (seen in the past on some syscalls)?
                 */
                if (tgt > pc && tgt <= pc + 16) {
                    bool ok = false;
                    do {
                        if (pc == tgt) {
                            ok = true;
                            break;
                        }
                        instr_reset(dcontext, instr);
                        pc = decode(dcontext, pc, instr);
                        if (verbose)
                            dr_print_instr(dcontext, STDOUT, instr, "");
                        if (instr_is_return(instr)) {
                            process_ret(instr, info);
                            found_ret = true;
                        } else if (!instr_is_nop(instr))
                            break;
                        num_instr++;
                    } while (num_instr <= MAX_INSTRS_BEFORE_SYSCALL);
                    if (ok)
                        continue;
                }
            }
            /* assume not a syscall wrapper if we hit a cti */
            break; /* give up gracefully */
        } else if ((!found_eax || !found_edx || !found_ecx) &&
            instr_get_opcode(instr) == OP_mov_imm &&
            opnd_is_reg(instr_get_dst(instr, 0))) {
            if (!found_eax && opnd_get_reg(instr_get_dst(instr, 0)) == REG_EAX) {
                info->sysnum = (int) opnd_get_immed_int(instr_get_src(instr, 0));
                found_eax = true;
            } else if (!found_edx && opnd_get_reg(instr_get_dst(instr, 0)) == REG_EDX) {
                int imm = (int) opnd_get_immed_int(instr_get_src(instr, 0));
                if (imm == 0x7ffe0300)
                    found_edx = true;
            } else if (!found_ecx && opnd_get_reg(instr_get_dst(instr, 0)) == REG_ECX) {
                found_ecx = true;
                info->fixup_index = (int) opnd_get_immed_int(instr_get_src(instr, 0));
            }
        } else if (instr_get_opcode(instr) == OP_xor &&
                   opnd_is_reg(instr_get_src(instr, 0)) &&
                   opnd_get_reg(instr_get_src(instr, 0)) == REG_ECX &&
                   opnd_is_reg(instr_get_dst(instr, 0)) &&
                   opnd_get_reg(instr_get_dst(instr, 0)) == REG_ECX) {
            /* xor to 0 */
            found_ecx = true;
            info->fixup_index = 0;
        }
        num_instr++;
        if (num_instr > MAX_INSTRS_BEFORE_SYSCALL) /* wrappers should be short! */
            break; /* avoid weird cases like NPXEMULATORTABLE */
    }
    instr_destroy(dcontext, instr);
    return found_syscall;
}