Files
cowrie/bin/fsctl
Florian Pelgrim 6c7417393a Flake8 fixes (#857)
* Adding flake8-import-order to linters

We need some kind of linter to enforce the code style.
Doing this by hand is error prone and no one will really watch for it.

I decieded to use the default style since it's from my point of view the
best to read and more strictes version.

* Enforcing imports order on bin/

* Enforcing imports order on src/twisted/

* Enforcing imports order on setup.py

* Enforcing imports order on src/cowrie/commands

* Enforcing imports order on src/cowrie/core

* Enforcing imports order on src/cowrie/dblog

* Enforcing imports order on src/cowrie/insults

* Enforcing imports order on src/cowrie/output

* Enforcing imports order on src/cowrie/proxy

* Enforcing imports order on src/cowrie/python

* Enforcing imports order on src/cowrie/shell

* Enforcing imports order on src/cowrie/ssh

* Enforcing imports order on src/cowrie/telnet

* Enforcing imports order on src/cowrie/test

* Reformat file, improved readability

* flake8 E5,E701 src/cowrie/commands/base.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/base.py
src/cowrie/commands/base.py:47:121: E501 line too long (180 > 120 characters)
src/cowrie/commands/base.py:48:121: E501 line too long (182 > 120 characters)
src/cowrie/commands/base.py:49:121: E501 line too long (149 > 120 characters)
src/cowrie/commands/base.py:50:121: E501 line too long (175 > 120 characters)
src/cowrie/commands/base.py:52:121: E501 line too long (127 > 120 characters)
src/cowrie/commands/base.py:54:121: E501 line too long (185 > 120 characters)
src/cowrie/commands/base.py:56:121: E501 line too long (130 > 120 characters)
src/cowrie/commands/base.py:57:121: E501 line too long (122 > 120 characters)
src/cowrie/commands/base.py:59:121: E501 line too long (188 > 120 characters)
src/cowrie/commands/base.py:60:121: E501 line too long (188 > 120 characters)
src/cowrie/commands/base.py:61:121: E501 line too long (145 > 120 characters)
src/cowrie/commands/base.py:63:121: E501 line too long (142 > 120 characters)
src/cowrie/commands/base.py:64:121: E501 line too long (152 > 120 characters)
src/cowrie/commands/base.py:66:121: E501 line too long (128 > 120 characters)
src/cowrie/commands/base.py:67:121: E501 line too long (123 > 120 characters)
src/cowrie/commands/base.py:72:121: E501 line too long (130 > 120 characters)
src/cowrie/commands/base.py:74:121: E501 line too long (125 > 120 characters)
src/cowrie/commands/base.py:75:121: E501 line too long (140 > 120 characters)
src/cowrie/commands/base.py:76:121: E501 line too long (133 > 120 characters)
src/cowrie/commands/base.py:78:121: E501 line too long (124 > 120 characters)
src/cowrie/commands/base.py:79:121: E501 line too long (122 > 120 characters)
src/cowrie/commands/base.py:80:121: E501 line too long (129 > 120 characters)
src/cowrie/commands/base.py:81:121: E501 line too long (150 > 120 characters)
src/cowrie/commands/base.py:83:121: E501 line too long (129 > 120 characters)
src/cowrie/commands/base.py:544:68: E502 the backslash is redundant between brackets
src/cowrie/commands/base.py:553:68: E502 the backslash is redundant between brackets
src/cowrie/commands/base.py:582:66: E502 the backslash is redundant between brackets
src/cowrie/commands/base.py:696:78: E502 the backslash is redundant between brackets
24    E501 line too long (180 > 120 characters)
4     E502 the backslash is redundant between brackets
28

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/commands/curl.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/curl.py
src/cowrie/commands/curl.py:413:106: E502 the backslash is redundant between brackets
1     E502 the backslash is redundant between brackets
1

* Reformat code, improved readability

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/commands/fs.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/fs.py
src/cowrie/commands/fs.py:438:74: E502 the backslash is redundant between brackets
src/cowrie/commands/fs.py:465:67: E502 the backslash is redundant between brackets
2     E502 the backslash is redundant between brackets
2

* flake8 E5, E701 src/cowrie/commands/gcc.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/gcc.py
src/cowrie/commands/gcc.py:167:121: E501 line too long (635 > 120 characters)
1     E501 line too long (635 > 120 characters)
1

* flake8 E5, E701 src/cowrie/commands/ifconfig.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/ifconfig.py
src/cowrie/commands/ifconfig.py:11:121: E501 line too long (145 > 120 characters)
src/cowrie/commands/ifconfig.py:13:121: E501 line too long (138 > 120 characters)
2     E501 line too long (145 > 120 characters)
2

* Reformat code, improved readability

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/commands/netstat.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/netstat.py
src/cowrie/commands/netstat.py:21:121: E501 line too long (126 > 120 characters)
1     E501 line too long (126 > 120 characters)
1

* flake8 E5, E701 src/cowrie/commands/ping.py

flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/ping.py
src/cowrie/commands/ping.py:81:74: E502 the backslash is redundant between brackets
1     E502 the backslash is redundant between brackets
1

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/commands/ssh.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/ssh.py
src/cowrie/commands/ssh.py:79:87: E502 the backslash is redundant between brackets
src/cowrie/commands/ssh.py:99:81: E502 the backslash is redundant between brackets
2     E502 the backslash is redundant between brackets
2

* flake8 E5, E701 src/cowrie/commands/sudo.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/sudo.py
src/cowrie/commands/sudo.py:14:121: E501 line too long (133 > 120 characters)
src/cowrie/commands/sudo.py:15:121: E501 line too long (166 > 120 characters)
src/cowrie/commands/sudo.py:16:121: E501 line too long (122 > 120 characters)
src/cowrie/commands/sudo.py:24:121: E501 line too long (133 > 120 characters)
src/cowrie/commands/sudo.py:25:121: E501 line too long (166 > 120 characters)
src/cowrie/commands/sudo.py:26:121: E501 line too long (122 > 120 characters)
6     E501 line too long (133 > 120 characters)
6

* Reformat code, improved readability

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/commands/wget.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/wget.py
src/cowrie/commands/wget.py:50:19: E701 multiple statements on one line (colon)
src/cowrie/commands/wget.py:264:69: E502 the backslash is redundant between brackets
1     E502 the backslash is redundant between brackets
1     E701 multiple statements on one line (colon)
2

* flake8 E5, E701 src/cowrie/commands/yum.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/commands/yum.py
src/cowrie/commands/yum.py:8:1: F401 'datetime.datetime' imported but unused
src/cowrie/commands/yum.py:223:121: E501 line too long (193 > 120 characters)
src/cowrie/commands/yum.py:228:121: E501 line too long (193 > 120 characters)
src/cowrie/commands/yum.py:237:121: E501 line too long (193 > 120 characters)
3     E501 line too long (193 > 120 characters)
1     F401 'datetime.datetime' imported but unused
4

* flake8 E5, E701 src/cowrie/core/cef.py

flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/core
src/cowrie/core/cef.py:53:121: E501 line too long (122 > 120 characters)
1     E501 line too long (122 > 120 characters)
1

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/output/hpfeeds.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/output/hpfeeds.py
src/cowrie/output/hpfeeds.py:61:26: E701 multiple statements on one line (colon)
src/cowrie/output/hpfeeds.py:80:29: E701 multiple statements on one line (colon)
src/cowrie/output/hpfeeds.py:147:22: E701 multiple statements on one line (colon)
src/cowrie/output/hpfeeds.py:166:22: E701 multiple statements on one line (colon)
src/cowrie/output/hpfeeds.py:173:26: E701 multiple statements on one line (colon)
src/cowrie/output/hpfeeds.py:180:30: E701 multiple statements on one line (colon)
src/cowrie/output/hpfeeds.py:186:34: E701 multiple statements on one line (colon)
7     E701 multiple statements on one line (colon)
7

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/output/sqlite.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/output/sqlite.py
src/cowrie/output/sqlite.py:73:62: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:74:60: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:82:62: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:83:60: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:91:41: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:92:67: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py💯41: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:101:67: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:109:62: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:116:45: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:117:75: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:125:45: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:126:75: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:134:41: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:135:65: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:143:67: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:149:69: E502 the backslash is redundant between brackets
src/cowrie/output/sqlite.py:165:57: E502 the backslash is redundant between brackets
18    E502 the backslash is redundant between brackets
18

* flake8 E5, E701 src/cowrie/output/mysql.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/output/mysql.py
src/cowrie/output/mysql.py:108:77: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:109:71: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:115:75: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:116:73: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:122:75: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:127:54: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:128:80: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:133:54: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:134:80: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:139:58: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:140:88: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:147:58: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:148:88: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:154:58: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:155:88: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:161:54: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:162:78: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:169:68: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:175:70: E502 the backslash is redundant between brackets
src/cowrie/output/mysql.py:191:73: E502 the backslash is redundant between brackets
20    E502 the backslash is redundant between brackets
20

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* flake8 E5, E701 src/cowrie/shell/shlex.py

Before
flake8 --count --select=E1,E2,E3,E5,E701,E901,E999,F401,F821,F822,F823 --max-line-length=120 --statistics src/cowrie/shell
src/cowrie/shell/protocol.py:37:121: E501 line too long (144 > 120 characters)
src/cowrie/shell/shlex.py:111:51: E502 the backslash is redundant between brackets
1     E501 line too long (144 > 120 characters)
1     E502 the backslash is redundant between brackets
2

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Reformat code, improved readability

* Update linters to check for E5 and E701

* Update travis file to the current state

- Removed every checker we do not use. That means twistedchecker
and pytest.
- Updated the flake8 command to match our current clean state
- Removed unused old code

* Fix format typo of cowrie.direct-tcpip.data log event

* Update travis to match the current state

Travis checks now every fixed flake8 error.
Also I removed unused code from it to keep it clean.

* Removed vim file markers

We don't want to have editor specific code in our source files.
Fix your IDE but don't do it in the code.

* src/cowrie/test/test_echo.py removed trailing whitespace

* src/cowrie/commands/yum.py removed trailing whitespace

* src/cowrie/commands/netstat.py removed trailing whitespace

* Checking for flake8 W291, W293

* flake8 F811 ./src/cowrie/commands/scp.py

I made sure to delete only the oldest version of the code.

Before
flake8 --count --select=F811 --application-import-names cowrie --max-line-length=120 --statistics .
./src/cowrie/commands/scp.py:209:5: F811 redefinition of unused 'handle_CTRL_D' from line 192
1     F811 redefinition of unused 'handle_CTRL_D' from line 192
1

* Update flake8 checks

* Fix flake8 E722, F841 src/cowrie/commands/wget.py

* Fix flake8 E722 src/cowrie/commands/ping.py

* Fix flake8 E722,F841 src/cowrie/commands/nc.py

* Fix flake8 E722, E741, F841 src/cowrie/commands/base.py

* Flake8 E731 src/cowrie/commands/base.py

I removed all lambda functions and replaced them with proper code.
That means straight function calls or not calling anything because it's
not needed.

* Fix flake8 E722, F841 src/cowrie/commands/scp.py

* Fix flake8 E722, F841 src/cowrie/commands/ssh.py

* Fix flake8 E712 src/cowrie/commands/iptables.py

* Fix flake8 E741 src/cowrie/commands/adduser.py

* Fix flake8 F841 src/cowrie/commands/tftp.py

* Fix flake8 E722 in all files

* Fix flake8 E711 bin/createdynamicprocess.py

* Fix flake8 E712, E713 src/cowrie/core/dblog.py

* Fix flake8 E712, E713 src/cowrie/shell/avatar.py

* Fix flake8 E712 src/cowrie/shell/fs.py

* Fix flake8 E712, E741 src/cowrie/commands/ls.py

* Fix flake8 E712, E713 src/cowrie/dblog/xmpp.py

* Fix flake8 E731, F841 src/cowrie/commands/gcc.py

* Fix flake8 F841 src/cowrie/insults/insults.py

* Fix flake8 F841 src/cowrie/telnet/session.py

* Fix flake8 F841 src/cowrie/commands/fs.py

* Fix flake8 E741,F841 src/cowrie/commands/last.py

* Fix flake8 E741 src/cowrie/commands/netstat.py

* Fix flake8 F841 src/cowrie/commands/free.py

* Fix flake8 F841 src/cowrie/commands/sudo.py

* Fix flake8 F841 src/cowrie/commands/curl.py

* Fix flake8 F841 src/cowrie/commands/base64.py

* Fix flake8 F841 src/cowrie/commands/service.py

* Fix flake8 F841 src/cowrie/ssh/factory.py

* Fix flake8 F841 src/cowrie/ssh/transport.py

* Fix flake8 F841 src/cowrie/output/csirtg.py

* Fix flake8 F841 src/cowrie/output/kafka.py

* Fix flake8 F841 src/cowrie/output/mongodb.py

* Fix flake8 F741 src/cowrie/output/hpfeeds.py

* Fix flake8 F741 src/cowrie/output/hpfeeds.py

* Fix flake8 F841 src/proxy/session.py

* Fix flake8 F841 src/cowrie/core/utils.py

* Update travis and Dockerfile for flake8 checks
2018-08-18 15:52:45 +04:00

721 lines
21 KiB
Python
Executable File

#!/usr/bin/env python
################################################################
# This is a command line interpreter used to edit
# cowrie file system pickle files.
#
# It is intended to mimic a basic bash shell and supports
# relative file references.
#
# Do not use to build a complete file system. Use:
# /opt/cowrie/bin/createfs
#
# Instead it should be used to edit existing file systems
# such as the default: /opt/cowrie/data/fs.pickle.
#
# Donovan Hubbard
# Douglas Hubbard
# March 2013
################################################################
import cmd
import copy
import os
import pickle
import sys
import time
from stat import *
A_NAME, A_TYPE, A_UID, A_GID, A_SIZE, A_MODE, A_CTIME, A_CONTENTS, A_TARGET, A_REALFILE = list(range(0, 10))
T_LINK, T_DIR, T_FILE, T_BLK, T_CHR, T_SOCK, T_FIFO = list(range(0, 7))
def getpath(fs, path):
cwd = fs
for part in path.split('/'):
if not len(part):
continue
ok = False
for c in cwd[A_CONTENTS]:
if c[A_NAME] == part:
cwd = c
ok = True
break
if not ok:
raise Exception('File not found')
return cwd
def exists(fs, path):
try:
getpath(fs, path)
return True
except Exception as e:
if str(e) == 'File not found':
return False
else:
raise Exception(e)
def is_directory(fs, path):
"""
Returns whether or not the file at 'path' is a directory
:param fs:
:param path:
:return:
"""
file = getpath(fs, path)
if file[A_TYPE] == T_DIR:
return True
else:
return False
def resolve_reference(pwd, relativeReference):
"""
Used to resolve a current working directory and a relative reference into an absolute file reference.
"""
tempPath = os.path.join(pwd, relativeReference)
absoluteReference = os.path.normpath(tempPath)
return absoluteReference
class fseditCmd(cmd.Cmd):
def __init__(self, pickle_file_path):
cmd.Cmd.__init__(self)
if not os.path.isfile(pickle_file_path):
print(("File %s does not exist." % pickle_file_path))
sys.exit(1)
try:
pickle_file = open(pickle_file_path, 'rb')
except IOError as e:
print(("Unable to open file %s" % pickle_file_path))
sys.exit(1)
try:
self.fs = pickle.load(pickle_file)
except:
print((("Unable to load file '%s'. " + \
"Are you sure it is a valid pickle file?") % \
(pickle_file_path,)))
sys.exit(1)
self.pickle_file_path = pickle_file_path
# get the name of the file so we can display it as the prompt
path_parts = pickle_file_path.split('/')
self.fs_name = path_parts[-1]
self.update_pwd("/")
self.intro = "\nKippo/Cowrie file system interactive editor\n" + \
"Donovan Hubbard, Douglas Hubbard, March 2013\n" + \
"Type 'help' for help\n"
def save_pickle(self):
"""
saves the current file system to the pickle
:return:
"""
try:
pickle.dump(self.fs, open(self.pickle_file_path, 'wb'))
except Exception as e:
print((("Unable to save pickle file '%s'. " + \
"Are you sure you have write access?") % \
(self.pickle_file_path,)))
print(str(e))
sys.exit(1)
def do_exit(self, args):
"""
Exits the file system editor
"""
return True
def do_EOF(self, args):
"""
The escape character ctrl+d exits the session
"""
# exiting from the do_EOF method does not create a newline automatically
# so we add it manually
print()
return True
def do_ls(self, args):
"""
Prints the contents of a directory, use ls -l to list in long format
Prints the current directory if no arguments are specified
"""
longls = False
if args.startswith('-l'):
longls = True
args = args[3:]
if not len(args):
path = self.pwd
else:
path = resolve_reference(self.pwd, args)
if exists(self.fs, path) == False:
print(("ls: cannot access %s: No such file or directory" % (path,)))
return
if is_directory(self.fs, path) == False:
print(("ls: %s is not a directory" % (path,)))
return
cwd = getpath(self.fs, path)
files = cwd[A_CONTENTS];
files.sort()
largest = 0
if len(files):
largest = max([x[A_SIZE] for x in files])
for file in files:
if not longls:
if file[A_TYPE] == T_DIR:
print((file[A_NAME] + '/'))
else:
print((file[A_NAME]))
continue
perms = ['-'] * 10
if file[A_MODE] & S_IRUSR: perms[1] = 'r'
if file[A_MODE] & S_IWUSR: perms[2] = 'w'
if file[A_MODE] & S_IXUSR: perms[3] = 'x'
if file[A_MODE] & S_IRGRP: perms[4] = 'r'
if file[A_MODE] & S_IWGRP: perms[5] = 'w'
if file[A_MODE] & S_IXGRP: perms[6] = 'x'
if file[A_MODE] & S_IROTH: perms[7] = 'r'
if file[A_MODE] & S_IWOTH: perms[8] = 'w'
if file[A_MODE] & S_IXOTH: perms[9] = 'x'
linktarget = ''
if file[A_TYPE] == T_DIR:
perms[0] = 'd'
elif file[A_TYPE] == T_LINK:
perms[0] = 'l'
linktarget = ' -> %s' % (file[A_TARGET],)
perms = ''.join(perms)
ctime = time.localtime(file[A_CTIME])
uid = file[A_UID]
gid = file[A_GID]
if uid == 0:
uid = 'root'
else:
uid = str(uid).rjust(4)
if gid == 0:
gid = 'root'
else:
gid = str(gid).rjust(4)
print(('%s 1 %s %s %s %s %s%s' % \
(perms,
uid,
gid,
str(file[A_SIZE]).rjust(len(str(largest))),
time.strftime('%Y-%m-%d %H:%M', ctime),
file[A_NAME],
linktarget)))
def update_pwd(self, directory):
self.pwd = directory
self.prompt = self.fs_name + ":" + self.pwd + "$ "
def do_cd(self, args):
"""
Changes the current directory.\nUsage: cd <target directory>
"""
# count the number of arguments
# 1 or more arguments: changes the directory to the first arg
# and ignores the rest
# 0 arguments: changes to '/'
arguments = args.split()
if not len(arguments):
self.update_pwd("/")
else:
relative_dir = arguments[0]
target_dir = resolve_reference(self.pwd, relative_dir)
if exists(self.fs, target_dir) == False:
print(("cd: %s: No such file or directory" % target_dir))
elif is_directory(self.fs, target_dir):
self.update_pwd(target_dir)
else:
print(("cd: %s: Not a directory" % target_dir))
def do_pwd(self, args):
"""
Prints the current working directory
:param args:
:return:
"""
print((self.pwd))
def do_mkdir(self, args):
"""
Add a new directory in the target directory.
Handles relative or absolute file paths. \n
Usage: mkdir <destination>...
"""
arg_list = args.split()
if len(arg_list) < 1:
print("usage: mkdir <new directory> <new directory>...")
else:
for arg in arg_list:
self.mkfile(arg.split(), T_DIR)
def do_touch(self, args):
"""
Add a new file in the target directory.
Handles relative or absolute file paths. \n
Usage: touch <destination> [<size in bytes>]
"""
arg_list = args.split()
if len(arg_list) < 1:
print('Usage: touch <destination> (<size in bytes>)')
else:
self.mkfile(arg_list, T_FILE)
def mkfile(self, args, file_type):
"""
args must be a list of arguments
"""
cwd = self.fs
path = resolve_reference(self.pwd, args[0])
pathList = path.split('/')
parentdir = '/'.join(pathList[:-1])
fileName = pathList[len(pathList) - 1]
if not exists(self.fs, parentdir):
print((('Parent directory %s doesn\'t exist!') % \
(parentdir,)))
self.mkfile(parentdir.split(), T_DIR)
if exists(self.fs, path):
print(('Error: %s already exists!' % (path,)))
return
cwd = getpath(self.fs, parentdir)
# get uid, gid, mode from parent
uid = cwd[A_UID]
gid = cwd[A_GID]
mode = cwd[A_MODE]
# create default file/directory size if none is specified
if len(args) == 1:
size = 4096
else:
size = args[1]
# set the last update time stamp to now
ctime = time.time()
cwd[A_CONTENTS].append(
[fileName, file_type, uid, gid, size, mode, ctime, [], None, None])
self.save_pickle()
print(("Added '%s'" % path))
def do_rm(self, arguments):
"""
Remove an object from the file system.
Will not remove a directory unless the -r switch is invoked.\n
Usage: rm [-r] <target>
"""
args = arguments.split()
if len(args) < 1 or len(args) > 2:
print('Usage: rm [-r] <target>')
return
if len(args) == 2 and args[0] != "-r":
print('Usage: rm [-r] <target>')
return
if len(args) == 1:
target_path = resolve_reference(self.pwd, args[0])
else:
target_path = resolve_reference(self.pwd, args[1])
if exists(self.fs, target_path) == False:
print(("File \'%s\' doesn\'t exist" % (target_path,)))
return
if target_path == "/":
print("rm: cannot delete root directory '/'")
return
target_object = getpath(self.fs, target_path)
if target_object[A_TYPE] == T_DIR and args[0] != "-r":
print(("rm: cannot remove '%s': Is a directory" % (target_path,)))
return
parent_path = '/'.join(target_path.split('/')[:-1])
parent_object = getpath(self.fs, parent_path)
parent_object[A_CONTENTS].remove(target_object)
self.save_pickle()
print(("Deleted %s" % target_path))
def do_rmdir(self, arguments):
"""
Remove a file object. Like the unix command,
this can only delete empty directories.
Use rm -r to recursively delete full directories.\n
Usage: rmdir <target directory>
"""
args = arguments.split()
if len(args) != 1:
print('Usage: rmdir <target>')
return
target_path = resolve_reference(self.pwd, args[0])
if exists(self.fs, target_path) == False:
print(("File \'%s\' doesn\'t exist" % (target_path,)))
return
target_object = getpath(self.fs, target_path)
if target_object[A_TYPE] != T_DIR:
print(("rmdir: failed to remove '%s': Not a directory" % \
(target_path,)))
return
# The unix rmdir command does not delete directories if they are not
# empty
if len(target_object[A_CONTENTS]) != 0:
print(("rmdir: failed to remove '%s': Directory not empty" % \
(target_path,)))
return
parent_path = '/'.join(target_path.split('/')[:-1])
parent_object = getpath(self.fs, parent_path)
parent_object[A_CONTENTS].remove(target_object)
self.save_pickle()
if self.pwd == target_path:
self.do_cd("..")
print(("Deleted %s" % target_path))
def do_mv(self, arguments):
"""
Moves a file/directory from one directory to another.\n
Usage: mv <source file> <destination file>
"""
args = arguments.split()
if len(args) != 2:
print('Usage: mv <source> <destination>')
return
src = resolve_reference(self.pwd, args[0])
dst = resolve_reference(self.pwd, args[1])
if src == "/":
print("mv: cannot move the root directory '/'")
return
src = src.strip('/')
dst = dst.strip('/')
if not exists(self.fs, src):
print(("Source file \'%s\' does not exist!" % src))
return
# Get the parent directory of the source file
# srcparent = '/'.join(src.split('/')[:-1])
srcparent = "/".join(src.split('/')[:-1])
# Get the object for source
srcl = getpath(self.fs, src)
# Get the object for the source's parent
srcparentl = getpath(self.fs, srcparent)
# if the specified filepath is a directory, maintain the current name
if exists(self.fs, dst) and is_directory(self.fs, dst):
dstparent = dst
dstname = srcl[A_NAME]
else:
dstparent = '/'.join(dst.split('/')[:-1])
dstname = dst.split('/')[-1]
if exists(self.fs, dstparent + '/' + dstname):
print(("A file already exists at " + dst + "!"))
return
if not exists(self.fs, dstparent):
print(('Destination directory \'%s\' doesn\'t exist!' % dst))
return
if src == self.pwd:
self.do_cd("..")
dstparentl = getpath(self.fs, dstparent)
copy = srcl[:]
copy[A_NAME] = dstname
dstparentl[A_CONTENTS].append(copy)
srcparentl[A_CONTENTS].remove(srcl)
self.save_pickle()
print(('File moved from /%s to /%s' % (src, dst)))
def do_cp(self, arguments):
"""
Copies a file/directory from one directory to another.\n
Usage: cp <source file> <destination file>
"""
args = arguments.split()
if len(args) != 2:
print('Usage: cp <source> <destination>')
return
# src, dst = args[0], args[1]
src = resolve_reference(self.pwd, args[0])
dst = resolve_reference(self.pwd, args[1])
src = src.strip('/')
dst = dst.strip('/')
if not exists(self.fs, src):
print(("Source file '%s' does not exist!" % (src,)))
return
# Get the parent directory of the source file
srcparent = '/'.join(src.split('/')[:-1])
# Get the object for source
srcl = getpath(self.fs, src)
# Get the object for the source's parent
srcparentl = getpath(self.fs, srcparent)
# if the specified filepath is a directory, maintain the current name
if exists(self.fs, dst) and is_directory(self.fs, dst):
dstparent = dst
dstname = srcl[A_NAME]
else:
dstparent = '/'.join(dst.split('/')[:-1])
dstname = dst.split('/')[-1]
if exists(self.fs, dstparent + '/' + dstname):
print(('A file already exists at %s/%s!' % (dstparent, dstname)))
return
if not exists(self.fs, dstparent):
print(('Destination directory %s doesn\'t exist!' % (dstparent,)))
return
dstparentl = getpath(self.fs, dstparent)
coppy = copy.deepcopy(srcl)
coppy[A_NAME] = dstname
dstparentl[A_CONTENTS].append(coppy)
self.save_pickle()
print(('File copied from /%s to /%s/%s' % (src, dstparent, dstname)))
def do_chown(self, args):
"""
Change file ownership
"""
arg_list = args.split()
if len(arg_list) != 2:
print("Incorrect number of arguments.\nUsage: chown <uid> <file>")
return
uid = arg_list[0]
target_path = resolve_reference(self.pwd, arg_list[1])
if not exists(self.fs, target_path):
print(("File '%s' doesn't exist." % target_path))
return
target_object = getpath(self.fs, target_path)
olduid = target_object[A_UID]
target_object[A_UID] = int(uid)
print(("former UID: " + str(olduid) + ". New UID: " + str(uid)))
self.save_pickle()
def do_chgrp(self, args):
"""
Change file ownership
"""
arg_list = args.split()
if len(arg_list) != 2:
print("Incorrect number of arguments.\nUsage: chgrp <gid> <file>")
return
gid = arg_list[0]
target_path = resolve_reference(self.pwd, arg_list[1])
if not exists(self.fs, target_path):
print(("File '%s' doesn't exist." % target_path))
return
target_object = getpath(self.fs, target_path)
oldgid = target_object[A_GID]
target_object[A_GID] = int(gid)
print(("former GID: " + str(oldgid) + ". New GID: " + str(gid)))
self.save_pickle()
def do_chmod(self, args):
"""
Change file permissions
only modes between 000 and 777 are implemented
"""
arg_list = args.split()
if len(arg_list) != 2:
print("Incorrect number of arguments.\nUsage: chmod <mode> <file>")
return
mode = arg_list[0]
target_path = resolve_reference(self.pwd, arg_list[1])
if not exists(self.fs, target_path):
print("File '%s' doesn't exist." % target_path)
return
target_object = getpath(self.fs, target_path)
oldmode = target_object[A_MODE]
if target_object[A_TYPE] == T_LINK:
print(target_path + " is a link, nothing changed.")
return
try:
num = int(mode, 8)
except:
print("Incorrect mode: " + mode)
return
if num < 0 or num > 511:
print("Incorrect mode: " + mode)
return
target_object[A_MODE] = (oldmode & 0o7777000) | (num & 0o777)
self.save_pickle()
def do_file(self, args):
"""
Identifies file types.\nUsage: file <file name>
"""
arg_list = args.split()
if len(arg_list) != 1:
print("Incorrect number of arguments.\nUsage: file <file>")
return
target_path = resolve_reference(self.pwd, arg_list[0])
if not exists(self.fs, target_path):
print("File '%s' doesn't exist." % target_path)
return
target_object = getpath(self.fs, target_path)
file_type = target_object[A_TYPE]
if file_type == T_FILE:
msg = "normal file object"
elif file_type == T_DIR:
msg = "directory"
elif file_type == T_LINK:
msg = "link"
elif file_type == T_BLK:
msg = "block file"
elif file_type == T_CHR:
msg = "character special"
elif file_type == T_SOCK:
msg = "socket"
elif file_type == T_FIFO:
msg = "named pipe"
else:
msg = "unrecognized file"
print(target_path + " is a " + msg)
def do_clear(self, args):
"""
Clears the screen
"""
os.system('clear')
def emptyline(self):
"""
By default the cmd object will repeat the last command
if a blank line is entered. Since this is different than
bash behavior, overriding this method will stop it.
"""
pass
def help_help(self):
print("Type help <topic> to get more information.")
def help_about(self):
print("Kippo/Cowrie stores information about its file systems in a " + \
"series of nested lists. Once the lists are made, they are " + \
"stored in a pickle file on the hard drive. Every time cowrie " + \
"gets a new client, it reads from the pickle file and loads " + \
"the fake file system into memory. By default this file " + \
"is /opt/cowrie/data/fs.pickle. Originally the script " + \
"/opt/cowrie/bin/createfs was used to copy the file system " + \
"of the existing computer. However, it quite difficult to " + \
"edit the pickle file by hand.\n\nThis script strives to be " + \
"a bash-like interface that allows users to modify " + \
"existing fs pickle files. It supports many of the " + \
"common bash commands and even handles relative file " + \
"paths. Keep in mind that you need to restart the " + \
"cowrie process in order for the new file system to be " + \
"reloaded into memory.\n\nDonovan Hubbard, Douglas Hubbard, " + \
"March 2013\nVersion 1.0")
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: %s <fs.pickle>" % os.path.basename(sys.argv[0], ))
sys.exit(1)
pickle_file_name = sys.argv[1].strip()
print(pickle_file_name)
fseditCmd(pickle_file_name).cmdloop()