├── README.md ├── headless-notifier.cna ├── notifier.cna └── notifier.py /README.md: -------------------------------------------------------------------------------- 1 | # Cobalt-Strike notification server 2 | 3 | In order to use the aggressor script you'll need: 4 | * python3 as your default python interpreter 5 | * signal-cli installed in your global path and registered to use signal. 6 | 7 | blogpost: https://blog.nviso.eu/2021/03/05/tap-tap-is-this-thing-on-creating-a-notification-service-for-cobalt-strike/ 8 | -------------------------------------------------------------------------------- /headless-notifier.cna: -------------------------------------------------------------------------------- 1 | global ('$emailaddress'); 2 | global ('$email2textaddress'); 3 | global ('$signalphonenumber'); 4 | global ('$scriptlocation'); 5 | global ('$receivemails'); 6 | global ('$receivetexts'); 7 | global ('$receivesignalmessages'); 8 | 9 | 10 | $emailaddress = ""; 11 | $txt2emailaddress =""; 12 | $signalphonenumber ="+"; 13 | $scriptlocation = "notifier.py"; 14 | $receivemails = "true"; 15 | $receivetexts = "false"; 16 | $receivesignalmessages = "true"; 17 | 18 | 19 | on beacon_initial { 20 | local('$computer'); 21 | local('$internal'); 22 | $computer = beacon_info($1, "computer"); 23 | $internal = beacon_info($1, "internal"); 24 | if(($receivemails eq 'true') && (strlen($emailaddress) != 0)){ 25 | say("new beacon detected! Emailing $emailaddress"); 26 | println("executing python $scriptlocation --ip $internal --computer $computer --receive-emails $emailaddress"); 27 | $handle = exec("python $scriptlocation --ip $internal --computer $computer --receive-emails --email-address $emailaddress"); 28 | } 29 | 30 | if(($receivetexts eq 'true') && (strlen($email2textaddress) != 0)) 31 | { 32 | say("new beacon detected! sending an email to the email to text service!"); 33 | println("executing python $scriptlocation --ip $internal --computer $computer --receive-texts --mail_totext $email2textaddress "); 34 | $handle = exec("python $scriptlocation --ip $internal --computer $computer --receive-texts --mail_totext $email2textaddress"); 35 | } 36 | 37 | if (($receivesignalmessages eq 'true') && (strlen($signalphonenumber) != 0)) 38 | { 39 | say("new beacon detected! sending a signal message to $signalphonenumber"); 40 | println("executing python $scriptlocation --ip $internal --computer $computer --receive-signalmessage --signal-number $signalphonenumber"); 41 | $handle = exec("python $scriptlocation --ip $internal --computer $computer --receive-signalmessage --signal-number $signalphonenumber"); 42 | } 43 | } 44 | {"mode":"full","isActive":false} 45 | -------------------------------------------------------------------------------- /notifier.cna: -------------------------------------------------------------------------------- 1 | global ('$emailaddress'); 2 | global ('$email2textaddress'); 3 | global ('$signalphonenumber'); 4 | global ('$receivesignalmessages'); 5 | global ('$receivemails'); 6 | global ('$receivetexts'); 7 | global ('$scriptlocation'); 8 | 9 | debug(57); 10 | sub callback { 11 | $receivemails = $3["emailchkbox"]; 12 | $emailaddress = $3["email"]; 13 | $email2textaddress = $3["txt2email"]; 14 | $receivetexts = $3["textschkbox"]; 15 | $signalphonenumber = $3["signalnumber"]; 16 | $receivesignalmessages = $3["signalchkbox"]; 17 | $scriptlocation = $3["script_location"]; 18 | if(($receivemails eq 'true') && (strlen($emailaddress) == 0)) 19 | { 20 | show_message("You won't receive emails because you did not input an email address!"); 21 | } 22 | else if(($receivetexts eq 'true') && (strlen($email2textaddress) == 0)) 23 | { 24 | show_message("mail to text field is empty, you will not receive text messages"); 25 | } 26 | 27 | else if (($receivesignalmessages eq 'true') && (strlen($signalphonenumber) == 0)) 28 | { 29 | show_message("You won't receive signal messages because you did not input a phone number"); 30 | } 31 | 32 | else 33 | { 34 | show_message("preferences saved successfully!"); 35 | } 36 | 37 | if (checkError($error)) 38 | { 39 | warn("$error"); 40 | } 41 | 42 | } 43 | 44 | 45 | sub shownotificationdialog{ 46 | $dialog = dialog("notification preferences",%(email => $emailaddress, txt2email => $txt2email,signalnumber => $signalphonenumber,script_location => "/home/kali/aggressors/mailer.py", emailchkbox => $receivemails,textschkbox => $receivetexts, signalchkbox => $receivesignalmessages),&callback); 47 | dialog_description($dialog, "Get notified when a new beacon calls home."); 48 | drow_text($dialog,"email","Your email address:"); 49 | drow_text($dialog,"txt2email","Email address of the mail-to-text provider:"); 50 | drow_text($dialog,"signalnumber","Your signal phone number in internation notation(+countrycode):"); 51 | drow_text($dialog,"script_location","The location of the mail script on YOUR LOCAL HOST:"); 52 | drow_checkbox($dialog,"emailchkbox","Do you want email notifications?"); 53 | drow_checkbox($dialog,"textschkbox","Do you want text messages?"); 54 | drow_checkbox($dialog,"signalchkbox","Do you want signal messages?"); 55 | dbutton_action($dialog,"set preferences"); 56 | dialog_show($dialog); 57 | } 58 | 59 | 60 | 61 | 62 | popup aggressor { 63 | item "Notification preferences" {shownotificationdialog();} 64 | } 65 | 66 | 67 | on beacon_initial { 68 | local('$computer'); 69 | local('$internal'); 70 | $computer = beacon_info($1, "computer"); 71 | $internal = beacon_info($1, "internal"); 72 | if(($receivemails eq 'true') && (strlen($emailaddress) != 0)){ 73 | println("executing python $scriptlocation --ip $internal --computer $computer --receive-emails $emailaddress"); 74 | $handle = exec("python $scriptlocation --ip $internal --computer $computer --receive-emails --email-address $emailaddress"); 75 | } 76 | 77 | if(($receivetexts eq 'true') && (strlen($email2textaddress) != 0)) 78 | { 79 | println("executing python $scriptlocation --ip $internal --computer $computer --receive-texts --mail_totext $email2textaddress "); 80 | $handle = exec("python $scriptlocation --ip $internal --computer $computer --receive-texts --mail_totext $email2textaddress"); 81 | } 82 | 83 | if (($receivesignalmessages eq 'true') && (strlen($signalphonenumber) != 0)) 84 | { 85 | println("executing python $scriptlocation --ip $internal --computer $computer --receive-signalmessage --signal-number $signalphonenumber"); 86 | $handle = exec("python $scriptlocation --ip $internal --computer $computer --receive-signalmessage --signal-number $signalphonenumber"); 87 | } 88 | 89 | 90 | if (checkError($error)) 91 | { 92 | warn("$error"); 93 | } 94 | 95 | }; 96 | 97 | {"mode":"full","isActive":false} 98 | -------------------------------------------------------------------------------- /notifier.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import smtplib 4 | from email.mime.multipart import MIMEMultipart 5 | from email.mime.text import MIMEText 6 | 7 | #change your smtp login details here. 8 | fromaddr = "" 9 | smtp_password="" 10 | smtp_server ="" 11 | smtp_port = 587 12 | 13 | #change your signal REGISTRATION number here: 14 | signal_registration_number ="" 15 | 16 | 17 | #leave these blank, they get handles by the aggressor. 18 | smsaddr = "" 19 | mailaddr = "" 20 | 21 | 22 | parser = argparse.ArgumentParser(description='beacon info') 23 | parser.add_argument('--computer') 24 | parser.add_argument('--ip') 25 | parser.add_argument('--receive-texts', action="store_true") 26 | parser.add_argument('--receive-emails', action="store_true") 27 | parser.add_argument('--receive-signalmessage', action="store_true") 28 | parser.add_argument('--email-address') 29 | parser.add_argument('--mail_totext') 30 | parser.add_argument('--signal-number') 31 | 32 | args = parser.parse_args() 33 | toaddr = [] 34 | 35 | #take care off email and email2text: 36 | if args.receive_texts and args.mail_totext: 37 | toaddr.append(smsaddr) 38 | if args.receive_emails and args.email_address: 39 | toaddr.append(args.email_address) 40 | 41 | 42 | #message contents: 43 | hostname = args.computer 44 | internal_ip = args.ip 45 | body = "Check your teamserver! \nHostname - " + str(hostname) + "\nInternal IP - " + str(internal_ip) 46 | 47 | #email logic 48 | if toaddr: 49 | print("debug") 50 | msg = MIMEMultipart() 51 | msg['From'] = fromaddr 52 | msg['To'] = ", ".join(toaddr) 53 | msg['Subject'] = "INCOMING BEACON" 54 | msg.attach(MIMEText(body, 'plain')) 55 | server = smtplib.SMTP(smtp_server, smtp_port) 56 | server.starttls() 57 | server.login(fromaddr,smtp_password) 58 | text = msg.as_string() 59 | server.sendmail(fromaddr, toaddr, text) 60 | server.quit() 61 | 62 | #signal-cli 63 | if args.signal_number and args.receive_signalmessage: 64 | #take care of signal 65 | print(f"{args.signal_number}") 66 | os.system(f"signal-cli -u {signal_registration_number} send -m " + "\"" + str(body) + "\"" + f" {args.signal_number}") 67 | {"mode":"full","isActive":false} 68 | --------------------------------------------------------------------------------