@@ -18,11 +18,10 @@ module Exploit::Remote::Gdb
18
18
# Default list of supported GDB features to send the to the target
19
19
GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;'
20
20
21
- # Maps arch -> index of register in GDB that holds $PC
21
+ # Maps index of register in GDB that holds $PC to architecture
22
22
PC_REGISTERS = {
23
- ARCH_X86 => '08' ,
24
- ARCH_X64 => '10' ,
25
- ARCH_X86_64 => '10'
23
+ '08' => ARCH_X86 ,
24
+ '10' => ARCH_X86_64
26
25
}
27
26
28
27
# Send an ACK packet
@@ -32,7 +31,7 @@ def send_ack
32
31
end
33
32
34
33
# 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
36
35
def read_ack
37
36
unless sock . get_once == '+'
38
37
raise 'received bad ack'
@@ -85,17 +84,6 @@ def checksum(str)
85
84
"%02x" % str . bytes . inject ( 0 ) { |b , sum | ( sum +b ) %256 }
86
85
end
87
86
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
-
99
87
# Writes the buffer +buf+ to the address +addr+ in the remote process's memory
100
88
# @param buf [String] the buffer to write
101
89
# @param addr [String] the hex-encoded address to write to
@@ -105,6 +93,24 @@ def write(buf, addr)
105
93
read_response
106
94
end
107
95
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
+
108
114
# Continues execution of the remote process
109
115
# @param opts [Hash] the options hash
110
116
# @option opts :read [Boolean] read the response
@@ -114,6 +120,13 @@ def continue(opts={})
114
120
end
115
121
116
122
# 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
+ #
117
130
# @return [String] a list of key/value pairs, including current PC
118
131
def step
119
132
send_cmd 'vCont;s'
@@ -129,13 +142,6 @@ def handshake(features=GDB_FEATURES)
129
142
read_response # lots of flags, nothing interesting
130
143
end
131
144
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
-
139
145
end
140
146
141
147
end
0 commit comments