CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/adb/message.rb
Views: 11704
1
# -*- coding: binary -*-
2
3
##
4
# ADB protocol support
5
##
6
7
module Rex
8
module Proto
9
module ADB
10
11
# A Message for the ADB protocol. For documentation see:
12
# https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
13
class Message
14
15
WORD_WIDTH = 4 # bytes
16
WORD_PACK = 'L<'
17
18
attr_accessor :command
19
attr_accessor :arg0
20
attr_accessor :arg1
21
attr_accessor :data
22
23
def initialize(arg0, arg1, data)
24
self.command = self.class::COMMAND if defined?(self.class::COMMAND)
25
self.arg0 = arg0
26
self.arg1 = arg1
27
self.data = data + "\0"
28
end
29
30
def data_check
31
# this check is implemented in adb/transport.cpp, in the send_packet method.
32
# it is not crc32 as the docs make it appear, it is just a 32bit sum.
33
data.bytes.inject(&:+) & 0xffffffff
34
end
35
36
def magic
37
command_word ^ 0xffffffff
38
end
39
40
def command_word
41
command.unpack(WORD_PACK)[0]
42
end
43
44
def send_recv(socket)
45
socket.print self.serialize
46
Message.read socket
47
end
48
49
def serialize
50
[
51
command_word,
52
arg0,
53
arg1,
54
data.bytes.length,
55
data_check,
56
magic
57
].pack(WORD_PACK+'*') + data
58
end
59
60
def to_s
61
[
62
"command=#{command}",
63
"arg0=0x#{arg0.to_s(16)}",
64
"arg1=0x#{arg1.to_s(16)}",
65
"data=#{data}"
66
].join("\n")
67
end
68
69
def self.read(socket)
70
header = socket.recvfrom(6 * WORD_WIDTH)[0]
71
command = header[0, WORD_WIDTH]
72
arg0 = header[WORD_WIDTH, WORD_WIDTH].unpack(WORD_PACK)[0]
73
arg1 = header[WORD_WIDTH*2, WORD_WIDTH].unpack(WORD_PACK)[0]
74
payload_len = header[WORD_WIDTH*3, WORD_WIDTH].unpack(WORD_PACK)[0]
75
payload = socket.recvfrom(payload_len)[0]
76
77
klass = MESSAGE_TYPES.find { |klass| klass::COMMAND == command }
78
if klass.nil?
79
raise "Invalid adb command: #{command}"
80
end
81
82
message = klass.allocate
83
message.command = command
84
message.arg0 = arg0
85
message.arg1 = arg1
86
message.data = payload
87
message
88
end
89
90
#
91
# Subclasses inside Message:: namespace for specific message types
92
#
93
94
class Connect < Message
95
COMMAND = "CNXN"
96
DEFAULT_VERSION = 0x01000000
97
DEFAULT_MAXDATA = 4096
98
DEFAULT_IDENTITY = "host::"
99
100
def initialize(version=DEFAULT_VERSION,
101
maxdata=DEFAULT_MAXDATA,
102
system_identity_string=DEFAULT_IDENTITY)
103
super
104
end
105
end
106
107
class Auth < Message
108
COMMAND = "AUTH"
109
TYPE_TOKEN = 1
110
TYPE_SIGNATURE = 2
111
112
def initialize(type, data)
113
super(type, 0, data)
114
end
115
end
116
117
class Open < Message
118
COMMAND = "OPEN"
119
120
def initialize(local_id, destination)
121
super(local_id, 0, destination)
122
end
123
end
124
125
class Ready < Message
126
COMMAND = "OKAY"
127
128
def initialize(local_id, remote_id)
129
super(local_id, remote_id, "")
130
end
131
end
132
133
class Write < Message
134
COMMAND = "WRTE"
135
136
def initialize(local_id, remote_id, data)
137
super
138
end
139
end
140
141
class Close < Message
142
COMMAND = "CLSE"
143
144
def initialize(local_id, remote_id)
145
super(local_id, remote_id, "")
146
end
147
end
148
149
class Sync < Message
150
COMMAND = "SYNC"
151
152
def initialize(online, sequence)
153
super(online, sequence, "")
154
end
155
end
156
157
# Avoid a dependency on Rails's nice Class#subclasses
158
MESSAGE_TYPES = [Connect, Auth, Open, Ready, Write, Close, Sync]
159
160
end # Message
161
162
end # ADB
163
end # Proto
164
end # Rex
165
166