Ejemplo n.º 1
0
int yr_modules_unload_all(
    YR_SCAN_CONTEXT* context)
{
  YR_OBJECT* module_structure;
  tidx_mask_t tidx_mask = 1 << yr_get_tidx();
  int i;

  for (i = 0; i < sizeof(yr_modules_table) / sizeof(YR_MODULE); i++)
  {
    if (yr_modules_table[i].is_loaded & tidx_mask)
    {
      module_structure = (YR_OBJECT*) yr_hash_table_lookup(
          context->objects_table,
          yr_modules_table[i].name,
          NULL);

      assert(module_structure != NULL);

      yr_modules_table[i].unload(module_structure);
      yr_modules_table[i].is_loaded &= ~tidx_mask;
    }
  }

  return ERROR_SUCCESS;
}
Ejemplo n.º 2
0
Archivo: rules.c Proyecto: dodng/yara
void _yr_rules_clean_matches(
    YR_RULES* rules)
{
  YR_RULE* rule;
  YR_STRING* string;

  int tidx = yr_get_tidx();

  rule = rules->rules_list_head;

  while (!RULE_IS_NULL(rule))
  {
    rule->t_flags[tidx] &= ~RULE_TFLAGS_MATCH;
    rule->ns->t_flags[tidx] &= ~NAMESPACE_TFLAGS_UNSATISFIED_GLOBAL;
    string = rule->strings;

    while (!STRING_IS_NULL(string))
    {
      string->matches[tidx].count = 0;
      string->matches[tidx].head = NULL;
      string->matches[tidx].tail = NULL;
      string->unconfirmed_matches[tidx].count = 0;
      string->unconfirmed_matches[tidx].head = NULL;
      string->unconfirmed_matches[tidx].tail = NULL;
      string++;
    }

    rule++;
  }
}
Ejemplo n.º 3
0
void yr_modules_print_data(
    YR_SCAN_CONTEXT* context)
{
  YR_OBJECT* module_structure;
  tidx_mask_t tidx_mask = 1 << yr_get_tidx();

  for (int i = 0; i < sizeof(yr_modules_table) / sizeof(YR_MODULE); i++)
  {
    if (yr_modules_table[i].is_loaded & tidx_mask)
    {
      module_structure = (YR_OBJECT*) yr_hash_table_lookup(
          context->objects_table,
          yr_modules_table[i].name,
          NULL);

      assert(module_structure != NULL);

      yr_object_print_data(module_structure, 0);
    }
  }
}
Ejemplo n.º 4
0
int yr_execute_code(
    YR_RULES* rules,
    EVALUATION_CONTEXT* context,
    int timeout,
    time_t start_time)
{
  int64_t r1;
  int64_t r2;
  int64_t r3;
  int64_t mem[MEM_SIZE];
  int64_t stack[STACK_SIZE];
  int32_t sp = 0;
  uint8_t* ip = rules->code_start;

  YR_RULE* rule;
  YR_STRING* string;
  YR_MATCH* match;
  YR_EXTERNAL_VARIABLE* external;

  int i;
  int found;
  int count;
  int result;
  int flags;
  int cycle = 0;
  int tidx = yr_get_tidx();

  while(1)
  {
    switch(*ip)
    {
      case HALT:
        // When the halt instruction is reached the stack
        // should be empty.
        assert(sp == 0);
        return ERROR_SUCCESS;

      case PUSH:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        push(r1);
        break;

      case POP:
        pop(r1);
        break;

      case CLEAR_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        mem[r1] = 0;
        break;

      case ADD_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);
        mem[r1] += r2;
        break;

      case INCR_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        mem[r1]++;
        break;

      case PUSH_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        push(mem[r1]);
        break;

      case POP_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(mem[r1]);
        break;

      case SWAPUNDEF:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);
        if (r2 != UNDEFINED)
          push(r2);
        else
          push(mem[r1]);
        break;

      case JNUNDEF:
        pop(r1);
        push(r1);

        if (r1 != UNDEFINED)
        {
          ip = *(uint8_t**)(ip + 1);
          // ip will be incremented at the end of the loop,
          // decrement it here to compensate.
          ip--;
        }
        else
        {
          ip += sizeof(uint64_t);
        }
        break;

      case JLE:
        pop(r2);
        pop(r1);
        push(r1);
        push(r2);

        if (r1 <= r2)
        {
          ip = *(uint8_t**)(ip + 1);
          // ip will be incremented at the end of the loop,
          // decrement it here to compensate.
          ip--;
        }
        else
        {
          ip += sizeof(uint64_t);
        }
        break;

      case AND:
        pop(r2);
        pop(r1);
        push(r1 & r2);
        break;

      case OR:
        pop(r2);
        pop(r1);
        push(r1 | r2);
        break;

      case NOT:
        pop(r1);
        push(!r1);
        break;

      case LT:
        pop(r2);
        pop(r1);
        push(comparison(<, r1, r2));
        break;

      case GT:
        pop(r2);
        pop(r1);
        push(comparison(>, r1, r2));
        break;

      case LE:
        pop(r2);
        pop(r1);
        push(comparison(<=, r1, r2));
        break;

      case GE:
        pop(r2);
        pop(r1);
        push(comparison(>=, r1, r2));
        break;

      case EQ:
        pop(r2);
        pop(r1);
        push(comparison(==, r1, r2));
        break;

      case NEQ:
        pop(r2);
        pop(r1);
        push(comparison(!=, r1, r2));
        break;

      case ADD:
        pop(r2);
        pop(r1);
        push(operation(+, r1, r2));
        break;

      case SUB:
        pop(r2);
        pop(r1);
        push(operation(-, r1, r2));
        break;

      case MUL:
        pop(r2);
        pop(r1);
        push(operation(*, r1, r2));
        break;

      case DIV:
        pop(r2);
        pop(r1);
        push(operation(/, r1, r2));
        break;

      case MOD:
        pop(r2);
        pop(r1);
        push(operation(%, r1, r2));
        break;

      case NEG:
        pop(r1);
        push(IS_UNDEFINED(r1) ? UNDEFINED : ~r1);
        break;

      case SHR:
        pop(r2);
        pop(r1);
        push(operation(>>, r1, r2));
        break;

      case SHL:
        pop(r2);
        pop(r1);
        push(operation(<<, r1, r2));
        break;

      case XOR:
        pop(r2);
        pop(r1);
        push(operation(^, r1, r2));
        break;

      case RULE_PUSH:
        rule = *(YR_RULE**)(ip + 1);
        ip += sizeof(uint64_t);
        push(rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0);
        break;

      case RULE_POP:
        pop(r1);
        rule = *(YR_RULE**)(ip + 1);
        ip += sizeof(uint64_t);
        if (r1)
          rule->t_flags[tidx] |= RULE_TFLAGS_MATCH;
        break;

      case EXT_INT:
        external = *(YR_EXTERNAL_VARIABLE**)(ip + 1);
        ip += sizeof(uint64_t);
        push(external->integer);
        break;

      case EXT_STR:
        external = *(YR_EXTERNAL_VARIABLE**)(ip + 1);
        ip += sizeof(uint64_t);
        push(PTR_TO_UINT64(external->string));
        break;

      case EXT_BOOL:
        external = *(YR_EXTERNAL_VARIABLE**)(ip + 1);
        ip += sizeof(uint64_t);
        if (external->type == EXTERNAL_VARIABLE_TYPE_FIXED_STRING ||
            external->type == EXTERNAL_VARIABLE_TYPE_MALLOC_STRING)
          push(external->string[0] != '\0');
        else
          push(external->integer);
        break;

      case SFOUND:
        pop(r1);
        string = UINT64_TO_PTR(YR_STRING*, r1);
        push(string->matches[tidx].tail != NULL ? 1 : 0);
        break;

      case SFOUND_AT:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1))
        {
          push(0);
          break;
        }

        string = UINT64_TO_PTR(YR_STRING*, r2);
        match = string->matches[tidx].head;
        found = 0;

        while (match != NULL)
        {
          if (r1 == match->offset)
          {
            push(1);
            found = 1;
            break;
          }

          if (r1 < match->offset)
            break;

          match = match->next;
        }

        if (!found)
          push(0);

        break;

      case SFOUND_IN:
        pop(r3);
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
        {
          push(0);
          break;
        }

        string = UINT64_TO_PTR(YR_STRING*, r3);
        match = string->matches[tidx].head;
        found = FALSE;

        while (match != NULL && !found)
        {
          if (match->offset >= r1 && match->offset <= r2)
          {
            push(1);
            found = TRUE;
          }

          if (match->offset > r2)
            break;

          match = match->next;
        }

        if (!found)
          push(0);

        break;

      case SCOUNT:
        pop(r1);
        string = UINT64_TO_PTR(YR_STRING*, r1);
        match = string->matches[tidx].head;
        found = 0;
        while (match != NULL)
        {
          found++;
          match = match->next;
        }
        push(found);
        break;

      case SOFFSET:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1))
        {
          push(UNDEFINED);
          break;
        }

        string = UINT64_TO_PTR(YR_STRING*, r2);
        match = string->matches[tidx].head;
        i = 1;
        found = FALSE;

        while (match != NULL && !found)
        {
          if (r1 == i)
          {
            push(match->offset);
            found = TRUE;
          }

          i++;
          match = match->next;
        }

        if (!found)
          push(UNDEFINED);

        break;

      case OF:
        found = 0;
        count = 0;
        pop(r1);

        while (r1 != UNDEFINED)
        {
          string = UINT64_TO_PTR(YR_STRING*, r1);
          if (string->matches[tidx].tail != NULL)
            found++;
          count++;
          pop(r1);
        }

        pop(r2);

        if (r2 != UNDEFINED)
          push(found >= r2 ? 1 : 0);
        else
          push(found >= count ? 1 : 0);

        break;

      case SIZE:
        push(context->file_size);
        break;

      case ENTRYPOINT:
        push(context->entry_point);
        break;

      case INT8:
        pop(r1);
        push(read_int8_t(context->mem_block, r1));
        break;

      case INT16:
        pop(r1);
        push(read_int16_t(context->mem_block, r1));
        break;

      case INT32:
        pop(r1);
        push(read_int32_t(context->mem_block, r1));
        break;

      case UINT8:
        pop(r1);
        push(read_uint8_t(context->mem_block, r1));
        break;

      case UINT16:
        pop(r1);
        push(read_uint16_t(context->mem_block, r1));
        break;

      case UINT32:
        pop(r1);
        push(read_uint32_t(context->mem_block, r1));
        break;

      case CONTAINS:
        pop(r2);
        pop(r1);
        push(strstr(UINT64_TO_PTR(char*, r1),
                    UINT64_TO_PTR(char*, r2)) != NULL);
        break;

      case MATCHES:
        pop(r3);
        pop(r2);
        pop(r1);

        flags = (int) r3;
        count = strlen(UINT64_TO_PTR(char*, r1));

        if (count == 0)
        {
          push(FALSE);
          break;
        }

        result = yr_re_exec(
          UINT64_TO_PTR(uint8_t*, r2),
          UINT64_TO_PTR(uint8_t*, r1),
          count,
          flags | RE_FLAGS_SCAN,
          NULL,
          NULL);

        push(result >= 0);
        break;

      default:
        // Unknown instruction, this shouldn't happen.
        assert(FALSE);
    }

    if (timeout > 0)  // timeout == 0 means no timeout
    {
      // Check for timeout every 10 instruction cycles.

      if (++cycle == 10)
      {
        if (difftime(time(NULL), start_time) > timeout)
          return ERROR_SCAN_TIMEOUT;

        cycle = 0;
      }
    }

    ip++;
  }

  // After executing the code the stack should be empty.
  assert(sp == 0);

  return ERROR_SUCCESS;
}
Ejemplo n.º 5
0
Archivo: rules.c Proyecto: dodng/yara
int _yr_scan_verify_literal_match(
    YR_AC_MATCH* ac_match,
    uint8_t* data,
    size_t data_size,
    size_t offset,
    YR_ARENA* matches_arena)
{
  int flags = 0;
  int forward_matches = 0;

  CALLBACK_ARGS callback_args;
  YR_STRING* string = ac_match->string;

  if (STRING_FITS_IN_ATOM(string))
  {
    if (STRING_IS_WIDE(string))
      forward_matches = string->length * 2;
    else
      forward_matches = string->length;
  }
  else if (STRING_IS_NO_CASE(string))
  {
    flags |= RE_FLAGS_NO_CASE;

    if (STRING_IS_ASCII(string))
    {
      forward_matches = _yr_scan_icompare(
          data + offset,
          data_size - offset,
          string->string,
          string->length);
    }

    if (STRING_IS_WIDE(string) && forward_matches == 0)
    {
      flags |= RE_FLAGS_WIDE;
      forward_matches = _yr_scan_wicompare(
          data + offset,
          data_size - offset,
          string->string,
          string->length);
    }
  }
  else
  {
    if (STRING_IS_ASCII(string))
    {
      forward_matches = _yr_scan_compare(
          data + offset,
          data_size - offset,
          string->string,
          string->length);
    }

    if (STRING_IS_WIDE(string) && forward_matches == 0)
    {
      flags |= RE_FLAGS_WIDE;
      forward_matches = _yr_scan_wcompare(
          data + offset,
          data_size - offset,
          string->string,
          string->length);
    }
  }

  if (forward_matches > 0)
  {
    if (STRING_IS_FULL_WORD(string))
    {
      if (flags & RE_FLAGS_WIDE)
      {
        if (offset >= 2 &&
            *(data + offset - 1) == 0 &&
            isalnum(*(data + offset - 2)))
          return ERROR_SUCCESS;

        if (offset + forward_matches + 1 < data_size &&
            *(data + offset + forward_matches + 1) == 0 &&
            isalnum(*(data + offset + forward_matches)))
          return ERROR_SUCCESS;
      }
      else
      {
        if (offset >= 1 &&
            isalnum(*(data + offset - 1)))
          return ERROR_SUCCESS;

        if (offset + forward_matches < data_size &&
            isalnum(*(data + offset + forward_matches)))
          return ERROR_SUCCESS;
      }
    }

    callback_args.string = string;
    callback_args.data = data;
    callback_args.data_size = data_size;
    callback_args.matches_arena = matches_arena;
    callback_args.forward_matches = forward_matches;
    callback_args.full_word = STRING_IS_FULL_WORD(string);
    callback_args.tidx = yr_get_tidx();

    FAIL_ON_ERROR(_yr_scan_match_callback(
        data + offset, 0, flags, &callback_args));
  }

  return ERROR_SUCCESS;
}
Ejemplo n.º 6
0
Archivo: rules.c Proyecto: dodng/yara
int _yr_scan_verify_re_match(
    YR_AC_MATCH* ac_match,
    uint8_t* data,
    size_t data_size,
    size_t offset,
    YR_ARENA* matches_arena)
{
  CALLBACK_ARGS callback_args;
  RE_EXEC_FUNC exec;

  int forward_matches = -1;
  int backward_matches = -1;
  int flags = 0;

  if (STRING_IS_FAST_HEX_REGEXP(ac_match->string))
    exec = _yr_scan_fast_hex_re_exec;
  else
    exec = yr_re_exec;

  if (STRING_IS_NO_CASE(ac_match->string))
    flags |= RE_FLAGS_NO_CASE;

  if (STRING_IS_HEX(ac_match->string) ||
      STRING_IS_REGEXP_DOT_ALL(ac_match->string))
    flags |= RE_FLAGS_DOT_ALL;

  if (STRING_IS_ASCII(ac_match->string))
  {
    forward_matches = exec(
        ac_match->forward_code,
        data + offset,
        data_size - offset,
        flags,
        NULL,
        NULL);
  }

  if (STRING_IS_WIDE(ac_match->string) && forward_matches == -1)
  {
    flags |= RE_FLAGS_WIDE;
    forward_matches = exec(
        ac_match->forward_code,
        data + offset,
        data_size - offset,
        flags,
        NULL,
        NULL);
  }

  switch(forward_matches)
  {
    case -1:
      return ERROR_SUCCESS;
    case -2:
      return ERROR_INSUFICIENT_MEMORY;
    case -3:
      return ERROR_INTERNAL_FATAL_ERROR;
  }

  if (forward_matches == 0 && ac_match->backward_code == NULL)
    return ERROR_SUCCESS;

  callback_args.string = ac_match->string;
  callback_args.data = data;
  callback_args.data_size = data_size;
  callback_args.matches_arena = matches_arena;
  callback_args.forward_matches = forward_matches;
  callback_args.full_word = STRING_IS_FULL_WORD(ac_match->string);
  callback_args.tidx = yr_get_tidx();

  if (ac_match->backward_code != NULL)
  {
    backward_matches = exec(
        ac_match->backward_code,
        data + offset,
        offset,
        flags | RE_FLAGS_BACKWARDS | RE_FLAGS_EXHAUSTIVE,
        _yr_scan_match_callback,
        (void*) &callback_args);

    if (backward_matches == -2)
      return ERROR_INSUFICIENT_MEMORY;

    if (backward_matches == -3)
      return ERROR_INTERNAL_FATAL_ERROR;
  }
  else
  {
    FAIL_ON_ERROR(_yr_scan_match_callback(
        data + offset, 0, flags, &callback_args));
  }

  return ERROR_SUCCESS;
}
Ejemplo n.º 7
0
int yr_execute_code(
    YR_RULES* rules,
    YR_SCAN_CONTEXT* context,
    int timeout,
    time_t start_time)
{
  int64_t r1;
  int64_t r2;
  int64_t r3;
  int64_t mem[MEM_SIZE];
  int64_t stack[STACK_SIZE];
  int64_t args[MAX_FUNCTION_ARGS];
  int32_t sp = 0;
  uint8_t* ip = rules->code_start;

  YR_RULE* rule;
  YR_STRING* string;
  YR_MATCH* match;
  YR_OBJECT* object;
  YR_OBJECT_FUNCTION* function;

  char* identifier;
  char* args_fmt;

  int i;
  int found;
  int count;
  int result;
  int cycle = 0;
  int tidx = yr_get_tidx();

  #ifdef PROFILING_ENABLED
  clock_t start = clock();
  #endif

  while(1)
  {
    switch(*ip)
    {
      case OP_HALT:
        // When the halt instruction is reached the stack
        // should be empty.
        assert(sp == 0);
        return ERROR_SUCCESS;

      case OP_PUSH:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        push(r1);
        break;

      case OP_POP:
        pop(r1);
        break;

      case OP_CLEAR_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        mem[r1] = 0;
        break;

      case OP_ADD_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);
        mem[r1] += r2;
        break;

      case OP_INCR_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        mem[r1]++;
        break;

      case OP_PUSH_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        push(mem[r1]);
        break;

      case OP_POP_M:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(mem[r1]);
        break;

      case OP_SWAPUNDEF:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);
        if (r2 != UNDEFINED)
          push(r2);
        else
          push(mem[r1]);
        break;

      case OP_JNUNDEF:
        pop(r1);
        push(r1);

        if (r1 != UNDEFINED)
        {
          ip = *(uint8_t**)(ip + 1);
          // ip will be incremented at the end of the loop,
          // decrement it here to compensate.
          ip--;
        }
        else
        {
          ip += sizeof(uint64_t);
        }
        break;

      case OP_JLE:
        pop(r2);
        pop(r1);
        push(r1);
        push(r2);

        if (r1 <= r2)
        {
          ip = *(uint8_t**)(ip + 1);
          // ip will be incremented at the end of the loop,
          // decrement it here to compensate.
          ip--;
        }
        else
        {
          ip += sizeof(uint64_t);
        }
        break;

      case OP_AND:
        pop(r2);
        pop(r1);
        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
          push(0);
        else
          push(r1 && r2);
        break;

      case OP_OR:
        pop(r2);
        pop(r1);
        if (IS_UNDEFINED(r1))
          push(r2);
        else if (IS_UNDEFINED(r2))
          push(r1);
        else
          push(r1 || r2);
        break;

      case OP_NOT:
        pop(r1);
        if (IS_UNDEFINED(r1))
          push(UNDEFINED);
        else
          push(!r1);
        break;

      case OP_LT:
        pop(r2);
        pop(r1);
        push(COMPARISON(<, r1, r2));
        break;

      case OP_GT:
        pop(r2);
        pop(r1);
        push(COMPARISON(>, r1, r2));
        break;

      case OP_LE:
        pop(r2);
        pop(r1);
        push(COMPARISON(<=, r1, r2));
        break;

      case OP_GE:
        pop(r2);
        pop(r1);
        push(COMPARISON(>=, r1, r2));
        break;

      case OP_EQ:
        pop(r2);
        pop(r1);
        push(COMPARISON(==, r1, r2));
        break;

      case OP_NEQ:
        pop(r2);
        pop(r1);
        push(COMPARISON(!=, r1, r2));
        break;

      case OP_SZ_EQ:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
          push(UNDEFINED);
        else
          push(strcmp(UINT64_TO_PTR(char*, r1),
                      UINT64_TO_PTR(char*, r2)) == 0);
        break;

      case OP_SZ_NEQ:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
          push(UNDEFINED);
        else
          push(strcmp(UINT64_TO_PTR(char*, r1),
                      UINT64_TO_PTR(char*, r2)) != 0);
        break;

      case OP_SZ_TO_BOOL:
        pop(r1);

        if (IS_UNDEFINED(r1))
          push(UNDEFINED);
        else
          push(strlen(UINT64_TO_PTR(char*, r1)) > 0);

        break;

      case OP_ADD:
        pop(r2);
        pop(r1);
        push(OPERATION(+, r1, r2));
        break;

      case OP_SUB:
        pop(r2);
        pop(r1);
        push(OPERATION(-, r1, r2));
        break;

      case OP_MUL:
        pop(r2);
        pop(r1);
        push(OPERATION(*, r1, r2));
        break;

      case OP_DIV:
        pop(r2);
        pop(r1);
        push(OPERATION(/, r1, r2));
        break;

      case OP_MOD:
        pop(r2);
        pop(r1);
        push(OPERATION(%, r1, r2));
        break;

      case OP_SHR:
        pop(r2);
        pop(r1);
        push(OPERATION(>>, r1, r2));
        break;

      case OP_SHL:
        pop(r2);
        pop(r1);
        push(OPERATION(<<, r1, r2));
        break;

      case OP_BITWISE_NOT:
        pop(r1);
        push(IS_UNDEFINED(r1) ? UNDEFINED : ~r1);
        break;

      case OP_BITWISE_AND:
        pop(r2);
        pop(r1);
        push(OPERATION(&, r1, r2));
        break;

      case OP_BITWISE_OR:
        pop(r2);
        pop(r1);
        push(OPERATION(|, r1, r2));
        break;

      case OP_BITWISE_XOR:
        pop(r2);
        pop(r1);
        push(OPERATION(^, r1, r2));
        break;

      case OP_PUSH_RULE:
        rule = *(YR_RULE**)(ip + 1);
        ip += sizeof(uint64_t);
        push(rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0);
        break;

      case OP_MATCH_RULE:
        pop(r1);
        rule = *(YR_RULE**)(ip + 1);
        ip += sizeof(uint64_t);

        if (!IS_UNDEFINED(r1) && r1)
          rule->t_flags[tidx] |= RULE_TFLAGS_MATCH;

        #ifdef PROFILING_ENABLED
        rule->clock_ticks += clock() - start;
        start = clock();
        #endif
        break;

      case OP_OBJ_LOAD:
        identifier = *(char**)(ip + 1);
        ip += sizeof(uint64_t);

        object = (YR_OBJECT*) yr_hash_table_lookup(
            context->objects_table,
            identifier,
            NULL);

        assert(object != NULL);
        push(PTR_TO_UINT64(object));
        break;

      case OP_OBJ_FIELD:
        pop(r1);

        identifier = *(char**)(ip + 1);
        ip += sizeof(uint64_t);

        if (IS_UNDEFINED(r1))
        {
          push(UNDEFINED);
          break;
        }

        object = UINT64_TO_PTR(YR_OBJECT*, r1);
        object = yr_object_lookup_field(object, identifier);
        assert(object != NULL);
        push(PTR_TO_UINT64(object));
        break;

      case OP_OBJ_VALUE:
        pop(r1);

        if (IS_UNDEFINED(r1))
        {
          push(UNDEFINED);
          break;
        }

        object = UINT64_TO_PTR(YR_OBJECT*, r1);

        switch(object->type)
        {
          case OBJECT_TYPE_INTEGER:
            push(((YR_OBJECT_INTEGER*) object)->value);
            break;

          case OBJECT_TYPE_STRING:
            if (((YR_OBJECT_STRING*) object)->value != NULL)
              push(PTR_TO_UINT64(((YR_OBJECT_STRING*) object)->value));
            else
              push(UNDEFINED);
            break;

          default:
            assert(FALSE);
        }

        break;

      case OP_INDEX_ARRAY:
        pop(r1);  // index
        pop(r2);  // array

        if (IS_UNDEFINED(r1))
        {
          push(UNDEFINED);
          break;
        }

        object = UINT64_TO_PTR(YR_OBJECT*, r2);
        assert(object->type == OBJECT_TYPE_ARRAY);
        object = yr_object_array_get_item(object, 0, r1);

        if (object != NULL)
          push(PTR_TO_UINT64(object));
        else
          push(UNDEFINED);

        break;

      case OP_LOOKUP_DICT:
        pop(r1);  // key
        pop(r2);  // dictionary

        if (IS_UNDEFINED(r1))
        {
          push(UNDEFINED);
          break;
        }

        object = UINT64_TO_PTR(YR_OBJECT*, r2);
        assert(object->type == OBJECT_TYPE_DICTIONARY);

        object = yr_object_dict_get_item(
            object, 0, UINT64_TO_PTR(const char*, r1));

        if (object != NULL)
          push(PTR_TO_UINT64(object));
        else
          push(UNDEFINED);

        break;

      case OP_CALL:
        args_fmt = *(char**)(ip + 1);
        ip += sizeof(uint64_t);

        i = strlen(args_fmt);

        // pop arguments from stack and copy them to args array

        while (i > 0)
        {
          pop(args[i - 1]);
          i--;
        }

        pop(r2);

        function = UINT64_TO_PTR(YR_OBJECT_FUNCTION*, r2);
        result = ERROR_INTERNAL_FATAL_ERROR;

        for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
        {
          if (function->prototypes[i].arguments_fmt == NULL)
            break;

          if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0)
          {
            result = function->prototypes[i].code(
                (void*) args,
                context,
                function);

            break;
          }
        }

        assert(i < MAX_OVERLOADED_FUNCTIONS);

        if (result == ERROR_SUCCESS)
          push(PTR_TO_UINT64(function->return_obj));
        else
          return result;

        break;

      case OP_STR_FOUND:
        pop(r1);
        string = UINT64_TO_PTR(YR_STRING*, r1);
        push(string->matches[tidx].tail != NULL ? 1 : 0);
        break;

      case OP_STR_FOUND_AT:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1))
        {
          push(0);
          break;
        }

        string = UINT64_TO_PTR(YR_STRING*, r2);
        match = string->matches[tidx].head;
        found = 0;

        while (match != NULL)
        {
          if (r1 == match->base + match->offset)
          {
            push(1);
            found = 1;
            break;
          }

          if (r1 < match->base + match->offset)
            break;

          match = match->next;
        }

        if (!found)
          push(0);

        break;

      case OP_STR_FOUND_IN:
        pop(r3);
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
        {
          push(UNDEFINED);
          break;
        }

        string = UINT64_TO_PTR(YR_STRING*, r3);
        match = string->matches[tidx].head;
        found = FALSE;

        while (match != NULL && !found)
        {
          if (match->base + match->offset >= r1 &&
              match->base + match->offset <= r2)
          {
            push(1);
            found = TRUE;
          }

          if (match->base + match->offset > r2)
            break;

          match = match->next;
        }

        if (!found)
          push(0);

        break;

      case OP_STR_COUNT:
        pop(r1);
        string = UINT64_TO_PTR(YR_STRING*, r1);
        push(string->matches[tidx].count);
        break;

      case OP_STR_OFFSET:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1))
        {
          push(UNDEFINED);
          break;
        }

        string = UINT64_TO_PTR(YR_STRING*, r2);
        match = string->matches[tidx].head;
        i = 1;
        found = FALSE;

        while (match != NULL && !found)
        {
          if (r1 == i)
          {
            push(match->base + match->offset);
            found = TRUE;
          }

          i++;
          match = match->next;
        }

        if (!found)
          push(UNDEFINED);

        break;

      case OP_OF:
        found = 0;
        count = 0;
        pop(r1);

        while (r1 != UNDEFINED)
        {
          string = UINT64_TO_PTR(YR_STRING*, r1);
          if (string->matches[tidx].tail != NULL)
            found++;
          count++;
          pop(r1);
        }

        pop(r2);

        if (r2 != UNDEFINED)
          push(found >= r2 ? 1 : 0);
        else
          push(found >= count ? 1 : 0);

        break;

      case OP_FILESIZE:
        push(context->file_size);
        break;

      case OP_ENTRYPOINT:
        push(context->entry_point);
        break;

      case OP_INT8:
        pop(r1);
        push(read_int8_t(context->mem_block, r1));
        break;

      case OP_INT16:
        pop(r1);
        push(read_int16_t(context->mem_block, r1));
        break;

      case OP_INT32:
        pop(r1);
        push(read_int32_t(context->mem_block, r1));
        break;

      case OP_UINT8:
        pop(r1);
        push(read_uint8_t(context->mem_block, r1));
        break;

      case OP_UINT16:
        pop(r1);
        push(read_uint16_t(context->mem_block, r1));
        break;

      case OP_UINT32:
        pop(r1);
        push(read_uint32_t(context->mem_block, r1));
        break;

      case OP_CONTAINS:
        pop(r2);
        pop(r1);

        if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2))
          push(UNDEFINED);
        else
          push(strstr(UINT64_TO_PTR(char*, r1),
                      UINT64_TO_PTR(char*, r2)) != NULL);
        break;

      case OP_IMPORT:
        r1 = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);

        FAIL_ON_ERROR(yr_modules_load(
            UINT64_TO_PTR(char*, r1),
            context));

        break;

      case OP_MATCHES:
        pop(r2);
        pop(r1);

        count = strlen(UINT64_TO_PTR(char*, r1));

        if (count == 0)
        {
          push(FALSE);
          break;
        }

        result = yr_re_exec(
          UINT64_TO_PTR(uint8_t*, r2),
          UINT64_TO_PTR(uint8_t*, r1),
          count,
          RE_FLAGS_SCAN,
          NULL,
          NULL);

        push(result >= 0);
        break;

      default:
        // Unknown instruction, this shouldn't happen.
        assert(FALSE);
    }

    if (timeout > 0)  // timeout == 0 means no timeout
    {
      // Check for timeout every 10 instruction cycles.

      if (++cycle == 10)
      {
        if (difftime(time(NULL), start_time) > timeout)
          return ERROR_SCAN_TIMEOUT;

        cycle = 0;
      }
    }

    ip++;
  }

  // After executing the code the stack should be empty.
  assert(sp == 0);

  return ERROR_SUCCESS;
}
Ejemplo n.º 8
0
int yr_modules_load(
    const char* module_name,
    YR_SCAN_CONTEXT* context)
{
  YR_MODULE_IMPORT mi;
  YR_OBJECT* module_structure;

  int result;
  int i;

  module_structure = (YR_OBJECT*) yr_hash_table_lookup(
      context->objects_table,
      module_name,
      NULL);

  // if module_structure != NULL, the module was already
  // loaded, return successfully without doing nothing.

  if (module_structure != NULL)
    return ERROR_SUCCESS;

  // not loaded yet

  FAIL_ON_ERROR(yr_object_create(
      OBJECT_TYPE_STRUCTURE,
      module_name,
      NULL,
      &module_structure));

  yr_hash_table_add(
      context->objects_table,
      module_name,
      NULL,
      module_structure);

  mi.module_name = module_name;
  mi.module_data = NULL;
  mi.module_data_size = 0;

  result = context->callback(
      CALLBACK_MSG_IMPORT_MODULE,
      &mi,
      context->user_data);

  if (result == CALLBACK_ERROR)
    return ERROR_CALLBACK_ERROR;

  yr_modules_do_declarations(
        module_name,
        module_structure);

  for (i = 0; i < sizeof(yr_modules_table) / sizeof(YR_MODULE); i++)
  {
    if (strcmp(yr_modules_table[i].name, module_name) == 0)
    {
      result = yr_modules_table[i].load(
          context,
          module_structure,
          mi.module_data,
          mi.module_data_size);

      if (result == ERROR_SUCCESS)
        yr_modules_table[i].is_loaded |= 1 << yr_get_tidx();
    }
  }

  return ERROR_SUCCESS;
}