Esempio n. 1
0
    def create_random_variable(self, var_type, prefix):
        """
        Description:
            Generate a randomized variable
        :param var_type: string
        :param prefix: string
        :return: dict
        """

        v = {"type": var_type, "name": "", "size": 0, "init_value": ""}

        # Create a variable name
        while (v["name"] == "") or (v["name"] in self.used_variables):
            v["name"] = "%s_%s" % (prefix, VarGenerators.random_lower_alphanum(8))
        self.used_variables.add(v["name"])

        # Create the variable init_value
        type_info = self.language["var_types"][var_type]

        # If the variable definition has a temporary name in it, create one and use it
        temp_name = ""
        if "`nt`" in type_info["line"]:
            while (temp_name == "") or (temp_name in self.used_variables):
                temp_name = "%s_%s" % (prefix, VarGenerators.random_lower_alphanum(8))
            self.used_variables.add(temp_name)

        # Fill in the size of the variable
        v["size"] = type_info["size"]
        if "rand" in v["size"]:
            m = re.match("randint\((\d+),(\d+)\)", v["size"])
            v["size"] = str(random.randint(int(m.group(1)), int(m.group(2))))

        # Or it's an expression of its type and size
        if "`" in type_info["init_value"]:
            v["init_value"] = type_info["init_value"].replace("`t`", var_type).replace("`l`", v["size"])
        # The value is a CSV
        elif "," in type_info["init_value"]:
            v["init_value"] = random.choice(type_info["init_value"].split(","))
        # Otherwise it is a function reference
        else:
            i = getattr(VarGenerators, type_info["init_value"])()
            v["init_value"] = i["value"]
            v["size"] = i["size"]

        if type_info["size"] == "len+1":
            v["size"] += 1

        v["line"] = type_info["line"].replace("`n`", v["name"]).replace("`v`", str(v["init_value"]))
        v["line"] = v["line"].replace("`t`", var_type).replace("`l`", str(v["size"])).replace("`nt`", temp_name)

        return v
Esempio n. 2
0
    def create_code_block(self, real_code, current_signature, lv,
                          add_return=False, code_levels=10, in_func=False):
        ret = {"code": [], "used_vars": []}

        unused_locals = []

        old_local_vars = copy.copy(lv)

        self.var_types = self.language["var_types"].keys()

        # Generate local variables for the code block if it's in a function or if variables
        # outside of functions are alright
        new_local_vars = []
        if int(self.language["features"]["gen_vars_outside_functions"]) or in_func:
            for i in range(len(self.var_types)):
                for j in range(random.randint(1, 2)):
                    new_local_vars.append(self.create_random_variable(self.var_types[i], "lvar"))
        random.shuffle(new_local_vars)

        # Add them to the code block return
        for lv in new_local_vars:
            unused_locals.append(lv)

        local_vars = old_local_vars
        local_vars.extend(new_local_vars)

        # Check for any assignments of variables and mix them into the other initializations
        assignments = []
        if real_code:
            while real_code[0].strip() in ["{", "}", ""]:
                del real_code[0]

            while re.match(self.regex_assignment, real_code[0].strip()):
                assignments.append(real_code[0])
                del real_code[0]

        if assignments:
            if new_local_vars:
                ass_break = len(new_local_vars)/len(assignments)
                ass = [new_local_vars[i::ass_break] for i in range(ass_break)]
                for i in range(len(ass)):
                    for a in ass[i]:
                        ret["code"].append(a["line"])
                    if i < len(assignments):
                        ret["code"].append(assignments[i].strip())

            else:
                for a in assignments:
                    ret["code"].append(a.strip())

        else:
            for lv in new_local_vars:
                ret["code"].append(lv["line"])

        # Keep creating code until there isn't any more real code to include
        # As real code is used, it will be removed from the list
        while True:
            r = self.config.choose_weighted()

            # If there's no real code left but we have unused local variables, focus what we create to use them
            if (not real_code) and unused_locals and in_func:
                unused_type = unused_locals[0]["type"]
                r = random.choice(self.language["var_types"][unused_type]["unusers"])

            # Force real code to be used immediately if it is the continuation of an if else block
            # Otherwise there can be code between if and else, causing syntax errors
            elif real_code and re.match("^(elif|else)", real_code[0]):
                r = "real"

            # If the language doesn't allow generating code outside functions, use real code until you're in a function
            elif (not in_func) and (not int(self.language["features"]["gen_code_outside_functions"])):
                r = "real"

            gen_code = {}

            # Handle functions
            if (r == "function") and ("function" in self.language["code_types"]):
                if code_levels <= 0:
                    continue

                # Create the new function signature
                signature = {"name": "", "return": random.choice(self.language["var_types"].keys()), "args": []}
                while (signature["name"] == "") or (signature["name"] in self.used_functions):
                    signature["name"] = "sub_%s" % VarGenerators.random_lower_alphanum(random.randint(5, 32))
                self.used_functions.add(signature["name"])

                # Create random arguments for the function
                for arg_count in range(random.randint(1, 5)):
                    signature["args"].append(self.create_random_variable(random.choice(self.var_types), "avar"))

                # Create the function call
                return_var = self.pick_unused_variable(signature["return"], unused_locals, current_signature["args"]+local_vars)
                fc = self.language["function"]["call_signature"].replace("`n`", signature["name"])
                arg_list = []
                for a in signature["args"]:
                    new_arg = self.pick_unused_variable(a["type"], unused_locals, current_signature["args"]+local_vars)
                    arg_list.append(self.language["function"]["call_arg_signature"].replace("`n`", new_arg))
                fc = fc.replace("`a`", ", ".join(arg_list)).replace("`v`", return_var)

                gen_code = {"code": [], "used_vars": []}
                gen_code["code"].append(fc)
                gen_code["used_vars"] = arg_list

                # Create the function's code
                self.obfuscated_functions.append(self.create_code_function([], signature, [], code_levels, add_return=True))

            # Handle MATH!
            elif (r == "math") and ("math" in self.language["code_types"]):
                gen_code = self.create_code_math(unused_locals, current_signature, local_vars)

            # Handle Memory manipulation
            elif (r == "memory") and ("memory" in self.language["code_types"]):
                gen_code = self.create_code_memory(unused_locals, current_signature, local_vars)

            # Handle API function calls
            elif (r == "api") and ("api" in self.language["code_types"]):
                gen_code = self.create_code_api(unused_locals, current_signature, local_vars)

            # Handle conditionals
            elif (r == "conditional") and ("conditional" in self.language["code_types"]):
                if code_levels <= 0:
                    continue

                gen_code = self.create_code_conditional([], unused_locals, current_signature, local_vars, code_levels, in_func)

            # Handle loops
            elif (r == "loop") and ("loop" in self.language["code_types"]):
                gen_code = self.create_code_loop(unused_locals, current_signature, local_vars)

            # Handle string manipulations
            elif (r == "strings") and ("strings" in self.language["code_types"]):
                gen_code = self.create_code_string_work(unused_locals, current_signature, local_vars)

            # Handle sleep
            elif (r == "sleep") and ("sleep" in self.language["code_types"]):
                gen_code = self.create_code_sleep(unused_locals, current_signature, local_vars)

            # Handle real code
            elif r == "real":
                # If there's no real code left and all the local vars have been used, end the code block
                if (not real_code) and ((self.language["features"]["must_use_vars"] == "0") or (not len(unused_locals)) or (not in_func)):

                    # Add a return value if it says to
                    if add_return:
                        v1 = self.pick_unused_variable(current_signature["return"], unused_locals, current_signature["args"]+local_vars)
                        return_line = self.language["function"]["return_definition"].replace("`r`", v1)
                        ret["code"].append(return_line)
                    break

                # Otherwise, if there's no more real code, keep using up vars
                elif not real_code:
                    continue

                # Get rid of bracket lines and empty lines
                if real_code[0].strip() in ["{", "}", ""]:
                    del real_code[0]
                    continue

                if re.match(self.regex_conditional, real_code[0].strip()) or \
                   re.match(self.regex_loop, real_code[0].strip()) or \
                   re.match(self.regex_function, real_code[0].strip()):
                    block = {"line": real_code[0].strip(), "code_block": []}

                    tab_count = CodeParsers.get_tab_count(real_code[0])

                    end_of_block = getattr(CodeParsers, self.language["features"]["code_blocks"])(index=1,
                                                                                                  code_block=real_code,
                                                                                                  tab_count=tab_count)
                    #end_of_block = self.find_code_block(tab_count, real_code, 1)

                    cb_in_func = in_func
                    if re.match(self.regex_function, real_code[0].strip()):
                        cb_in_func = True

                    # Pass the code no local variables if it's a new function
                    use_locals_vars = local_vars
                    if re.match(self.regex_function, real_code[0].strip()):
                        use_locals_vars = []

                    print real_code[0]
                    new_code_block = self.create_code_block(real_code[1:end_of_block], current_signature,
                                                            use_locals_vars, False, code_levels-1, cb_in_func)
                    block["code_block"] = new_code_block["code"]

                    gen_code = {"code": [block], "used_vars": new_code_block["used_vars"]}

                    real_code = real_code[end_of_block:]

                elif re.match(self.regex_return, real_code[0].strip()):
                    ret["code"].append("%s" % real_code[0].strip())
                    print real_code[0]
                    del real_code[0]
                    break

                else:
                    ret["code"].append("%s" % real_code[0].strip())
                    print real_code[0]
                    del real_code[0]

            if gen_code:
                ret["code"].extend(gen_code["code"])
                for new_arg in gen_code["used_vars"]:
                    ret["used_vars"].append(new_arg)
                    for i in range(len(unused_locals)):
                        if unused_locals[i]["name"] == new_arg:
                            del unused_locals[i]
                            break

        ret["used_vars"] = list(set(ret["used_vars"]))
        return ret