Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pyrasite
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
pyrasite
Commits
eab58d17
Commit
eab58d17
authored
Feb 11, 2012
by
Luke Macken
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add some useful code to help with subprocess & logging from the python-script code.
https://github.com/wcmaier/python-script
parent
f9c55435
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
72 additions
and
127 deletions
+72
-127
pyrasite/utils.py
pyrasite/utils.py
+72
-127
No files found.
pyrasite/utils.py
View file @
eab58d17
# This file is part of pyrasite.
# Some useful functions based on code from Will Maier's 'ideal Python script'
# https://github.com/wcmaier/python-script
#
#
# pyrasite is free software: you can redistribute it and/or modify
# Copyright (c) 2010 Will Maier <willmaier@ml1.net>
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
#
# pyrasite is distributed in the hope that it will be useful,
# Permission to use, copy, modify, and distribute this software for any
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# purpose with or without fee is hereby granted, provided that the above
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# copyright notice and this permission notice appear in all copies.
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# along with pyrasite. If not, see <http://www.gnu.org/licenses/>.
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
#
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# Copyright (C) 2011 Red Hat, Inc.
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
import
os
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
import
socket
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import
struct
import
pyrasite
import
logging
import
tempfile
import
warnings
import
traceback
import
subprocess
import
subprocess
def
run
(
cmd
):
def
run
(
*
args
,
**
kwargs
):
p
=
subprocess
.
Popen
(
cmd
,
shell
=
True
,
"""Run a subprocess.
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
out
,
err
=
p
.
communicate
()
if
err
:
warnings
.
warn
(
err
)
return
out
.
strip
()
REVERSE_SHELL
=
"""
\
import sys, struct
sys.path.insert(0, "%s/../payloads/")
from StringIO import StringIO
Returns a tuple (*process*, *stdout*, *stderr*). If the *communicate*
from _reverseconnection import ReverseConnection
keyword argument is True, *stdout* and *stderr* will be strings.
Otherwise, they will be None. *process* is a :class:`subprocess.Popen`
instance. By default, the path to the script itself will be used as the
executable and *args* will be passed as arguments to it.
class ReversePythonShell(ReverseConnection):
.. note::
host = 'localhost'
The value of *executable* will be prepended to *args*.
port = %d
def on_command(self, s, cmd):
:param args: arguments to be passed to :class:`subprocess.Popen`.
buffer = StringIO()
:param kwargs: keyword arguments to be passed to :class:`subprocess.Popen`.
sys.stdout = buffer
:param communicate: if True, call :meth:`subprocess.Popen.communicate` after creating the subprocess.
sys.stderr = buffer
:param executable: if present, the path to a program to execute instead of this script.
output = ''
try:
exec(cmd)
output = buffer.getvalue()
except Exception, e:
output = str(e)
finally:
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
buffer.close()
header = struct.pack('<L', len(output))
s.sendall(header + output)
return True
ReversePythonShell().start()
"""
class
PyrasiteIPC
(
object
):
"""
An object that listens for connections from the reverse python shell payload,
and then allows you to run commands in the other process.
"""
"""
def
__init__
(
self
,
pid
):
_kwargs
=
{
super
(
PyrasiteIPC
,
self
).
__init__
()
"stdin"
:
subprocess
.
PIPE
,
self
.
pid
=
pid
"stdout"
:
subprocess
.
PIPE
,
self
.
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
"stderr"
:
subprocess
.
PIPE
,
self
.
sock
.
settimeout
(
5
)
"shell"
:
True
,
self
.
sock
.
bind
((
'localhost'
,
0
))
}
self
.
sock
.
listen
(
20
)
communicate
=
kwargs
.
pop
(
"communicate"
,
True
)
self
.
port
=
self
.
sock
.
getsockname
()[
1
]
_kwargs
.
update
(
kwargs
)
self
.
client
=
None
kwargs
=
_kwargs
self
.
running
=
True
process
=
subprocess
.
Popen
(
args
,
**
kwargs
)
def
inject
(
self
):
if
communicate
is
True
:
# Write out a reverse subprocess payload with a custom port
stdout
,
stderr
=
process
.
communicate
()
(
fd
,
filename
)
=
tempfile
.
mkstemp
()
else
:
self
.
filename
=
filename
stdout
,
stderr
=
None
,
None
tmp
=
os
.
fdopen
(
fd
,
'w'
)
tmp
.
write
(
REVERSE_SHELL
%
(
return
process
,
stdout
,
stderr
os
.
path
.
abspath
(
os
.
path
.
dirname
(
pyrasite
.
__file__
)),
self
.
port
))
tmp
.
close
()
def
setup_logger
(
verbose
=
False
):
# NullHandler was added in Python 3.1.
injector
=
pyrasite
.
CodeInjector
(
self
.
pid
)
try
:
injector
.
inject
(
filename
)
NullHandler
=
logging
.
NullHandler
except
AttributeError
:
def
listen
(
self
):
class
NullHandler
(
logging
.
Handler
):
(
clientsocket
,
address
)
=
self
.
sock
.
accept
()
def
emit
(
self
,
record
):
pass
self
.
client
=
clientsocket
self
.
client
.
settimeout
(
3
)
# Add a do-nothing NullHandler to the module logger to prevent "No handlers
# could be found" errors. The calling code can still add other, more useful
def
cmd
(
self
,
cmd
):
# handlers, or otherwise configure logging.
self
.
client
.
sendall
(
cmd
+
'
\
n
'
)
log
=
logging
.
getLogger
(
'pyrasite'
)
try
:
log
.
addHandler
(
NullHandler
())
header_data
=
self
.
_recv_bytes
(
4
)
if
len
(
header_data
)
==
4
:
level
=
logging
.
INFO
msg_len
=
struct
.
unpack
(
'<L'
,
header_data
)[
0
]
if
verbose
:
data
=
self
.
_recv_bytes
(
msg_len
)
level
=
logging
.
DEBUG
if
len
(
data
)
==
msg_len
:
return
data
handler
=
logging
.
StreamHandler
()
else
:
handler
.
setFormatter
(
logging
.
Formatter
(
'%(message)s'
))
print
(
"Response doesn't match header len (%s) : %r"
%
(
handler
.
setLevel
(
level
)
msg_len
,
data
))
log
.
addHandler
(
handler
)
except
:
log
.
setLevel
(
level
)
traceback
.
print_exc
()
self
.
close
()
return
log
def
_recv_bytes
(
self
,
n
):
data
=
''
while
len
(
data
)
<
n
:
chunk
=
self
.
client
.
recv
(
n
-
len
(
data
))
if
chunk
==
''
:
break
data
+=
chunk
return
data
def
close
(
self
):
os
.
unlink
(
self
.
filename
)
if
self
.
client
:
self
.
client
.
sendall
(
'exit
\
n
'
)
self
.
client
.
close
()
def
__repr__
(
self
):
return
"<%s %s>"
%
(
self
.
__class__
.
__name__
,
self
.
pid
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment