Created
December 13, 2014 17:03
-
-
Save rickardp/08b513e55ac5edd56caa to your computer and use it in GitHub Desktop.
Busybox file copy tool
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 | |
# | |
# Tool to copy files/directory trees to/from devices where the only opening | |
# is a telnet/serial shell and there is nothing other than a basic busybox on the device. | |
# | |
import sys, socket, tempfile, shutil, re, time | |
import telnetlib as T | |
# Busybox telnetd always expands tabs to spaces (this is hard-coded into telnetd.c) | |
XTABS_WORKAROUND = True | |
prompt = None | |
def expect(s, r, to=1000): | |
buf = "" | |
t0 = time.time() | |
while (not r) or (not buf.endswith(r)): | |
l = s.recv(4096) | |
if len(l) == 0: break | |
buf += l | |
if time.time() - t0 > to: break | |
return buf | |
# Expand / unexpand telnet IAC chars | |
def escape(s): | |
return s.replace("\xff", "\xff\xff") | |
def unescape(s): | |
return s.replace("\xff\xff", "\xff") | |
def do_cmd(s, cmd, stdin=False, stdout=False): | |
cmd = escape(cmd).strip() | |
if XTABS_WORKAROUND and stdout: | |
cmd += ' | sed "s/#/##/g" | sed "s/\\t/#t/g"' | |
cmd += '\r\n' | |
print >>sys.stderr, ">>", cmd, | |
s.send(cmd) | |
if stdin: | |
raise NotImplementedError() | |
buf = unescape(expect(s, prompt)) | |
if buf.startswith(cmd): buf = buf[len(cmd):] | |
if buf.endswith(prompt): buf = buf[:-len(prompt)] | |
if XTABS_WORKAROUND and stdout: | |
buf = buf.replace("#t","\t").replace("##","#") | |
buf = buf.replace("\r\n", "\n") | |
l = [] | |
return buf | |
def usage(): | |
print >>sys.stderr, "Usage: " + sys.argv[0] + " <dest> [getdir|get|putdir|put] <remotefile>" | |
print >>sys.stderr, "Last-resort binary transfer when the only access is telnet or a" | |
print >>sys.stderr, "serial console. When possible, use ssh/scp instead of this hack." | |
print >>sys.stderr, "" | |
print >>sys.stderr, "Local file is always stdin/stdout" | |
print >>sys.stderr, "Examples:" | |
print >>sys.stderr, " " + sys.argv[0] + " 192.168.1.121 getdir / > rootfs.tar.gz" | |
print >>sys.stderr, " (Gets entire filesystem as tarball over telnet)" | |
print >>sys.stderr, " " + sys.argv[0] + " /dev/ttyUSB0 get /dev/mmcblk0p1 > part0.gz" | |
print >>sys.stderr, " (Gets block device as gzip over serial)" | |
print >>sys.stderr, " " + sys.argv[0] + " /dev/ttyUSB0 put /bin/ls < hacked_ls" | |
print >>sys.stderr, " (Replaces /bin/ls over serial)" | |
def do_connect(dest): | |
global prompt | |
hp = dest.split(":") | |
port = 23 | |
if len(hp) > 1: | |
port = int(hp[1]) | |
# Connect | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.connect((hp[0], port)) | |
# Wait for prompt | |
buf = expect(s, r"# ", .5) | |
prompt = buf.split("\n")[-1] | |
return s | |
def do_getdir(dest, remotefile): | |
s = do_connect(dest) | |
buf = do_cmd(s, 'tar -zc -C ' + remotefile + ' . 2>/dev/null', stdout=True) | |
sys.stdout.write(buf) | |
s.close() | |
def do_get(dest, remotefile): | |
s = do_connect(dest) | |
buf = do_cmd(s, 'gzip 2>/dev/null < ' + remotefile, stdout=True) | |
sys.stdout.write(buf) | |
s.close() | |
def do_put(dest, remotefile): | |
s = do_connect(dest) | |
buf = do_cmd(s, 'cat > ' + remotefile, stdin=True) | |
sys.stdout.write(buf) | |
s.close() | |
def do_putdir(dest, remotefile): | |
raise NotImplementedError("putdir command is not implemented") | |
if __name__ == '__main__': | |
if len(sys.argv) <= 3: | |
usage() | |
sys.exit(1) | |
dest = sys.argv[2] | |
remotefile = sys.argv[3] | |
if sys.argv[1] == "getdir": | |
do_getdir(dest, remotefile) | |
elif sys.argv[1] == "get": | |
do_get(dest, remotefile) | |
elif sys.argv[1] == "putdir": | |
do_putdir(dest, remotefile) | |
elif sys.argv[1] == "put": | |
do_put(dest, remotefile) | |
else: | |
print >>sys.stderr, "Sub-command", sys.argv[1], "not recognized" | |
usage() | |
sys.exit(1) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment