Esempio n. 1
0
int yr_parser_reduce_external(
  yyscan_t yyscanner,
  const char* identifier,
  int8_t instruction)
{
  YR_COMPILER* compiler = yyget_extra(yyscanner);
  YR_EXTERNAL_VARIABLE* external;

  external = yr_parser_lookup_external_variable(yyscanner, identifier);

  if (external != NULL)
  {
    if (instruction == EXT_BOOL)
    {
      compiler->last_result = yr_parser_emit_with_arg_reloc(
          yyscanner,
          EXT_BOOL,
          PTR_TO_UINT64(external),
          NULL);
    }
    else if (instruction == EXT_INT &&
             external->type == EXTERNAL_VARIABLE_TYPE_INTEGER)
    {
      compiler->last_result = yr_parser_emit_with_arg_reloc(
          yyscanner,
          EXT_INT,
          PTR_TO_UINT64(external),
          NULL);
    }
    else if (instruction == EXT_STR &&
             external->type == EXTERNAL_VARIABLE_TYPE_FIXED_STRING)
    {
      compiler->last_result = yr_parser_emit_with_arg_reloc(
          yyscanner,
          EXT_STR,
          PTR_TO_UINT64(external),
          NULL);
    }
    else
    {
      yr_compiler_set_error_extra_info(compiler, external->identifier);
      compiler->last_result = ERROR_INCORRECT_VARIABLE_TYPE;
    }
  }

  return compiler->last_result;
}
Esempio n. 2
0
int yr_parser_emit_pushes_for_strings(
    yyscan_t yyscanner,
    const char* identifier)
{
  YR_COMPILER* compiler = yyget_extra(yyscanner);
  YR_STRING* string = compiler->current_rule_strings;

  const char* string_identifier;
  const char* target_identifier;

  int matching = 0;

  while(!STRING_IS_NULL(string))
  {
    // Don't generate pushes for strings chained to another one, we are
    // only interested in non-chained strings or the head of the chain.

    if (string->chained_to == NULL)
    {
      string_identifier = string->identifier;
      target_identifier = identifier;

      while (*target_identifier != '\0' &&
             *string_identifier != '\0' &&
             *target_identifier == *string_identifier)
      {
        target_identifier++;
        string_identifier++;
      }

      if ((*target_identifier == '\0' && *string_identifier == '\0') ||
           *target_identifier == '*')
      {
        yr_parser_emit_with_arg_reloc(
            yyscanner,
            PUSH,
            PTR_TO_UINT64(string),
            NULL);

        string->g_flags |= STRING_GFLAGS_REFERENCED;
        matching++;
      }
    }

    string = yr_arena_next_address(
        compiler->strings_arena,
        string,
        sizeof(YR_STRING));
  }

  if (matching == 0)
  {
    yr_compiler_set_error_extra_info(compiler, identifier);
    compiler->last_result = ERROR_UNDEFINED_STRING;
  }

  return compiler->last_result;
}
Esempio n. 3
0
void *
grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size,
			       int *handle, int type, int flags)
{
  void *ret;

  if (flags & (GRUB_MMAP_MALLOC_LOW | GRUB_MMAP_MALLOC_HIGH))
    {
      struct grub_mmap_malign_and_register_closure c;

      c.align = align;
      c.size = size;
      c.highestlow = 0;
      if (flags & GRUB_MMAP_MALLOC_LOW)
	{
	  c.min = 0;
	  c.max = 0x100000;
	}
      else
	{
	  c.min = grub_mmap_high;
	  c.max = 0x100000000ll;
	}
      /* FIXME: use low-memory mm allocation once it's available. */
      grub_mmap_iterate (find_hook, &c);
      ret = UINT_TO_PTR (c.highestlow);
    }
  else
    ret = grub_memalign (align, size);

  if (! ret)
    {
      *handle = 0;
      return 0;
    }

  *handle = grub_mmap_register (PTR_TO_UINT64 (ret), size, type);
  if (! *handle)
    {
      grub_free (ret);
      return 0;
    }

  return ret;
}
Esempio n. 4
0
void yr_parser_emit_pushes_for_strings(
    yyscan_t yyscanner,
    const char* identifier)
{
  YR_COMPILER* compiler = yyget_extra(yyscanner);
  YR_STRING* string = compiler->current_rule_strings;
  const char* string_identifier;
  const char* target_identifier;

  while(!STRING_IS_NULL(string))
  {
    string_identifier = string->identifier;
    target_identifier = identifier;

    while (*target_identifier != '\0' &&
           *string_identifier != '\0' &&
           *target_identifier == *string_identifier)
    {
      target_identifier++;
      string_identifier++;
    }

    if ((*target_identifier == '\0' && *string_identifier == '\0') ||
         *target_identifier == '*')
    {
      yr_parser_emit_with_arg_reloc(
          yyscanner,
          PUSH,
          PTR_TO_UINT64(string),
          NULL);

      string->g_flags |= STRING_GFLAGS_REFERENCED;
    }

    string = yr_arena_next_address(
        compiler->strings_arena,
        string,
        sizeof(YR_STRING));
  }
}
Esempio n. 5
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;
}
Esempio n. 6
0
int yr_parser_reduce_string_identifier(
    yyscan_t yyscanner,
    const char* identifier,
    int8_t instruction)
{
  YR_STRING* string;
  YR_COMPILER* compiler = yyget_extra(yyscanner);

  if (strcmp(identifier, "$") == 0)
  {
    if (compiler->loop_depth > 0)
    {
      yr_parser_emit_with_arg(
          yyscanner,
          PUSH_M,
          LOOP_LOCAL_VARS * (compiler->loop_depth - 1),
          NULL);

      yr_parser_emit(yyscanner, instruction, NULL);

      if (instruction != SFOUND)
      {
        string = compiler->current_rule_strings;

        while(!STRING_IS_NULL(string))
        {
          string->g_flags &= ~STRING_GFLAGS_SINGLE_MATCH;
          string = yr_arena_next_address(
              compiler->strings_arena,
              string,
              sizeof(YR_STRING));
        }
      }
    }
    else
    {
      compiler->last_result = ERROR_MISPLACED_ANONYMOUS_STRING;
    }
  }
  else
  {
    string = yr_parser_lookup_string(yyscanner, identifier);

    if (string != NULL)
    {
      yr_parser_emit_with_arg_reloc(
          yyscanner,
          PUSH,
          PTR_TO_UINT64(string),
          NULL);

      if (instruction != SFOUND)
        string->g_flags &= ~STRING_GFLAGS_SINGLE_MATCH;

      yr_parser_emit(yyscanner, instruction, NULL);

      string->g_flags |= STRING_GFLAGS_REFERENCED;
    }
  }

  return compiler->last_result;
}
Esempio n. 7
0
int yr_parser_reduce_rule_declaration(
    yyscan_t yyscanner,
    int32_t flags,
    const char* identifier,
    char* tags,
    YR_STRING* strings,
    YR_META* metas)
{
  YR_COMPILER* compiler = yyget_extra(yyscanner);
  YR_RULE* rule;
  YR_STRING* string;

  if (yr_hash_table_lookup(
        compiler->rules_table,
        identifier,
        compiler->current_namespace->name) != NULL)
  {
    // A rule with the same identifier already exists, return the
    // appropriate error.

    yr_compiler_set_error_extra_info(compiler, identifier);
    compiler->last_result = ERROR_DUPLICATE_RULE_IDENTIFIER;
    return compiler->last_result;
  }

  // Check for unreferenced (unused) strings.

  string = compiler->current_rule_strings;

  while(!STRING_IS_NULL(string))
  {
    // Only the heading fragment in a chain of strings (the one with
    // chained_to == NULL) must be referenced. All other fragments
    // are never marked as referenced.

    if (!STRING_IS_REFERENCED(string) &&
        string->chained_to == NULL)
    {
      yr_compiler_set_error_extra_info(compiler, string->identifier);
      compiler->last_result = ERROR_UNREFERENCED_STRING;
      break;
    }

    string = yr_arena_next_address(
        compiler->strings_arena,
        string,
        sizeof(YR_STRING));
  }

  if (compiler->last_result != ERROR_SUCCESS)
    return compiler->last_result;

  compiler->last_result = yr_arena_allocate_struct(
      compiler->rules_arena,
      sizeof(YR_RULE),
      (void**) &rule,
      offsetof(YR_RULE, identifier),
      offsetof(YR_RULE, tags),
      offsetof(YR_RULE, strings),
      offsetof(YR_RULE, metas),
      offsetof(YR_RULE, ns),
      EOL);

  if (compiler->last_result != ERROR_SUCCESS)
    return compiler->last_result;

  compiler->last_result = yr_arena_write_string(
      compiler->sz_arena,
      identifier,
      &rule->identifier);

  if (compiler->last_result != ERROR_SUCCESS)
    return compiler->last_result;

  compiler->last_result = yr_parser_emit_with_arg_reloc(
      yyscanner,
      RULE_POP,
      PTR_TO_UINT64(rule),
      NULL);

  if (compiler->last_result != ERROR_SUCCESS)
    return compiler->last_result;

  rule->g_flags = flags | compiler->current_rule_flags;
  rule->tags = tags;
  rule->strings = strings;
  rule->metas = metas;
  rule->ns = compiler->current_namespace;

  compiler->current_rule_flags = 0;
  compiler->current_rule_strings = NULL;

  yr_hash_table_add(
      compiler->rules_table,
      identifier,
      compiler->current_namespace->name,
      (void*) rule);

  return compiler->last_result;
}
Esempio n. 8
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;
}
Esempio n. 9
0
/* Write value (pointer to memory PLUS_HANDLE)
   - (pointer to memory MINUS_HANDLE) + VALUE to ADDR assuming that the
   size SIZE bytes. If PTV_NEEDED is 1 then announce it to runtime that this
   value needs to be recomputed before going to virtual mode
*/
grub_err_t
grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
			 int minus_handle, int ptv_needed, int size)
{
  /* Announce relocator to runtime */
  if (ptv_needed)
    {
      struct grub_efiemu_ptv_rel *ptv_rels
	= grub_efiemu_mm_obtain_request (ptv_handle);

      if (ptv_needed && ptv_written >= ptv_alloc)
	return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			   "your module didn't declare efiemu "
			   " relocators correctly");

      if (minus_handle)
	ptv_rels[ptv_written].minustype
	  = grub_efiemu_mm_get_type (minus_handle);
      else
	ptv_rels[ptv_written].minustype = 0;

      if (plus_handle)
	ptv_rels[ptv_written].plustype
	  = grub_efiemu_mm_get_type (plus_handle);
      else
	ptv_rels[ptv_written].plustype = 0;

      ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr);
      ptv_rels[ptv_written].size = size;
      ptv_written++;

      /* memset next value to zero to mark the end */
      grub_memset (&ptv_rels[ptv_written], 0, sizeof (ptv_rels[ptv_written]));
    }

  /* Compute the value */
  if (minus_handle)
    value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle));

  if (plus_handle)
    value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle));

  /* Write the value */
  switch (size)
    {
    case 8:
      *((grub_uint64_t *) addr) = value;
      break;
    case 4:
      *((grub_uint32_t *) addr) = value;
      break;
    case 2:
      *((grub_uint16_t *) addr) = value;
      break;
    case 1:
      *((grub_uint8_t *) addr) = value;
      break;
    default:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "wrong symbol size");
    }

  return GRUB_ERR_NONE;
}
Esempio n. 10
0
/* Really allocate the memory */
static grub_err_t
efiemu_alloc_requests (void)
{
  grub_size_t align_overhead = 0;
  grub_uint8_t *curptr, *typestart;
  struct grub_efiemu_memrequest *cur;
  grub_size_t total_alloc = 0;
  unsigned i;
  /* Order of memory regions */
  grub_efi_memory_type_t reqorder[] =
    {
      /* First come regions usable by OS*/
      GRUB_EFI_LOADER_CODE,
      GRUB_EFI_LOADER_DATA,
      GRUB_EFI_BOOT_SERVICES_CODE,
      GRUB_EFI_BOOT_SERVICES_DATA,
      GRUB_EFI_CONVENTIONAL_MEMORY,
      GRUB_EFI_ACPI_RECLAIM_MEMORY,

      /* Then memory used by runtime */
      /* This way all our regions are in a single block */
      GRUB_EFI_RUNTIME_SERVICES_CODE,
      GRUB_EFI_RUNTIME_SERVICES_DATA,
      GRUB_EFI_ACPI_MEMORY_NVS,

      /* And then unavailable memory types. This is more for a completeness.
	 You should double think before allocating memory of any of these types
       */
      GRUB_EFI_UNUSABLE_MEMORY,
      GRUB_EFI_MEMORY_MAPPED_IO,
      GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
      GRUB_EFI_PAL_CODE
    };

  /* Compute total memory needed */
  for (i = 0; i < sizeof (reqorder) / sizeof (reqorder[0]); i++)
    {
      align_overhead = GRUB_EFIEMU_PAGESIZE
	- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
      if (align_overhead == GRUB_EFIEMU_PAGESIZE)
	align_overhead = 0;
      total_alloc += requested_memory[reqorder[i]] + align_overhead;
    }

  /* Allocate the whole memory in one block */
  resident_memory = grub_memalign (GRUB_EFIEMU_PAGESIZE, total_alloc);
  if (!resident_memory)
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
		       "couldn't allocate resident memory");

  /* Split the memory into blocks by type */
  curptr = resident_memory;
  for (i = 0; i < sizeof (reqorder) / sizeof (reqorder[0]); i++)
    {
      if (!requested_memory[reqorder[i]])
	continue;
      typestart = curptr;

      /* Write pointers to requests */
      for (cur = memrequests; cur; cur = cur->next)
	if (cur->type == reqorder[i])
	  {
	    curptr = ((grub_uint8_t *)curptr) + cur->align_overhead;
	    cur->val = curptr;
	    curptr = ((grub_uint8_t *)curptr) + cur->size;
	  }

      /* Ensure that the regions are page-aligned */
      align_overhead = GRUB_EFIEMU_PAGESIZE
	- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
      if (align_overhead == GRUB_EFIEMU_PAGESIZE)
	align_overhead = 0;
      curptr = ((grub_uint8_t *)curptr) + align_overhead;

      /* Add the region to memory map */
      grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart),
			       curptr - typestart, reqorder[i]);
    }

  return GRUB_ERR_NONE;
}