def __set_file_for_obfuscator(self, value): # Specific set for extras obfuscate # Check if file exists if not os.path.isfile(value): alert.error(f"Error: {value} is not a file") return False return self.__set_file(value)
def __set_encoder(self, value): arch, current_module = str(self.current_module).split("/")[-2:] module_path = f"owasp_zsc.modules.encoders.{arch}.{current_module}.{value}" try: list_encoder = [ x[0] for x in self.current_module.get_encoders( str(self.current_module)) ] if value not in list_encoder: alert.error("Error: invalid encoder") return False module = importlib.import_module(module_path) encoder_module = getattr(module, "Encoder")() encoder_options = [] for k, v in encoder_module.module_attributes.items(): self.current_module.module_attributes.update({k: v}) setattr(self.current_module, k, v[0]) encoder_options.append(k) if encoder_options: self.current_module.encoder_options = encoder_options return True except: alert.error("Error while set encoders") return False
def _show_methods(self, *args, **kwargs): if not hasattr(self.current_module, "obfuscate_methods"): alert.error("This module doesn't support obfuscate") else: alert.info( f"Available obfuscate methods: {self.current_module.obfuscate_methods}" )
def run(self): if not self.target_file: alert.error("Target file is required") return if not self.content: alert.error("File's content is required") return self.handle_generate(__name__)
def run(self): if not self.target_file: alert.error("Target file and file's permissions are required") return if not self.permission: alert.error("Target's permission is required") return self.handle_generate(__name__)
def run(self): if not self.lhost: alert.error("Listen address") return if not self.lport: alert.error("Listen port") return self.handle_generate(__name__)
def __set_file(self, value): # Parse file extension to set arguments automatically file_name, file_ext = os.path.splitext(value) # If no extension, we try shebang. Have to deal with binary files if not file_ext: alert.error( f"{value} might be a valid file. But shebang parsing isn't supported." ) else: if file_ext == ".py": module_type = "python" elif file_ext.lower() == ".js": module_type = "javascript" elif file_ext.lower() == ".pl": module_type = "perl" elif file_ext.lower() == ".rb": module_type = "ruby" elif file_ext.lower().startswith(".php"): module_type = "php" elif file_ext.lower() == ".c": module_type = "c" else: alert.error("Obfuscate is not supported for this language") # Remove obfuscate methods and options self.current_module.obfuscate_methods = [] self.current_module.obfuscate_options = [] return 2 alert.info( f"Detected {module_type} language. Obfuscation is available.") setattr(self.current_module, "type", module_type) if "type" in self.current_module.module_attributes.keys(): self.current_module.module_attributes["type"][0] = module_type else: self.current_module.module_attributes.update( {"type": [module_type, "File type"]}) from owasp_zsc.libs import obfuscate module_path = obfuscate.__path__[0].split("ZSC/")[1] module = importlib.import_module( f"{module_path.replace('/', '.')}.{module_type}") obfuscate_module = getattr(module, "Obfuscator")() self.current_module.obfuscate_methods = [ os.path.splitext(x)[0] for x in os.listdir(f"{module_path}/{module_type}") if x.endswith(".py") and not x.startswith("__") ] obfuscate_opts = [] for k, v in obfuscate_module.module_attributes.items(): self.current_module.module_attributes.update({k: v}) setattr(self.current_module, k, v[0]) obfuscate_opts.append(k) if obfuscate_opts: self.current_module.obfuscate_options = obfuscate_opts return True
def __set__(self, instance, value): try: if not str(value): alert.error("Value is empty") return self.display_value = str(value) self.value = int(value) except ValueError: alert.error(f"Invalid option. Cannot cast '{value}' to integer.")
def run(self): if not self.target_file: alert.error("Target file and file's permissions are required") return try: import traceback self.handle_generate(__name__) except: traceback.print_exc()
def command_use(self, module_path, *args, **kwargs): full_module_path = ".".join( ("owasp_zsc.modules.payloads", module_path)) try: module = importlib.import_module(full_module_path) # When we use new module, some old values are kept -> buggy "show options". Reload to "refresh" all attr importlib.reload(module) self.current_module = getattr(module, "Module")() except ModuleNotFoundError: alert.error(f"Invalid module {module_path}")
def command_show(self, *args, **kwargs): sub_command = args[0] try: if self.current_module: getattr(self, f"_show_{sub_command}")(*args, **kwargs) else: alert.error("A module is required!") except AttributeError: alert.error( f"Unknown 'show' sub-command '{sub_command}'. What do you want to show?\n" )
def __set__(self, instance, value): try: if not str(value): alert.error("Value is empty") return if "://" not in value: alert.warn( "URL is not starting with protocol. Force 'http://'") value = f"http://{value}" self.display_value = self.value = str(value) except ValueError: alert.error(f"Invalid option. Cannot cast '{value}' to integer.")
def _show_encoders(self, *args, **kwargs): if issubclass(self.current_module.__class__, BasePayload): encoders = self.current_module.get_encoders( str(self.current_module)) if encoders: headers = ("Encoder", "Description") print_table(headers, *encoders, max_column_length=100) return else: alert.error("No encoders available") else: alert.error("Module doesn't support encoders")
def handle_generate(self, name=""): alert.info("Generating payload") asm_code = self.generate() arch, module = name.split(".")[-2:] if not arch: alert.error("Invalid arch of module") return if self.encoder: asm_code = self.handle_encode(arch, module, self.encoder, asm_code) from owasp_zsc.libs import opcoder opcode_path = f"{opcoder.__path__[0].split('ZSC/')[1].replace('/', '.')}.{arch}" opcode_module = importlib.import_module(opcode_path) opcode = getattr(opcode_module, "convert")(asm_code) if not self.file: alert.info("ASM code:") print(asm_code) if opcode: alert.info("Opcode:") print(f"\"{opcode}\"") else: alert.warn("No opcode is available") else: # We do generate code here. Scope: C, ASM, Nim, ... # if file is asm, we don't have to have opcode ext = os.path.splitext(self.file)[1] if ext.lower() == ".asm": alert.info("ASM file. Only write ASM code.") try: open(self.file, "w").write(asm_code) alert.info(f"ASM code is written at {self.file}") if arch.endswith("x86"): # alert.info("Compile binary commands:") # DEBUG compile binaries for easier test folder = os.path.split(self.file)[0] folder = os.getcwd() if not folder else folder os.system(f"as {self.file} --32 -o {folder}/out.o") os.system( f"ld -m elf_i386 -o {folder}/out {folder}/out.o") alert.info(f"Binary is compiled at {folder}/out") # print(f"as {self.file} --32 -o <out.o>") # print(f"ld -m elf_i386 -o <out_binary> <out.o>") else: print(f" as {self.file} -o <out.o>") print(f" ld -o <out_binary> <out.o>") except: alert.error(f"Failed to write ASM code to {self.file}") return False return True
def __set__(self, instance, value): # When user set file, we are having 2 cases # 1. File exists (obfuscate) # 2. File doesn't exist (generate) # Both cases need file is writable. First case needs file readable try: # If file exists, we check if file is readable. If not, alert and return if os.path.isfile(value): if not os.access(value, os.R_OK): alert.error(f"File {value} is not readable") return # If file is not there, check if we can read and write file folder = os.path.split(value)[0] if not os.access(folder, os.W_OK): alert.error(f"Folder {folder} is not writable.") self.value = self.display_value = str(value) except ValueError: raise ValueError( f"Invalid option. Cannot cast '{value}' to string.")
def command_set(self, *args, **kwargs): if not self.current_module: return key, _, value = args[0].partition(" ") if key in self.current_module.options: if key == "file": if str(self.current_module) == "payloads/obfuscator/obfuscate": result = self.__set_file_for_obfuscator(value) if not result or result == 2: return elif str(self.current_module).split("/")[1] == "generator": if not self.__set_file(value): return elif key == "encoder": if not self.__set_encoder(value): return elif key == "method": if not self.__set_method(value): alert.error(f"Invalid obfuscation method {value}") return try: setattr(self.current_module, key, value) self.current_module.module_attributes[key][0] = value if kwargs.get("glob", False): GLOBAL_OPTS[key] = value alert.info(f"{key} => {value}") except AttributeError: alert.error(f"Failed to set {key} -> {value}") else: alert.error( f"You can't set option '{key}'.\nAvailable options: {self.current_module.options}" )
def run(self): if not self.file: alert.error("File option is required") return if not self.method: alert.error("An obfuscation method is required") return from owasp_zsc.libs import obfuscate import importlib try: module_path = obfuscate.__path__[0].split("owasp_zsc")[1].replace( "/", ".") module = importlib.import_module( f"owasp_zsc{module_path}.{self.type}.{self.method}") module = getattr(module, "ObfuscateModule")() if hasattr(module, "times"): setattr(module, "times", self.times ) # FIX submodule doesn't take new times from options alert.info("Getting file content") content = open(self.file).read() if not content.strip(): alert.error("File is empty!") return alert.info("Obfuscating file content") obfuscated_content = module.start(content) alert.info("Generating obfuscated script") f = open(self.file, "w") f.write(obfuscated_content) f.close() alert.info("Completed. Your file is obfuscated.") except AttributeError: traceback.print_exc() alert.error("Invalid module") except: traceback.print_exc()
def run(self): if not self.command: alert.error("A command is required.") return self.handle_generate(__name__)
def command_unset(self, *args, **kwargs): key, _, value = args[0].partition(" ") try: del self.current_module.module_attributes[key] except KeyError: alert.error(f"Can't unset {key}.")