예제 #1
0
    def _handle_func_decls(self, tokens):
        """
        Look for functions/subs declared anywhere, including inside the body 
        of other functions/subs.
        """

        # Look through each parsed item in the module for function/sub
        # definitions.
        for token in tokens:
            if (not hasattr(token, "accept")):
                continue
            func_visitor = function_defn_visitor()
            token.accept(func_visitor)
            for i in func_visitor.func_objects:

                # Sub to add?
                if isinstance(i, Sub):
                    if (log.getEffectiveLevel() == logging.DEBUG):
                        log.debug("saving sub decl: %r" % i.name)
                    self.subs[i.name] = i

                # Func to add?
                elif isinstance(i, Function):
                    if (log.getEffectiveLevel() == logging.DEBUG):
                        log.debug("saving func decl: %r" % i.name)
                    self.functions[i.name] = i
예제 #2
0
    def eval(self, context, params=None):

        # Perform all of the const assignments first.
        for block in self.loose_lines:
            if (isinstance(block, Sub) or isinstance(block, Function)
                    or isinstance(block, External_Function)):
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Skip loose line const eval of " + str(block))
                continue
            if (isinstance(block, LooseLines)):
                context.global_scope = True
                do_const_assignments(block.block, context)
                context.global_scope = False

        # Emulate the loose line blocks (statements that appear outside sub/func
        # defs) in order.
        done_emulation = False
        for block in self.loose_lines:
            if (isinstance(block, Sub) or isinstance(block, Function)
                    or isinstance(block, External_Function)):
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Skip loose line eval of " + str(block))
                continue
            context.global_scope = True
            block.eval(context, params)
            context.global_scope = False
            done_emulation = True

        # Return if we ran anything.
        return done_emulation
예제 #3
0
 def add_compiled_module(self, m):
     """
     Add an already parsed and processed module.
     """
     if (m is None):
         return
     self.modules.append(m)
     for name, _sub in m.subs.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing sub "%s" in globals' % name)
         self.globals[name.lower()] = _sub
         self.globals[name] = _sub
     for name, _function in m.functions.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing function "%s" in globals' % name)
         self.globals[name.lower()] = _function
         self.globals[name] = _function
     for name, _function in m.external_functions.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing external function "%s" in globals' %
                       name)
         self.globals[name.lower()] = _function
         self.externals[name.lower()] = _function
     for name, _var in m.global_vars.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing global var "%s" = %s in globals (1)' %
                       (name, str(_var)))
         if (isinstance(name, str)):
             self.globals[name.lower()] = _var
         if (isinstance(name, list)):
             self.globals[name[0].lower()] = _var
             self.types[name[0].lower()] = name[1]
예제 #4
0
def set_cached_value(arg, val):
    """Set the cached value of an all constant numeric expression.

    @param arg (VBA_Object object) The unresolved expression to
    cache. 

    @param val (int, float, complex) The value of the resolved
    expression.

    """

    # We should be setting this to a numeric expression
    if ((not isinstance(val, int)) and (not isinstance(val, float))
            and (not isinstance(val, complex))):
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.warning("Expression '" + safe_str_convert(val) + "' is a " +
                        safe_str_convert(type(val)) +
                        ", not an int. Not caching.")
        return

    # Don't cache things that contain Excel sheets or workbooks.
    if contains_excel(arg):
        return

    # We have a number. Cache it.
    arg_str = safe_str_convert(arg)
    try:
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Cache value of " + arg_str + " = " +
                      safe_str_convert(val))
    except UnicodeEncodeError:
        pass
    constant_expr_cache[arg_str] = val
예제 #5
0
    def load_context(self, context):
        """
        Load functions/subs defined in the module into the given
        context.
        """

        for name, _sub in self.subs.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing sub "%s" in globals' % name)
            context.set(name, _sub)
            context.set(name, _sub, force_global=True)
        for name, _function in self.functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing function "%s" in globals' % name)
            context.set(name, _function)
            context.set(name, _function, force_global=True)
        for name, _function in self.external_functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing external function "%s" in globals' %
                          name)
            context.set(name, _function)
        for name, _var in self.global_vars.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing global var "%s" = %s in globals (1)' %
                          (name, str(_var)))
            if (isinstance(name, str)):
                context.set(name, _var)
                context.set(name, _var, force_global=True)
            if (isinstance(name, list)):
                context.set(name[0], _var, var_type=name[1])
                context.set(name[0], _var, var_type=name[1], force_global=True)
예제 #6
0
def _handle_selected_item_read(arg, context, got_constant_math):
    """Handle reads of the selectedItem field of an object.

    @param arg (VBA_Object object) The item being evaluated.

    @param context (Context object) The current program state.
    
    @param got_constant_math (boolean) If True the given arg is an all
    numeric literal expression, if False it is not.
    
    @return (??) On success the evaluated item is returned, None is
    returned on error.
    """

    # This is a hack to get values saved in the .rapt.Value field of objects.
    if (".selecteditem" in arg.lower()):
        try:
            tmp = arg.lower().replace(".selecteditem", ".rapt.value")
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("eval_arg: Try to get as " + tmp + "...")
            val = context.get(tmp)
            if got_constant_math: set_cached_value(arg, val)
            return val

        except KeyError:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("eval_arg: Not found as .rapt.value.")

    # Not handled.
    return None
예제 #7
0
    def add_compiled_module(self, m, stream):
        """Add an already parsed and processed module.

        @param m (Module object) The parsed object.

        @param stream (str) The OLE stream name containing the module.

        """
        if (m is None):
            return
        self.modules.append(m)
        for name, _sub in m.subs.items():

            # Append the stream name for duplicate subs
            if (name in self.globals):
                new_name = safe_str_convert(stream) + "::" + safe_str_convert(
                    name)
                log.warn("Renaming duplicate function " + name + " to " +
                         new_name)
                name = new_name

            # Save the sub.
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing sub "%s" in globals' % name)
            self.globals[name.lower()] = _sub
            self.globals[name] = _sub

        # Functions.
        for name, _function in m.functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing function "%s" in globals' % name)
            self.globals[name.lower()] = _function
            self.globals[name] = _function

        # Properties.
        for name, _prop in m.functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing property let "%s" in globals' % name)
            self.globals[name.lower()] = _prop
            self.globals[name] = _prop

        # External DLL functions.
        for name, _function in m.external_functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing external function "%s" in globals' %
                          name)
            self.globals[name.lower()] = _function
            self.externals[name.lower()] = _function

        # Global variables.
        for name, _var in m.global_vars.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing global var "%s" = %s in globals (1)' %
                          (name, safe_str_convert(_var)))
            if (isinstance(name, str)):
                self.globals[name.lower()] = _var
            if (isinstance(name, list)):
                self.globals[name[0].lower()] = _var
                self.types[name[0].lower()] = name[1]
예제 #8
0
 def parse_next_line(self):
     # extract next line
     line = self.lines.pop(0)
     if (log.getEffectiveLevel() == logging.DEBUG):
         log.debug('Parsing line %d: %s' % (self.line_index, line.rstrip()))
     self.line_index += 1
     # extract first two keywords in lowercase, for quick matching
     line_keywords = line.lower().split(None, 2)
     if (log.getEffectiveLevel() == logging.DEBUG):
         log.debug('line_keywords: %r' % line_keywords)
     # ignore empty lines
     if len(line_keywords) == 0 or line_keywords[0].startswith("'"):
         return self.line_index - 1, line, None
     return self.line_index - 1, line, line_keywords
예제 #9
0
    def eval(self, context, params=None):
        # NOTE: in the specification, the parameter is expected to be an integer
        # But in reality, VBA accepts a string containing the representation
        # of an integer in decimal, hexadecimal or octal form.
        # It also ignores leading and trailing spaces.
        # Examples: Chr("65"), Chr("&65 "), Chr(" &o65"), Chr("  &H65")
        # => need to parse the string as integer
        # It also looks like floating point numbers are allowed.
        # First, eval the argument:
        param = eval_arg(self.arg, context)

        # Get the ordinal value.
        if isinstance(param, basestring):
            try:
                param = integer.parseString(param.strip())[0]
            except:
                log.error("%r is not a valid chr() value. Returning ''." % param)
                return ''            
        elif isinstance(param, float):
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('Chr: converting float %r to integer' % param)
            try:
                param = int(round(param))
            except:
                log.error("%r is not a valid chr() value. Returning ''." % param)
                return ''
        elif isinstance(param, int):
            pass
        else:
            log.error('Chr: parameter must be an integer or a string, not %s' % type(param))
            return ''
            
        # Figure out whether to create a unicode or ascii character.
        converter = chr
        if (param < 0):
            param = param * -1
        if (param > 255):
            converter = unichr
            
        # Do the conversion.
        try:
            r = converter(param)
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Chr(" + str(param) + ") = " + r)
            return r
        except Exception as e:
            log.error(str(e))
            log.error("%r is not a valid chr() value. Returning ''." % param)
            return ""
예제 #10
0
    def eval(self, context, params=None):

        # Exit if an exit function statement was previously called.
        #if (context.exit_func):
        #    return

        # Assign all const variables first.
        do_const_assignments(self.block, context)

        # Emulate the statements in the block.
        log.info("Emulating " + str(self) + " ...")
        context.global_scope = True
        for curr_statement in self.block:

            # Don't emulate declared functions.
            if (isinstance(curr_statement, Sub)
                    or isinstance(curr_statement, Function)
                    or isinstance(curr_statement, External_Function)):
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Skip loose line eval of " + str(curr_statement))
                continue

            # Is this something we can emulate?
            if (not isinstance(curr_statement, VBA_Object)):
                continue
            curr_statement.eval(context, params=params)

            # Was there an error that will make us jump to an error handler?
            if (context.must_handle_error()):
                break
            context.clear_error()

        # Run the error handler if we have one and we broke out of the statement
        # loop with an error.
        context.handle_error(params)
예제 #11
0
def _read_from_excel(arg, context):
    """Try to evaluate an argument by reading from the loaded Excel
    spreadsheet.

    @param arg (VBA_Object object) The argument to evaluate.

    @param context (Context object) The current program state.
    
    @return (any) The result of the evaluation on success, None on
    failure.

    """

    # Try handling reading value from an Excel spreadsheet cell.
    # ThisWorkbook.Sheets('YHRPN').Range('J106').Value
    if ("MemberAccessExpression" not in safe_str_convert(type(arg))):
        return None
    arg_str = safe_str_convert(arg)
    if (("sheets(" in arg_str.lower()) and (("range(" in arg_str.lower()) or
                                            ("cells(" in arg_str.lower()))):

        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Try as Excel cell read...")

        return arg.eval(context)

    # Not handled.
    return None
예제 #12
0
 def __init__(self, original_str, location, tokens):
     super(Concatenation, self).__init__(original_str, location, tokens)
     # extract argument from the tokens:
     # expected to be a tuple containing a list [a,'&',b,'&',c,...]
     self.arg = tokens[0][::2]
     if (log.getEffectiveLevel() == logging.DEBUG):
         log.debug('Concatenation: self.arg=%s' % repr(self.arg))
예제 #13
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the floor division of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute floor div " + str(self.arg))
            return reduce(lambda x, y: x // y,
                          coerce_args(evaluated_args, preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: int(x) // int(y), evaluated_args)
            except Exception as e:
                if (str(e).strip() != "division by zero"):
                    log.error(
                        'Impossible to divide arguments of different types. ' +
                        str(e))
                # TODO
                return 0
        except ZeroDivisionError as e:
            context.set_error(str(e))
예제 #14
0
def _handle_shapes_access(r, arg, context, got_constant_math):
    """Finish handling a partially handled Shapes() access.

    @param arg (VBA_Object object) The item being evaluated.

    @param context (Context object) The current program state.
    
    @param got_constant_math (boolean) If True the given arg is an all
    numeric literal expression, if False it is not.
    
    @return (??) On success the evaluated item is returned, None is
    returned on error.

    """

    # Is this a Shapes() access that still needs to be handled?
    poss_shape_txt = ""
    if isinstance(r, (VBA_Object, str)):
        poss_shape_txt = safe_str_convert(r)
    if ((poss_shape_txt.startswith("Shapes("))
            or (poss_shape_txt.startswith("InlineShapes("))):
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("eval_arg: Handling intermediate Shapes() access for " +
                      safe_str_convert(r))
        r = eval_arg(r, context)
        if got_constant_math: set_cached_value(arg, r)
        return r

    # Not handled.
    return None
예제 #15
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the exponentiation of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute pow " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: pow(x, y),
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: pow(int(x), int(y)), evaluated_args)
            except Exception as e:
                log.error(
                    'Impossible to do exponentiation with arguments of different types. '
                    + safe_str_convert(e))
                return 0
예제 #16
0
def load_excel_xlrd(data):
    """Read in an Excel file into an ExceBook object directly with the
    xlrd Excel library.

    @param data (str) The Excel file contents.

    @return (core.excel.ExceBook object) On success return the Excel
    spreadsheet as an ExcelBook object. Returns None on error.

    """

    # Only use this on Office 97 Excel files.
    if (not filetype.is_office97_file(data, True)):
        log.warning("File is not an Excel 97 file. Not reading with xlrd2.")
        return None

    # It is Office 97. See if we can read it with xlrd2.
    try:
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Trying to load with xlrd...")
        r = xlrd.open_workbook(file_contents=data)
        return r
    except Exception as e:
        log.error("Reading in file as Excel with xlrd failed. " + str(e))
        return None
예제 #17
0
 def __init__(self, original_str, location, tokens):
     super(Chr, self).__init__(original_str, location, tokens)
     # extract argument from the tokens:
     # Here the arg is expected to be either an int or a VBA_Object
     self.arg = tokens[0]
     if (log.getEffectiveLevel() == logging.DEBUG):
         log.debug('parsed %r as %s' % (self, self.__class__.__name__))
예제 #18
0
def get_metadata_exif(filename):

    # Use exiftool to get the document metadata.
    output = None
    try:
        output = subprocess.check_output(["exiftool", filename])
    except Exception as e:
        log.error("Cannot read metadata with exiftool. " + str(e))
        return {}

    # Sanity check results.
    if (log.getEffectiveLevel() == logging.DEBUG):
        log.debug("exiftool output: '" + str(output) + "'")
    if (":" not in output):
        log.warning("Cannot read metadata with exiftool.")
        return {}

    # Store the metadata in an object.
    lines = output.split("\n")
    r = FakeMeta()
    for line in lines:
        line = line.strip()
        if ((len(line) == 0) or (":" not in line)):
            continue
        field = line[:line.index(":")].strip().lower()
        val = line[line.index(":") + 1:].strip().replace("...", "\r\n")
        setattr(r, field, val)

    # Done.
    return r
예제 #19
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the and of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute or " + str(self.arg))
            return reduce(lambda x, y: x | y,
                          coerce_args(evaluated_args, preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: int(x) | int(y), evaluated_args)
            except:
                log.error('Impossible to or arguments of different types.')
                return 0
        except RuntimeError as e:
            log.error("overflow trying eval or: %r" % self.arg)
            raise e
예제 #20
0
 def eval(self, context, params=None):
     # return the environment variable name surrounded by % signs:
     # e.g. Environ("TEMP") => "%TEMP%"
     arg = eval_arg(self.arg, context=context)
     value = '%%%s%%' % arg
     if (log.getEffectiveLevel() == logging.DEBUG):
         log.debug('evaluating Environ(%s) => %r' % (arg, value))
     return value
예제 #21
0
 def add_compiled_module(self, m):
     """
     Add an already parsed and processed module.
     """
     if (m is None):
         return
     self.modules.append(m)
     for name, _sub in m.subs.items():
         # Skip duplicate subs that look less interesting than the old one.
         if (name in self.globals):
             old_sub = self.globals[name]
             if (hasattr(old_sub, "statements")):
                 if (len(_sub.statements) < len(old_sub.statements)):
                     log.warning(
                         "Sub " + str(name) +
                         " is already defined. Skipping new definition.")
                     continue
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing sub "%s" in globals' % name)
         self.globals[name.lower()] = _sub
         self.globals[name] = _sub
     for name, _function in m.functions.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing function "%s" in globals' % name)
         self.globals[name.lower()] = _function
         self.globals[name] = _function
     for name, _prop in m.functions.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing property let "%s" in globals' % name)
         self.globals[name.lower()] = _prop
         self.globals[name] = _prop
     for name, _function in m.external_functions.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing external function "%s" in globals' %
                       name)
         self.globals[name.lower()] = _function
         self.externals[name.lower()] = _function
     for name, _var in m.global_vars.items():
         if (log.getEffectiveLevel() == logging.DEBUG):
             log.debug('(1) storing global var "%s" = %s in globals (1)' %
                       (name, str(_var)))
         if (isinstance(name, str)):
             self.globals[name.lower()] = _var
         if (isinstance(name, list)):
             self.globals[name[0].lower()] = _var
             self.types[name[0].lower()] = name[1]
예제 #22
0
    def eval(self, context, params=None):
        """
        Evaluate the current value of the object.

        :param context: Context for the evaluation (local and global variables)
        :return: current value of the object
        """
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug(self)
예제 #23
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the sum of all the arguments:
        # (Note: sum() is not applicable here, because it does not work for strings)
        # see https://docs.python.org/2/library/functions.html#reduce
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute sum (1) " + safe_str_convert(self.arg))
            r = reduce(
                lambda x, y: x + y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
            return r
        except (TypeError, ValueError):
            # NOTE: In VB you are not supposed to be able to add integers and strings.
            # However, there are maldocs that do this. If the strings are integer strings,
            # integer addition is performed.
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug(
                    'Impossible to sum arguments of different types. Try converting strings to common type.'
                )
            try:
                r = reduce(lambda x, y: int(x) + int(y), evaluated_args)
                return r
            except (TypeError, ValueError):
                # Punt and sum all arguments as strings.
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Compute sum (2) " + safe_str_convert(self.arg))
                r = reduce(
                    lambda x, y: safe_str_convert(x) + safe_str_convert(y),
                    vba_conversion.coerce_args_to_str(evaluated_args))
                return r
        except RuntimeError as e:
            log.error("overflow trying eval sum: %r" % self.arg)
            raise e
예제 #24
0
def set_cached_value(arg, val):
    """
    Set the cached value of an all constant numeric expression.
    """

    # We should be setting this to a numeric expression
    if ((not isinstance(val, int)) and
        (not isinstance(val, float)) and
        (not isinstance(val, complex))):
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.warning("Expression '" + str(val) + "' is a " + str(type(val)) + ", not an int. Not caching.")
        return

    # We have a number. Cache it.
    arg_str = str(arg)
    try:
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Cache value of " + arg_str + " = " + str(val))
    except UnicodeEncodeError:
        pass
    constant_expr_cache[arg_str] = val
예제 #25
0
    def load_context(self, context):
        """Load functions/subs defined in the module into the given
        context. The function/sub names will be associated with the
        function/sub definitions in the context.

        @param context (VBA_Context object) The context in which to
        load the functions/subs defined in the current module.

        """

        for name, _sub in self.subs.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing sub "%s" in globals' % name)
            context.set(name, _sub)
            context.set(name, _sub, force_global=True)
        for name, _function in self.functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing function "%s" in globals' % name)
            context.set(name, _function)
            context.set(name, _function, force_global=True)
        for name, _prop in self.props.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing property let "%s" in globals' % name)
            context.set(name, _prop)
            context.set(name, _prop, force_global=True)
        for name, _function in self.external_functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing external function "%s" in globals' %
                          name)
            context.set(name, _function)
        for name, _var in self.global_vars.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing global var "%s" = %s in globals (1)' %
                          (name, safe_str_convert(_var)))
            if (isinstance(name, str)):
                context.set(name, _var)
                context.set(name, _var, force_global=True)
            if (isinstance(name, list)):
                context.set(name[0], _var, var_type=name[1])
                context.set(name[0], _var, var_type=name[1], force_global=True)
예제 #26
0
def _handle_nodetypedvalue_read(arg, context, got_constant_math):
    """Handle reads of the nodeTypedValue field of an object.

    @param arg (VBA_Object object) The item being evaluated.

    @param context (Context object) The current program state.
    
    @param got_constant_math (boolean) If True the given arg is an all
    numeric literal expression, if False it is not.
    
    @return (??) On success the evaluated item is returned, None is
    returned on error.

    """

    # This is a hack to get values saved in the .text field of objects.
    # To do this properly we need to save "FOO.text" as a variable and
    # return the value of "FOO.text" when getting "FOO.nodeTypedValue".
    if ("nodetypedvalue" in arg.lower()):
        try:
            tmp = arg.lower().replace("nodetypedvalue", "text")
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("eval_arg: Try to get as " + tmp + "...")
            val = context.get(tmp)

            # It looks like maybe this magically does base64 decode? Try that.
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("eval_arg: Try base64 decode of '" +
                          safe_str_convert(val) + "'...")
            val_decode = utils.b64_decode(val)
            if (val_decode is not None):
                if got_constant_math: set_cached_value(arg, val_decode)
                return val_decode
        except KeyError:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("eval_arg: Not found as .text.")

    # Not handled.
    return None
예제 #27
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the concatenation of all the arguments:
        # TODO: handle non-string args
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug('Concatenation before eval: %r' % params)
        try:
            eval_params = evaluated_args
            eval_params = coerce_args_to_str(eval_params)
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('Concatenation after eval: %r' % eval_params)
            return ''.join(eval_params)
        except (TypeError, ValueError) as e:
            log.exception('Impossible to concatenate non-string arguments. ' +
                          str(e))
            # TODO
            return ''
예제 #28
0
    def _handle_func_decls(self, tokens):
        """Look for functions/subs declared anywhere, including inside the
        body of other functions/subs. The function/sub declarations
        will be saved in the subs and functions fields of the current
        Module object.

        @param tokens (list) A list of pyparsing tokens representing a
        parsed Module.

        """

        # Look through each parsed item in the module for function/sub
        # definitions.
        for token in tokens:
            if (not hasattr(token, "accept")):
                continue
            func_visitor = function_defn_visitor()
            token.accept(func_visitor)
            for i in func_visitor.func_objects:

                # Sub to add?
                if isinstance(i, Sub):
                    if (log.getEffectiveLevel() == logging.DEBUG):
                        log.debug("saving sub decl: %r" % i.name)
                    self.subs[i.name] = i

                # Func to add?
                elif isinstance(i, Function):
                    if (log.getEffectiveLevel() == logging.DEBUG):
                        log.debug("saving func decl: %r" % i.name)
                    self.functions[i.name] = i

                # Property Let or Get function to add?
                elif isinstance(i, (PropertyLet, PropertyGet)):
                    if (log.getEffectiveLevel() == logging.DEBUG):
                        log.debug("saving property let/get decl: %r" % i.name)
                    self.props[i.name] = i
예제 #29
0
def _updated_vars_to_python(loop, context, indent):
    """Generate Python JIT code for saving the variables updated in a loop
    in Python. These updates are saved in the Python var_updates
    variable.

    @param loop (VBA_Object object) The loop for which to generate
    Python JIT code.

    @param context (Context object) The current program state.

    @param indent (int) The number of spaces to indent the generated
    Python code.

    @return (str) Python JIT code.

    """
    import statements
    
    indent_str = " " * indent
    lhs_visitor = lhs_var_visitor()
    loop.accept(lhs_visitor)
    lhs_var_names = lhs_visitor.variables
    # Handle With variables if needed.
    if (context.with_prefix_raw is not None):
        lhs_var_names.add(safe_str_convert(context.with_prefix_raw))
    # Handle For loop index variables if needed.
    if (isinstance(loop, statements.For_Statement)):
        lhs_var_names.add(safe_str_convert(loop.name))
    var_dict_str = "{"
    first = True
    for var in lhs_var_names:
        py_var = utils.fix_python_overlap(var)
        if (not first):
            var_dict_str += ", "
        first = False
        var = var.replace(".", "")
        var_dict_str += '"' + var + '" : ' + py_var
    var_dict_str += "}"
    save_vals = indent_str + "try:\n"
    save_vals += indent_str + " " * 4 + "var_updates\n"
    save_vals += indent_str + " " * 4 + "var_updates.update(" + var_dict_str + ")\n"
    save_vals += indent_str + "except (NameError, UnboundLocalError):\n"
    save_vals += indent_str + " " * 4 + "var_updates = " + var_dict_str + "\n"
    save_vals += indent_str + 'var_updates["__shell_code__"] = core.vba_library.get_raw_shellcode_data()\n'
    save_vals = indent_str + "# Save the updated variables for reading into ViperMonkey.\n" + save_vals
    if (log.getEffectiveLevel() == logging.DEBUG):
        save_vals += indent_str + "print \"UPDATED VALS!!\"\n"
        save_vals += indent_str + "print var_updates\n"
    return save_vals
예제 #30
0
    def eval(self, context, params=None):
        """Evaluate the current value of the object.

        @param context (Context object) Context for the evaluation
        (local and global variables). State updates will be reflected
        in the given context.

        @param params (list) Any parameters provided to the object.

        @return (any) The result of emulating the current object.

        """
        context = context  # pylint
        params = params  # pylint

        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug(self)
예제 #31
0
                return response
            else:
                log.error("Unhandled error {0}. If you get this error message something is broken in the intent module. Please raise an issue on https://github.com/ironman5366/W.I.L.L".format(str(parsed.values()[0])))
    except Exception as e:
        log.error(e, 'error')
        return str(e)


if __name__ == "__main__":
    '''Open logs, check log settings, and start the flask server and slack thread'''
    log.info('''

\                /   |    |              |
 \              /    |    |              |
  \            /     |    |              |
   \    /\    /      |    |              |
    \  /  \  /       |    |              |
     \/    \/        |    ------------   ------------
        ''')
    if log.getEffectiveLevel() == logging.DEBUG:
        debugval = True
    else:
        debugval = False
    log.info("Debug value is {0}".format(debugval))
    log.info("Connecting to rtm socket")
    t = threading.Thread(target=slack)
    t.daemon=True #Kills the thread on program exit
    t.start()
    log.info("Starting flask server on localhost")
    print app.run(debug=debugval, use_reloader=False)