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
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